w-orm-lmdb 1.0.19 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -523,7 +523,7 @@ err為錯誤訊息字串,內容與正規管道所送出者一致。
523
523
 
524
524
  <dt class="tag-source">Source:</dt>
525
525
  <dd class="tag-source"><ul class="dummy"><li>
526
- <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line714">line 714</a>
526
+ <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line777">line 777</a>
527
527
  </li></ul></dd>
528
528
 
529
529
 
@@ -684,7 +684,7 @@ err為錯誤訊息字串,內容與正規管道所送出者一致。
684
684
 
685
685
  <dt class="tag-source">Source:</dt>
686
686
  <dd class="tag-source"><ul class="dummy"><li>
687
- <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line845">line 845</a>
687
+ <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line913">line 913</a>
688
688
  </li></ul></dd>
689
689
 
690
690
 
@@ -846,7 +846,7 @@ err為錯誤訊息字串,內容與正規管道所送出者一致。
846
846
 
847
847
 
848
848
 
849
- <h4 class="name" id=".insert"><span class="type-signature type-signature-async, static">(async, static) </span>insert<span class="signature">(data)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
849
+ <h4 class="name" id=".insert"><span class="type-signature type-signature-async, static">(async, static) </span>insert<span class="signature">(data, option<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
850
850
 
851
851
 
852
852
 
@@ -862,7 +862,7 @@ err為錯誤訊息字串,內容與正規管道所送出者一致。
862
862
 
863
863
  <dt class="tag-source">Source:</dt>
864
864
  <dd class="tag-source"><ul class="dummy"><li>
865
- <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line325">line 325</a>
865
+ <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line349">line 349</a>
866
866
  </li></ul></dd>
867
867
 
868
868
 
@@ -922,8 +922,12 @@ err為錯誤訊息字串,內容與正規管道所送出者一致。
922
922
  <th>Type</th>
923
923
 
924
924
 
925
+ <th>Attributes</th>
926
+
925
927
 
926
928
 
929
+ <th>Default</th>
930
+
927
931
 
928
932
  <th class="last">Description</th>
929
933
  </tr>
@@ -951,13 +955,135 @@ err為錯誤訊息字串,內容與正規管道所送出者一致。
951
955
  </td>
952
956
 
953
957
 
958
+ <td class="attributes">
959
+
960
+
961
+
962
+
963
+
964
+ </td>
965
+
954
966
 
955
967
 
968
+ <td class="default">
969
+
970
+ </td>
971
+
956
972
 
957
973
  <td class="description last"><p>輸入數據物件或陣列</p></td>
958
974
  </tr>
959
975
 
960
976
 
977
+
978
+ <tr>
979
+
980
+ <td class="name"><code>option</code></td>
981
+
982
+
983
+ <td class="type">
984
+
985
+
986
+ <span class="param-type">Object</span>
987
+
988
+
989
+
990
+
991
+ </td>
992
+
993
+
994
+ <td class="attributes">
995
+
996
+ &lt;optional><br>
997
+
998
+
999
+
1000
+
1001
+
1002
+ </td>
1003
+
1004
+
1005
+
1006
+ <td class="default">
1007
+
1008
+ <code>{}</code>
1009
+
1010
+ </td>
1011
+
1012
+
1013
+ <td class="description last"><p>輸入設定物件,預設為{}</p>
1014
+ <h6>Properties</h6>
1015
+
1016
+
1017
+ <table class="params">
1018
+ <thead>
1019
+ <tr>
1020
+
1021
+ <th>Name</th>
1022
+
1023
+
1024
+ <th>Type</th>
1025
+
1026
+
1027
+ <th>Attributes</th>
1028
+
1029
+
1030
+
1031
+ <th>Default</th>
1032
+
1033
+
1034
+ <th class="last">Description</th>
1035
+ </tr>
1036
+ </thead>
1037
+
1038
+ <tbody>
1039
+
1040
+
1041
+ <tr>
1042
+
1043
+ <td class="name"><code>returnList</code></td>
1044
+
1045
+
1046
+ <td class="type">
1047
+
1048
+
1049
+ <span class="param-type">Boolean</span>
1050
+
1051
+
1052
+
1053
+
1054
+ </td>
1055
+
1056
+
1057
+ <td class="attributes">
1058
+
1059
+ &lt;optional><br>
1060
+
1061
+
1062
+
1063
+
1064
+
1065
+ </td>
1066
+
1067
+
1068
+
1069
+ <td class="default">
1070
+
1071
+ <code>false</code>
1072
+
1073
+ </td>
1074
+
1075
+
1076
+ <td class="description last"><p>輸入是否改回傳逐筆結果布林值,預設false。給true時回傳與輸入等長保序之陣列,各筆為{n,nInserted,ok},nInserted為1即該筆為新增;聚合計數只回答有幾筆是新的,逐筆結果方能回答是哪幾筆,供下游僅對新資料執行昂貴動作。回傳形式由呼叫點靜態決定,共用之結果處理程式碼不可跨不同取值之呼叫點混用</p></td>
1077
+ </tr>
1078
+
1079
+
1080
+ </tbody>
1081
+ </table>
1082
+
1083
+ </td>
1084
+ </tr>
1085
+
1086
+
961
1087
  </tbody>
962
1088
  </table>
963
1089
 
@@ -980,7 +1106,7 @@ err為錯誤訊息字串,內容與正規管道所送出者一致。
980
1106
 
981
1107
 
982
1108
  <div class="param-desc">
983
- <p>回傳Promise,resolve回傳插入結果物件{n,nInserted,ok},n為輸入筆數、nInserted為實際插入筆數,reject回傳錯誤訊息</p>
1109
+ <p>回傳Promise,resolve依returnList回傳插入結果:預設回傳聚合物件{n,nInserted,ok},n為輸入筆數、nInserted為實際插入筆數;returnList為true時回傳逐筆陣列,各筆n恆為1(主鍵命中或經插入)、ok恆為1(insert之錯誤皆屬整批性而reject,不進逐筆);reject回傳錯誤訊息</p>
984
1110
  </div>
985
1111
 
986
1112
 
@@ -1027,7 +1153,7 @@ err為錯誤訊息字串,內容與正規管道所送出者一致。
1027
1153
 
1028
1154
  <dt class="tag-source">Source:</dt>
1029
1155
  <dd class="tag-source"><ul class="dummy"><li>
1030
- <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line421">line 421</a>
1156
+ <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line474">line 474</a>
1031
1157
  </li></ul></dd>
1032
1158
 
1033
1159
 
@@ -1188,7 +1314,7 @@ err為錯誤訊息字串,內容與正規管道所送出者一致。
1188
1314
 
1189
1315
  <dt class="tag-source">Source:</dt>
1190
1316
  <dd class="tag-source"><ul class="dummy"><li>
1191
- <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line513">line 513</a>
1317
+ <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line571">line 571</a>
1192
1318
  </li></ul></dd>
1193
1319
 
1194
1320
 
@@ -1475,7 +1601,7 @@ err為錯誤訊息字串,內容與正規管道所送出者一致。
1475
1601
 
1476
1602
  <dt class="tag-source">Source:</dt>
1477
1603
  <dd class="tag-source"><ul class="dummy"><li>
1478
- <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line214">line 214</a>
1604
+ <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line226">line 226</a>
1479
1605
  </li></ul></dd>
1480
1606
 
1481
1607
 
@@ -1654,7 +1780,7 @@ err為錯誤訊息字串,內容與正規管道所送出者一致。
1654
1780
 
1655
1781
  <dt class="tag-source">Source:</dt>
1656
1782
  <dd class="tag-source"><ul class="dummy"><li>
1657
- <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line273">line 273</a>
1783
+ <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line290">line 290</a>
1658
1784
  </li></ul></dd>
1659
1785
 
1660
1786
 
@@ -1811,7 +1937,7 @@ err為錯誤訊息字串,內容與正規管道所送出者一致。
1811
1937
  <br class="clear">
1812
1938
 
1813
1939
  <footer>
1814
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Aug 17 2026 11:00:07 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1940
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Aug 18 2026 12:13:07 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1815
1941
  </footer>
1816
1942
 
1817
1943
  <script>prettyPrint();</script>
@@ -173,13 +173,25 @@ function WOrmLmdb(opt = {}) {
173
173
  }
174
174
 
175
175
  //waitOpen, 等待client開啟, 因getRange與get於client關閉時會拋錯
176
+ //closed為終態: LMDB env一旦關閉不會自行回到open, 續等必然逾時, 故直接拋出而非空轉至逾時
177
+ //各函數入口已有procClosed守門, 此處之終態判斷為縱深防禦, 攔[操作進行中被close]之競態
178
+ //等待參數收斂: 開啟中為毫秒級過渡, 50次x200ms=10秒已極寬裕, 不使非終態之等待拖至waitFun預設之200秒
176
179
  let waitOpen = async () => {
180
+ if (client.status === 'closed') {
181
+ throw new Error('client is closed, instance can not be used after close()')
182
+ }
177
183
  await waitFun(() => {
178
- if (client.status === 'closed') {
179
- console.log(`client.status[${client.status}], level is closed`)
180
- }
181
184
  return client.status === 'open'
182
- })
185
+ }, { attemptNum: 50, timeInterval: 200 })
186
+ }
187
+
188
+ //procClosed, 各函數入口之終態守門: close()後再操作屬整批性錯誤, 立即reject令誤用當場可見
189
+ //不可靜默回正常空值(如null或未命中), 否則[已關閉]與[查無資料]同形,
190
+ //去重類呼叫端將把每筆判為未存在而fail-open, 整批重送下游昂貴動作
191
+ let procClosed = (mode, data) => {
192
+ let msg = `can not ${mode} by closed client, instance can not be used after close()`
193
+ emitError(mode, data, msg)
194
+ return Promise.reject(new Error(msg))
183
195
  }
184
196
 
185
197
  //emitChange, 資料實際異動成功後發出, 事件僅為附加通知不承擔回傳義務
@@ -259,6 +271,11 @@ function WOrmLmdb(opt = {}) {
259
271
  * @returns {Promise} 回傳Promise,resolve回傳數據,reject回傳錯誤訊息
260
272
  */
261
273
  async function select(find = {}) {
274
+
275
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
276
+ if (client.status === 'closed') {
277
+ return procClosed('select', null)
278
+ }
262
279
  let isErr = false
263
280
  let res = null
264
281
 
@@ -318,6 +335,11 @@ function WOrmLmdb(opt = {}) {
318
335
  * @returns {Promise} 回傳Promise,resolve回傳數據物件,若無此主鍵則回傳null,reject回傳錯誤訊息
319
336
  */
320
337
  async function selectByPk(pk) {
338
+
339
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
340
+ if (client.status === 'closed') {
341
+ return procClosed('selectByPk', null)
342
+ }
321
343
  let isErr = false
322
344
  let res = null
323
345
 
@@ -367,13 +389,30 @@ function WOrmLmdb(opt = {}) {
367
389
  *
368
390
  * @memberOf WOrmLmdb
369
391
  * @param {Object|Array} data 輸入數據物件或陣列
370
- * @returns {Promise} 回傳Promise,resolve回傳插入結果物件{n,nInserted,ok},n為輸入筆數、nInserted為實際插入筆數,reject回傳錯誤訊息
392
+ * @param {Object} [option={}] 輸入設定物件,預設為{}
393
+ * @param {Boolean} [option.returnList=false] 輸入是否改回傳逐筆結果布林值,預設false。給true時回傳與輸入等長保序之陣列,各筆為{n,nInserted,ok},nInserted為1即該筆為新增;聚合計數只回答有幾筆是新的,逐筆結果方能回答是哪幾筆,供下游僅對新資料執行昂貴動作。回傳形式由呼叫點靜態決定,共用之結果處理程式碼不可跨不同取值之呼叫點混用
394
+ * @returns {Promise} 回傳Promise,resolve依returnList回傳插入結果:預設回傳聚合物件{n,nInserted,ok},n為輸入筆數、nInserted為實際插入筆數;returnList為true時回傳逐筆陣列,各筆n恆為1(主鍵命中或經插入)、ok恆為1(insert之錯誤皆屬整批性而reject,不進逐筆);reject回傳錯誤訊息
371
395
  */
372
- async function insert(data) {
396
+ async function insert(data, option = {}) {
397
+
398
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
399
+ if (client.status === 'closed') {
400
+ return procClosed('insert', data)
401
+ }
373
402
  let isErr = false
374
403
 
404
+ //returnList
405
+ let returnList = get(option, 'returnList')
406
+ if (!isbol(returnList)) {
407
+ returnList = false
408
+ }
409
+
375
410
  //check
376
411
  if (!iseobj(data) &amp;&amp; !isearr(data)) {
412
+ if (returnList) {
413
+ //輸入無效, 對齊save與del之T5規定回傳空陣列
414
+ return []
415
+ }
377
416
  return {
378
417
  n: 0,
379
418
  nInserted: 0,
@@ -422,10 +461,24 @@ function WOrmLmdb(opt = {}) {
422
461
  })
423
462
 
424
463
  //res
425
- res = {
426
- n: nAll,
427
- nInserted: nPush,
428
- ok: 1,
464
+ if (returnList) {
465
+ //逐筆結果, 與輸入等長保序, 元素沿用逐筆結果之家族形狀(同save與del之元素)
466
+ //n恆為1(主鍵命中既有或經插入而產生), ok恆為1(insert之錯誤皆屬整批性而reject, 不進逐筆),
467
+ //資訊由nInserted承載, filter(v=>v.nInserted===1)之長度必等於聚合模式之nInserted
468
+ res = map(ltdone, function(done) {
469
+ return {
470
+ n: 1,
471
+ nInserted: done ? 1 : 0,
472
+ ok: 1,
473
+ }
474
+ })
475
+ }
476
+ else {
477
+ res = {
478
+ n: nAll,
479
+ nInserted: nPush,
480
+ ok: 1,
481
+ }
429
482
  }
430
483
 
431
484
  }
@@ -466,6 +519,11 @@ function WOrmLmdb(opt = {}) {
466
519
  * @returns {Promise} 回傳Promise,resolve回傳插入結果物件{n,nInserted,ok},n為輸入筆數、nInserted成功時恆等於n,任一筆主鍵已存在則reject回傳錯誤訊息
467
520
  */
468
521
  async function insertBulk(data) {
522
+
523
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
524
+ if (client.status === 'closed') {
525
+ return procClosed('insertBulk', data)
526
+ }
469
527
  let isErr = false
470
528
 
471
529
  //check
@@ -558,6 +616,11 @@ function WOrmLmdb(opt = {}) {
558
616
  * @returns {Promise} 回傳Promise,resolve回傳與輸入等長之儲存結果陣列,各筆為{n,nInserted,nModified,ok},n為主鍵命中筆數,單筆失敗者ok為0並附err,reject回傳錯誤訊息
559
617
  */
560
618
  async function save(data, option = {}) {
619
+
620
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
621
+ if (client.status === 'closed') {
622
+ return procClosed('save', data)
623
+ }
561
624
  let isErr = false
562
625
 
563
626
  //check
@@ -759,6 +822,11 @@ function WOrmLmdb(opt = {}) {
759
822
  * @returns {Promise} 回傳Promise,resolve回傳與輸入等長之刪除結果陣列,各筆為{n,nDeleted,ok},n為主鍵命中筆數,單筆失敗或未給有效id者ok為0並附err,reject回傳錯誤訊息
760
823
  */
761
824
  async function del(data) {
825
+
826
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
827
+ if (client.status === 'closed') {
828
+ return procClosed('del', data)
829
+ }
762
830
  let isErr = false
763
831
 
764
832
  //check
@@ -890,6 +958,11 @@ function WOrmLmdb(opt = {}) {
890
958
  * @returns {Promise} 回傳Promise,resolve回傳刪除結果物件{n,nDeleted,ok},n與nDeleted同為實際刪除筆數,reject回傳錯誤訊息
891
959
  */
892
960
  async function delAll(find = {}) {
961
+
962
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
963
+ if (client.status === 'closed') {
964
+ return procClosed('delAll', null)
965
+ }
893
966
  let isErr = false
894
967
 
895
968
  //res
@@ -992,7 +1065,8 @@ function WOrmLmdb(opt = {}) {
992
1065
  return res
993
1066
  }
994
1067
 
995
- //close, 關閉內部LMDB env並釋放檔案鎖, close後該實例即報廢, 須重新new WOrmLmdb
1068
+ //close, 關閉內部LMDB env並釋放檔案鎖, close後該實例即報廢, 須重新new WOrmLmdb,
1069
+ //再呼叫任何操作函數將立即reject(訊息明示closed), 不與[查無資料]同形
996
1070
  let close = async () => {
997
1071
  if (client &amp;&amp; client.status !== 'closed') {
998
1072
  await client.close() //lmdb root database之close(), 回傳Promise
@@ -1028,7 +1102,7 @@ export default WOrmLmdb
1028
1102
  <br class="clear">
1029
1103
 
1030
1104
  <footer>
1031
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Aug 17 2026 11:00:07 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1105
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Aug 18 2026 12:13:07 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1032
1106
  </footer>
1033
1107
 
1034
1108
  <script>prettyPrint();</script>
package/docs/index.html CHANGED
@@ -71,7 +71,7 @@
71
71
  <br class="clear">
72
72
 
73
73
  <footer>
74
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Aug 17 2026 11:00:07 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
74
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Aug 18 2026 12:13:07 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
75
75
  </footer>
76
76
 
77
77
  <script>prettyPrint();</script>
package/g-basic.mjs CHANGED
@@ -180,10 +180,21 @@ async function test() {
180
180
  let sb2 = await wo.select()
181
181
  console.log('ids after insertBulk', _.map(_.sortBy(sb2, 'id'), 'id'))
182
182
 
183
+ //insert by returnList, 回傳與輸入等長保序之逐筆結果, nInserted為1即該筆為新增
184
+ //聚合計數只回答有幾筆是新的, 逐筆結果方能回答是哪幾筆, 供下游僅對新資料執行昂貴動作
185
+ let rl = await wo.insert([{ id: 'id-peter', name: 'dup' }, { id: 'id-new1', name: 'new1' }], { returnList: true })
186
+ console.log('insert by returnList', rl)
187
+
188
+ //filter, 以逐筆結果對位取出新增之數據
189
+ let fresh = [{ id: 'id-peter', name: 'dup' }, { id: 'id-new1', name: 'new1' }].filter(function(v, i) {
190
+ return rl[i].nInserted === 1
191
+ })
192
+ console.log('fresh by returnList', _.map(fresh, 'id'))
193
+
183
194
  }
184
195
  test()
185
196
  // change delAll
186
- // delAll then { n: 2, nDeleted: 2, ok: 1 }
197
+ // delAll then { n: 5, nDeleted: 5, ok: 1 }
187
198
  // change insert
188
199
  // insert then { n: 3, nInserted: 3, ok: 1 }
189
200
  // change save
@@ -236,6 +247,9 @@ test()
236
247
  // error insertBulk can not insertBulk by existed id[id-peter]
237
248
  // insertBulk by data with existed id catch Error: can not insertBulk by existed id[id-peter]
238
249
  // ids after insertBulk [ 'id-bulk1', 'id-bulk2', 'id-peter', 'id-rosemary' ]
250
+ // change insert
251
+ // insert by returnList [ { n: 1, nInserted: 0, ok: 1 }, { n: 1, nInserted: 1, ok: 1 } ]
252
+ // fresh by returnList [ 'id-new1' ]
239
253
 
240
254
 
241
255
  //node g-basic.mjs
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "w-orm-lmdb",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "main": "dist/w-orm-lmdb.umd.js",
5
5
  "dependencies": {
6
6
  "lmdb": "^3.5.6",
7
- "mingo": "^7.2.2",
8
- "wsemi": "^1.8.70"
7
+ "mingo": "^7.2.4",
8
+ "wsemi": "^1.8.73"
9
9
  },
10
10
  "devDependencies": {
11
11
  "w-package-tools": "^1.1.12"
package/src/WOrmLmdb.mjs CHANGED
@@ -126,13 +126,25 @@ function WOrmLmdb(opt = {}) {
126
126
  }
127
127
 
128
128
  //waitOpen, 等待client開啟, 因getRange與get於client關閉時會拋錯
129
+ //closed為終態: LMDB env一旦關閉不會自行回到open, 續等必然逾時, 故直接拋出而非空轉至逾時
130
+ //各函數入口已有procClosed守門, 此處之終態判斷為縱深防禦, 攔[操作進行中被close]之競態
131
+ //等待參數收斂: 開啟中為毫秒級過渡, 50次x200ms=10秒已極寬裕, 不使非終態之等待拖至waitFun預設之200秒
129
132
  let waitOpen = async () => {
133
+ if (client.status === 'closed') {
134
+ throw new Error('client is closed, instance can not be used after close()')
135
+ }
130
136
  await waitFun(() => {
131
- if (client.status === 'closed') {
132
- console.log(`client.status[${client.status}], level is closed`)
133
- }
134
137
  return client.status === 'open'
135
- })
138
+ }, { attemptNum: 50, timeInterval: 200 })
139
+ }
140
+
141
+ //procClosed, 各函數入口之終態守門: close()後再操作屬整批性錯誤, 立即reject令誤用當場可見
142
+ //不可靜默回正常空值(如null或未命中), 否則[已關閉]與[查無資料]同形,
143
+ //去重類呼叫端將把每筆判為未存在而fail-open, 整批重送下游昂貴動作
144
+ let procClosed = (mode, data) => {
145
+ let msg = `can not ${mode} by closed client, instance can not be used after close()`
146
+ emitError(mode, data, msg)
147
+ return Promise.reject(new Error(msg))
136
148
  }
137
149
 
138
150
  //emitChange, 資料實際異動成功後發出, 事件僅為附加通知不承擔回傳義務
@@ -212,6 +224,11 @@ function WOrmLmdb(opt = {}) {
212
224
  * @returns {Promise} 回傳Promise,resolve回傳數據,reject回傳錯誤訊息
213
225
  */
214
226
  async function select(find = {}) {
227
+
228
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
229
+ if (client.status === 'closed') {
230
+ return procClosed('select', null)
231
+ }
215
232
  let isErr = false
216
233
  let res = null
217
234
 
@@ -271,6 +288,11 @@ function WOrmLmdb(opt = {}) {
271
288
  * @returns {Promise} 回傳Promise,resolve回傳數據物件,若無此主鍵則回傳null,reject回傳錯誤訊息
272
289
  */
273
290
  async function selectByPk(pk) {
291
+
292
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
293
+ if (client.status === 'closed') {
294
+ return procClosed('selectByPk', null)
295
+ }
274
296
  let isErr = false
275
297
  let res = null
276
298
 
@@ -320,13 +342,30 @@ function WOrmLmdb(opt = {}) {
320
342
  *
321
343
  * @memberOf WOrmLmdb
322
344
  * @param {Object|Array} data 輸入數據物件或陣列
323
- * @returns {Promise} 回傳Promise,resolve回傳插入結果物件{n,nInserted,ok},n為輸入筆數、nInserted為實際插入筆數,reject回傳錯誤訊息
345
+ * @param {Object} [option={}] 輸入設定物件,預設為{}
346
+ * @param {Boolean} [option.returnList=false] 輸入是否改回傳逐筆結果布林值,預設false。給true時回傳與輸入等長保序之陣列,各筆為{n,nInserted,ok},nInserted為1即該筆為新增;聚合計數只回答有幾筆是新的,逐筆結果方能回答是哪幾筆,供下游僅對新資料執行昂貴動作。回傳形式由呼叫點靜態決定,共用之結果處理程式碼不可跨不同取值之呼叫點混用
347
+ * @returns {Promise} 回傳Promise,resolve依returnList回傳插入結果:預設回傳聚合物件{n,nInserted,ok},n為輸入筆數、nInserted為實際插入筆數;returnList為true時回傳逐筆陣列,各筆n恆為1(主鍵命中或經插入)、ok恆為1(insert之錯誤皆屬整批性而reject,不進逐筆);reject回傳錯誤訊息
324
348
  */
325
- async function insert(data) {
349
+ async function insert(data, option = {}) {
350
+
351
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
352
+ if (client.status === 'closed') {
353
+ return procClosed('insert', data)
354
+ }
326
355
  let isErr = false
327
356
 
357
+ //returnList
358
+ let returnList = get(option, 'returnList')
359
+ if (!isbol(returnList)) {
360
+ returnList = false
361
+ }
362
+
328
363
  //check
329
364
  if (!iseobj(data) && !isearr(data)) {
365
+ if (returnList) {
366
+ //輸入無效, 對齊save與del之T5規定回傳空陣列
367
+ return []
368
+ }
330
369
  return {
331
370
  n: 0,
332
371
  nInserted: 0,
@@ -375,10 +414,24 @@ function WOrmLmdb(opt = {}) {
375
414
  })
376
415
 
377
416
  //res
378
- res = {
379
- n: nAll,
380
- nInserted: nPush,
381
- ok: 1,
417
+ if (returnList) {
418
+ //逐筆結果, 與輸入等長保序, 元素沿用逐筆結果之家族形狀(同save與del之元素)
419
+ //n恆為1(主鍵命中既有或經插入而產生), ok恆為1(insert之錯誤皆屬整批性而reject, 不進逐筆),
420
+ //資訊由nInserted承載, filter(v=>v.nInserted===1)之長度必等於聚合模式之nInserted
421
+ res = map(ltdone, function(done) {
422
+ return {
423
+ n: 1,
424
+ nInserted: done ? 1 : 0,
425
+ ok: 1,
426
+ }
427
+ })
428
+ }
429
+ else {
430
+ res = {
431
+ n: nAll,
432
+ nInserted: nPush,
433
+ ok: 1,
434
+ }
382
435
  }
383
436
 
384
437
  }
@@ -419,6 +472,11 @@ function WOrmLmdb(opt = {}) {
419
472
  * @returns {Promise} 回傳Promise,resolve回傳插入結果物件{n,nInserted,ok},n為輸入筆數、nInserted成功時恆等於n,任一筆主鍵已存在則reject回傳錯誤訊息
420
473
  */
421
474
  async function insertBulk(data) {
475
+
476
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
477
+ if (client.status === 'closed') {
478
+ return procClosed('insertBulk', data)
479
+ }
422
480
  let isErr = false
423
481
 
424
482
  //check
@@ -511,6 +569,11 @@ function WOrmLmdb(opt = {}) {
511
569
  * @returns {Promise} 回傳Promise,resolve回傳與輸入等長之儲存結果陣列,各筆為{n,nInserted,nModified,ok},n為主鍵命中筆數,單筆失敗者ok為0並附err,reject回傳錯誤訊息
512
570
  */
513
571
  async function save(data, option = {}) {
572
+
573
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
574
+ if (client.status === 'closed') {
575
+ return procClosed('save', data)
576
+ }
514
577
  let isErr = false
515
578
 
516
579
  //check
@@ -712,6 +775,11 @@ function WOrmLmdb(opt = {}) {
712
775
  * @returns {Promise} 回傳Promise,resolve回傳與輸入等長之刪除結果陣列,各筆為{n,nDeleted,ok},n為主鍵命中筆數,單筆失敗或未給有效id者ok為0並附err,reject回傳錯誤訊息
713
776
  */
714
777
  async function del(data) {
778
+
779
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
780
+ if (client.status === 'closed') {
781
+ return procClosed('del', data)
782
+ }
715
783
  let isErr = false
716
784
 
717
785
  //check
@@ -843,6 +911,11 @@ function WOrmLmdb(opt = {}) {
843
911
  * @returns {Promise} 回傳Promise,resolve回傳刪除結果物件{n,nDeleted,ok},n與nDeleted同為實際刪除筆數,reject回傳錯誤訊息
844
912
  */
845
913
  async function delAll(find = {}) {
914
+
915
+ //check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
916
+ if (client.status === 'closed') {
917
+ return procClosed('delAll', null)
918
+ }
846
919
  let isErr = false
847
920
 
848
921
  //res
@@ -945,7 +1018,8 @@ function WOrmLmdb(opt = {}) {
945
1018
  return res
946
1019
  }
947
1020
 
948
- //close, 關閉內部LMDB env並釋放檔案鎖, close後該實例即報廢, 須重新new WOrmLmdb
1021
+ //close, 關閉內部LMDB env並釋放檔案鎖, close後該實例即報廢, 須重新new WOrmLmdb,
1022
+ //再呼叫任何操作函數將立即reject(訊息明示closed), 不與[查無資料]同形
949
1023
  let close = async () => {
950
1024
  if (client && client.status !== 'closed') {
951
1025
  await client.close() //lmdb root database之close(), 回傳Promise