w-orm-lmdb 1.0.10 → 1.0.12

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.
@@ -0,0 +1,203 @@
1
+ import assert from 'assert'
2
+ import { spawn } from 'child_process'
3
+ import path from 'path'
4
+ import _ from 'lodash-es'
5
+ import w from 'wsemi'
6
+ import WOrm from '../src/WOrmLmdb.mjs'
7
+
8
+
9
+ //runProc, 另起行程對同一筆記錄併發save各自不同欄位, 用於驗證跨行程之讀改寫原子性
10
+ function runProc(tag, url, keys) {
11
+ return new Promise(function(resolve) {
12
+ let code = `
13
+ import { pathToFileURL } from 'url'
14
+ let { default: WOrm } = await import(pathToFileURL(process.env.SRC).href)
15
+ let wo = WOrm({ url: process.env.URL, db: 'worm', cl: 'xproc' })
16
+ let keys = JSON.parse(process.env.KEYS)
17
+ for (let k of keys) {
18
+ await wo.save({ id: 'x1', [k]: 1 })
19
+ }
20
+ console.log(JSON.stringify({ tag: process.env.TAG, ok: true }))
21
+ await wo.close()
22
+ `
23
+ let out = ''
24
+ let p = spawn(process.execPath, ['--input-type=module', '-e', code], {
25
+ shell: false,
26
+ env: {
27
+ ...process.env,
28
+ SRC: path.resolve('./src/WOrmLmdb.mjs'),
29
+ URL: url,
30
+ KEYS: JSON.stringify(keys),
31
+ TAG: tag,
32
+ },
33
+ })
34
+ p.stdout.on('data', function(d) {
35
+ out += d.toString()
36
+ })
37
+ p.stderr.on('data', function(d) {
38
+ out += d.toString()
39
+ })
40
+ p.on('close', function() {
41
+ resolve(_.trim(out))
42
+ })
43
+ })
44
+ }
45
+
46
+
47
+ describe('save', function() {
48
+ let rt = null
49
+ let vans = {}
50
+ let vget = {}
51
+
52
+ before(async function() {
53
+
54
+ w.fsDeleteFolder('./_db_save')
55
+
56
+ let url = './_db_save'
57
+
58
+ //併發save對既有id之不同欄位, 各欄位皆須保留
59
+ let woMerge = WOrm({ url, db: 'worm', cl: 'merge' })
60
+ await woMerge.insert({ id: 'u1', base: 1 })
61
+ await Promise.all(_.times(10, function(k) {
62
+ return woMerge.save({ id: 'u1', [`f${k}`]: k })
63
+ }))
64
+ let vu1 = await woMerge.selectById('u1')
65
+ vget[1] = _.size(_.filter(_.keys(vu1), function(k) {
66
+ return _.startsWith(k, 'f')
67
+ }))
68
+ vget[2] = vu1.base
69
+ await woMerge.close()
70
+
71
+ //併發save對全新id, autoInsert僅一次且各欄位皆須保留
72
+ let woNew = WOrm({ url, db: 'worm', cl: 'newid' })
73
+ let rsn = await Promise.all([
74
+ woNew.save({ id: 'w1', fa: 1 }),
75
+ woNew.save({ id: 'w1', fb: 2 }),
76
+ woNew.save({ id: 'w1', fc: 3 }),
77
+ ])
78
+ let vw1 = await woNew.selectById('w1')
79
+ vget[3] = _.pick(vw1, ['id', 'fa', 'fb', 'fc'])
80
+ vget[4] = _.size(await woNew.select())
81
+ vget[5] = _.size(_.filter(_.flatten(rsn), function(v) {
82
+ return v.nInserted === 1
83
+ }))
84
+ await woNew.close()
85
+
86
+ //跨行程併發save對同一既有id之不同欄位
87
+ let woX = WOrm({ url, db: 'worm', cl: 'xproc' })
88
+ await woX.insert({ id: 'x1', base: 1 })
89
+ await woX.close()
90
+ await Promise.all([
91
+ runProc('P1', url, _.times(25, function(k) {
92
+ return `p1k${k}`
93
+ })),
94
+ runProc('P2', url, _.times(25, function(k) {
95
+ return `p2k${k}`
96
+ })),
97
+ ])
98
+ let woX2 = WOrm({ url, db: 'worm', cl: 'xproc' })
99
+ let vx1 = await woX2.selectById('x1')
100
+ vget[6] = _.size(_.filter(_.keys(vx1), function(k) {
101
+ return _.startsWith(k, 'p1k') || _.startsWith(k, 'p2k')
102
+ }))
103
+ await woX2.close()
104
+
105
+ //既有行為: 內容相同不更新
106
+ let woKeep = WOrm({ url, db: 'worm', cl: 'keep' })
107
+ await woKeep.insert({ id: 'k1', name: 'peter' })
108
+ rt = null
109
+ // vans[7] = [{ n: 0, nModified: 0, ok: 1 }]
110
+ await woKeep.save({ id: 'k1', name: 'peter' })
111
+ .then(function(msg) {
112
+ rt = msg
113
+ })
114
+ .catch(function(msg) {
115
+ rt = msg.toString()
116
+ })
117
+ vget[7] = rt
118
+
119
+ //既有行為: autoInsert=false且id不存在則不插入
120
+ rt = null
121
+ // vans[8] = [{ n: 0, nModified: 0, ok: 1 }]
122
+ await woKeep.save({ id: 'k-none', name: 'none' }, { autoInsert: false })
123
+ .then(function(msg) {
124
+ rt = msg
125
+ })
126
+ .catch(function(msg) {
127
+ rt = msg.toString()
128
+ })
129
+ vget[8] = rt
130
+ vget[9] = await woKeep.selectById('k-none')
131
+ await woKeep.close()
132
+
133
+ //既有行為: change事件, autoInsert時仍須發出insert事件
134
+ let woEv = WOrm({ url, db: 'worm', cl: 'event' })
135
+ let modes = []
136
+ woEv.on('change', function(mode) {
137
+ modes.push(mode)
138
+ })
139
+ await woEv.save({ id: 'e1', name: 'new' }) //不存在, 走autoInsert
140
+ vget[10] = _.clone(modes)
141
+ modes = []
142
+ await woEv.save({ id: 'e1', name: 'modify' }) //已存在, 走更新
143
+ vget[11] = _.clone(modes)
144
+ await woEv.close()
145
+
146
+ })
147
+
148
+ vans[1] = 10
149
+ it(`should get ${JSON.stringify(vans[1])} for fields after 10 concurrent save with different field`, async function() {
150
+ assert.strict.deepStrictEqual(vget[1], vans[1])
151
+ })
152
+
153
+ vans[2] = 1
154
+ it(`should get ${JSON.stringify(vans[2])} for keeping original field after concurrent save`, async function() {
155
+ assert.strict.deepStrictEqual(vget[2], vans[2])
156
+ })
157
+
158
+ vans[3] = { id: 'w1', fa: 1, fb: 2, fc: 3 }
159
+ it(`should get ${JSON.stringify(vans[3])} for 3 concurrent save with id not existed`, async function() {
160
+ assert.strict.deepStrictEqual(vget[3], vans[3])
161
+ })
162
+
163
+ vans[4] = 1
164
+ it(`should get ${JSON.stringify(vans[4])} for records after 3 concurrent save with id not existed`, async function() {
165
+ assert.strict.deepStrictEqual(vget[4], vans[4])
166
+ })
167
+
168
+ vans[5] = 1
169
+ it(`should get ${JSON.stringify(vans[5])} for count of nInserted===1 in 3 concurrent save with id not existed`, async function() {
170
+ assert.strict.deepStrictEqual(vget[5], vans[5])
171
+ })
172
+
173
+ vans[6] = 50
174
+ it(`should get ${JSON.stringify(vans[6])} for fields after 2 processes saving different fields`, async function() {
175
+ assert.strict.deepStrictEqual(vget[6], vans[6])
176
+ })
177
+
178
+ vans[7] = [{ n: 0, nModified: 0, ok: 1 }]
179
+ it(`should get ${JSON.stringify(vans[7])} for save with same content`, async function() {
180
+ assert.strict.deepStrictEqual(vget[7], vans[7])
181
+ })
182
+
183
+ vans[8] = [{ n: 0, nModified: 0, ok: 1 }]
184
+ it(`should get ${JSON.stringify(vans[8])} for save(autoInsert=false) with id not existed`, async function() {
185
+ assert.strict.deepStrictEqual(vget[8], vans[8])
186
+ })
187
+
188
+ vans[9] = null
189
+ it(`should get ${JSON.stringify(vans[9])} for not inserting by save(autoInsert=false)`, async function() {
190
+ assert.strict.deepStrictEqual(vget[9], vans[9])
191
+ })
192
+
193
+ vans[10] = ['insert', 'save']
194
+ it(`should get ${JSON.stringify(vans[10])} for change events of save(autoInsert) with id not existed`, async function() {
195
+ assert.strict.deepStrictEqual(vget[10], vans[10])
196
+ })
197
+
198
+ vans[11] = ['save']
199
+ it(`should get ${JSON.stringify(vans[11])} for change events of save with id existed`, async function() {
200
+ assert.strict.deepStrictEqual(vget[11], vans[11])
201
+ })
202
+
203
+ })
Binary file
Binary file
File without changes