@aztec/kv-store 0.0.1-commit.b655e406 → 0.0.1-commit.b9865e97
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.
- package/README.md +8 -1
- package/dest/bench/shared_map_bench.d.ts +19 -0
- package/dest/bench/shared_map_bench.d.ts.map +1 -0
- package/dest/bench/shared_map_bench.js +91 -0
- package/dest/indexeddb/array.d.ts +1 -1
- package/dest/indexeddb/array.d.ts.map +1 -1
- package/dest/indexeddb/array.js +21 -7
- package/dest/indexeddb/index.d.ts +3 -3
- package/dest/indexeddb/index.d.ts.map +1 -1
- package/dest/indexeddb/index.js +3 -6
- package/dest/indexeddb/map.d.ts +8 -2
- package/dest/indexeddb/map.d.ts.map +1 -1
- package/dest/indexeddb/map.js +23 -13
- package/dest/indexeddb/multi_map.d.ts +3 -1
- package/dest/indexeddb/multi_map.d.ts.map +1 -1
- package/dest/indexeddb/multi_map.js +30 -1
- package/dest/indexeddb/set.d.ts +1 -1
- package/dest/indexeddb/set.d.ts.map +1 -1
- package/dest/indexeddb/singleton.d.ts +1 -1
- package/dest/indexeddb/singleton.d.ts.map +1 -1
- package/dest/indexeddb/singleton.js +3 -1
- package/dest/indexeddb/store.d.ts +3 -3
- package/dest/indexeddb/store.d.ts.map +1 -1
- package/dest/indexeddb/store.js +6 -4
- package/dest/interfaces/array.d.ts +1 -1
- package/dest/interfaces/array_test_suite.d.ts +1 -1
- package/dest/interfaces/array_test_suite.d.ts.map +1 -1
- package/dest/interfaces/array_test_suite.js +33 -34
- package/dest/interfaces/common.d.ts +1 -1
- package/dest/interfaces/counter.d.ts +1 -1
- package/dest/interfaces/index.d.ts +2 -2
- package/dest/interfaces/index.d.ts.map +1 -1
- package/dest/interfaces/map.d.ts +1 -1
- package/dest/interfaces/map_test_suite.d.ts +1 -1
- package/dest/interfaces/map_test_suite.d.ts.map +1 -1
- package/dest/interfaces/map_test_suite.js +74 -29
- package/dest/interfaces/multi_map.d.ts +7 -1
- package/dest/interfaces/multi_map.d.ts.map +1 -1
- package/dest/interfaces/multi_map_test_suite.d.ts +1 -1
- package/dest/interfaces/multi_map_test_suite.d.ts.map +1 -1
- package/dest/interfaces/multi_map_test_suite.js +154 -36
- package/dest/interfaces/set.d.ts +1 -1
- package/dest/interfaces/set_test_suite.d.ts +1 -1
- package/dest/interfaces/set_test_suite.d.ts.map +1 -1
- package/dest/interfaces/set_test_suite.js +13 -14
- package/dest/interfaces/singleton.d.ts +1 -1
- package/dest/interfaces/singleton_test_suite.d.ts +1 -1
- package/dest/interfaces/singleton_test_suite.d.ts.map +1 -1
- package/dest/interfaces/singleton_test_suite.js +6 -7
- package/dest/interfaces/store.d.ts +1 -1
- package/dest/interfaces/utils.d.ts +2 -1
- package/dest/interfaces/utils.d.ts.map +1 -1
- package/dest/interfaces/utils.js +2 -1
- package/dest/lmdb/array.d.ts +1 -1
- package/dest/lmdb/array.d.ts.map +1 -1
- package/dest/lmdb/array.js +4 -2
- package/dest/lmdb/counter.d.ts +1 -1
- package/dest/lmdb/counter.d.ts.map +1 -1
- package/dest/lmdb/index.d.ts +3 -3
- package/dest/lmdb/index.d.ts.map +1 -1
- package/dest/lmdb/index.js +4 -4
- package/dest/lmdb/map.d.ts +1 -1
- package/dest/lmdb/map.d.ts.map +1 -1
- package/dest/lmdb/multi_map.d.ts +2 -1
- package/dest/lmdb/multi_map.d.ts.map +1 -1
- package/dest/lmdb/multi_map.js +15 -0
- package/dest/lmdb/set.d.ts +1 -1
- package/dest/lmdb/set.d.ts.map +1 -1
- package/dest/lmdb/singleton.d.ts +1 -1
- package/dest/lmdb/singleton.d.ts.map +1 -1
- package/dest/lmdb/store.d.ts +4 -5
- package/dest/lmdb/store.d.ts.map +1 -1
- package/dest/lmdb/store.js +13 -9
- package/dest/lmdb-v2/array.d.ts +2 -2
- package/dest/lmdb-v2/array.d.ts.map +1 -1
- package/dest/lmdb-v2/array.js +4 -3
- package/dest/lmdb-v2/factory.d.ts +32 -10
- package/dest/lmdb-v2/factory.d.ts.map +1 -1
- package/dest/lmdb-v2/factory.js +71 -16
- package/dest/lmdb-v2/index.d.ts +1 -1
- package/dest/lmdb-v2/map.d.ts +2 -2
- package/dest/lmdb-v2/map.d.ts.map +1 -1
- package/dest/lmdb-v2/map.js +1 -2
- package/dest/lmdb-v2/message.d.ts +1 -1
- package/dest/lmdb-v2/multi_map.d.ts +3 -2
- package/dest/lmdb-v2/multi_map.d.ts.map +1 -1
- package/dest/lmdb-v2/multi_map.js +11 -1
- package/dest/lmdb-v2/read_transaction.d.ts +1 -1
- package/dest/lmdb-v2/read_transaction.d.ts.map +1 -1
- package/dest/lmdb-v2/read_transaction.js +21 -19
- package/dest/lmdb-v2/set.d.ts +1 -1
- package/dest/lmdb-v2/set.d.ts.map +1 -1
- package/dest/lmdb-v2/singleton.d.ts +2 -2
- package/dest/lmdb-v2/singleton.d.ts.map +1 -1
- package/dest/lmdb-v2/singleton.js +1 -2
- package/dest/lmdb-v2/store.d.ts +4 -5
- package/dest/lmdb-v2/store.d.ts.map +1 -1
- package/dest/lmdb-v2/store.js +6 -28
- package/dest/lmdb-v2/tx-helpers.d.ts +6 -0
- package/dest/lmdb-v2/tx-helpers.d.ts.map +1 -0
- package/dest/lmdb-v2/tx-helpers.js +21 -0
- package/dest/lmdb-v2/utils.d.ts +1 -10
- package/dest/lmdb-v2/utils.d.ts.map +1 -1
- package/dest/lmdb-v2/utils.js +0 -94
- package/dest/lmdb-v2/write_transaction.d.ts +1 -1
- package/dest/lmdb-v2/write_transaction.d.ts.map +1 -1
- package/dest/lmdb-v2/write_transaction.js +9 -5
- package/dest/sqlite-opfs/array.d.ts +21 -0
- package/dest/sqlite-opfs/array.d.ts.map +1 -0
- package/dest/sqlite-opfs/array.js +128 -0
- package/dest/sqlite-opfs/errors.d.ts +27 -0
- package/dest/sqlite-opfs/errors.d.ts.map +1 -0
- package/dest/sqlite-opfs/errors.js +34 -0
- package/dest/sqlite-opfs/index.d.ts +16 -0
- package/dest/sqlite-opfs/index.d.ts.map +1 -0
- package/dest/sqlite-opfs/index.js +22 -0
- package/dest/sqlite-opfs/internal/ordered-binary-browser.d.ts +32 -0
- package/dest/sqlite-opfs/internal/ordered-binary-browser.d.ts.map +1 -0
- package/dest/sqlite-opfs/internal/ordered-binary-browser.js +448 -0
- package/dest/sqlite-opfs/map.d.ts +35 -0
- package/dest/sqlite-opfs/map.d.ts.map +1 -0
- package/dest/sqlite-opfs/map.js +163 -0
- package/dest/sqlite-opfs/messages.d.ts +66 -0
- package/dest/sqlite-opfs/messages.d.ts.map +1 -0
- package/dest/sqlite-opfs/messages.js +5 -0
- package/dest/sqlite-opfs/multi_map.d.ts +16 -0
- package/dest/sqlite-opfs/multi_map.d.ts.map +1 -0
- package/dest/sqlite-opfs/multi_map.js +67 -0
- package/dest/sqlite-opfs/set.d.ts +13 -0
- package/dest/sqlite-opfs/set.d.ts.map +1 -0
- package/dest/sqlite-opfs/set.js +19 -0
- package/dest/sqlite-opfs/singleton.d.ts +13 -0
- package/dest/sqlite-opfs/singleton.d.ts.map +1 -0
- package/dest/sqlite-opfs/singleton.js +48 -0
- package/dest/sqlite-opfs/store.d.ts +79 -0
- package/dest/sqlite-opfs/store.d.ts.map +1 -0
- package/dest/sqlite-opfs/store.js +281 -0
- package/dest/sqlite-opfs/worker.d.ts +2 -0
- package/dest/sqlite-opfs/worker.d.ts.map +1 -0
- package/dest/sqlite-opfs/worker.js +249 -0
- package/dest/stores/index.d.ts +1 -1
- package/dest/stores/l2_tips_store.d.ts +25 -10
- package/dest/stores/l2_tips_store.d.ts.map +1 -1
- package/dest/stores/l2_tips_store.js +62 -53
- package/dest/utils.d.ts +9 -6
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +51 -16
- package/package.json +33 -26
- package/src/bench/shared_map_bench.ts +111 -0
- package/src/indexeddb/array.ts +4 -4
- package/src/indexeddb/index.ts +9 -7
- package/src/indexeddb/map.ts +24 -11
- package/src/indexeddb/multi_map.ts +27 -1
- package/src/indexeddb/singleton.ts +1 -1
- package/src/indexeddb/store.ts +13 -6
- package/src/interfaces/array_test_suite.ts +33 -35
- package/src/interfaces/index.ts +1 -1
- package/src/interfaces/map_test_suite.ts +56 -30
- package/src/interfaces/multi_map.ts +7 -0
- package/src/interfaces/multi_map_test_suite.ts +167 -37
- package/src/interfaces/set_test_suite.ts +13 -15
- package/src/interfaces/singleton_test_suite.ts +6 -8
- package/src/interfaces/utils.ts +1 -0
- package/src/lmdb/index.ts +10 -5
- package/src/lmdb/multi_map.ts +16 -0
- package/src/lmdb/store.ts +13 -9
- package/src/lmdb-v2/array.ts +2 -2
- package/src/lmdb-v2/factory.ts +93 -19
- package/src/lmdb-v2/map.ts +2 -2
- package/src/lmdb-v2/multi_map.ts +10 -1
- package/src/lmdb-v2/read_transaction.ts +23 -23
- package/src/lmdb-v2/singleton.ts +2 -2
- package/src/lmdb-v2/store.ts +9 -33
- package/src/lmdb-v2/tx-helpers.ts +29 -0
- package/src/lmdb-v2/utils.ts +0 -118
- package/src/lmdb-v2/write_transaction.ts +9 -8
- package/src/sqlite-opfs/array.ts +124 -0
- package/src/sqlite-opfs/errors.ts +44 -0
- package/src/sqlite-opfs/index.ts +39 -0
- package/src/sqlite-opfs/internal/ordered-binary-browser.js +465 -0
- package/src/sqlite-opfs/map.ts +163 -0
- package/src/sqlite-opfs/messages.ts +39 -0
- package/src/sqlite-opfs/multi_map.ts +74 -0
- package/src/sqlite-opfs/set.ts +29 -0
- package/src/sqlite-opfs/singleton.ts +48 -0
- package/src/sqlite-opfs/store.ts +296 -0
- package/src/sqlite-opfs/worker.ts +231 -0
- package/src/stores/l2_tips_store.ts +66 -56
- package/src/utils.ts +79 -21
- package/dest/config.d.ts +0 -17
- package/dest/config.d.ts.map +0 -1
- package/dest/config.js +0 -26
- package/src/config.ts +0 -36
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { toArray } from '@aztec/foundation/iterable';
|
|
2
2
|
|
|
3
|
-
import { expect } from 'chai';
|
|
4
|
-
|
|
5
3
|
import type { Key, Range } from './common.js';
|
|
6
4
|
import type { AztecAsyncMultiMap, AztecMultiMap } from './multi_map.js';
|
|
7
5
|
import type { AztecAsyncKVStore, AztecKVStore } from './store.js';
|
|
@@ -61,20 +59,27 @@ export function describeAztecMultiMap(
|
|
|
61
59
|
: await toArray((multiMap as AztecAsyncMultiMap<any, any>).getValuesAsync(key));
|
|
62
60
|
}
|
|
63
61
|
|
|
62
|
+
async function getValueCount(
|
|
63
|
+
key: Key,
|
|
64
|
+
sut: AztecAsyncMultiMap<any, any> | AztecMultiMap<any, any> = multiMap,
|
|
65
|
+
): Promise<number> {
|
|
66
|
+
return await (sut as AztecAsyncMultiMap<any, any>).getValueCountAsync(key);
|
|
67
|
+
}
|
|
68
|
+
|
|
64
69
|
it('should be able to set and get values', async () => {
|
|
65
70
|
await multiMap.set('foo', 'bar');
|
|
66
71
|
await multiMap.set('baz', 'qux');
|
|
67
72
|
|
|
68
|
-
expect(await get('foo')).
|
|
69
|
-
expect(await get('baz')).
|
|
70
|
-
expect(await get('quux')).
|
|
73
|
+
expect(await get('foo')).toBe('bar');
|
|
74
|
+
expect(await get('baz')).toBe('qux');
|
|
75
|
+
expect(await get('quux')).toBe(undefined);
|
|
71
76
|
});
|
|
72
77
|
|
|
73
78
|
it('should be able to set values if they do not exist', async () => {
|
|
74
|
-
expect(await multiMap.setIfNotExists('foo', 'bar')).
|
|
75
|
-
expect(await multiMap.setIfNotExists('foo', 'baz')).
|
|
79
|
+
expect(await multiMap.setIfNotExists('foo', 'bar')).toBe(true);
|
|
80
|
+
expect(await multiMap.setIfNotExists('foo', 'baz')).toBe(false);
|
|
76
81
|
|
|
77
|
-
expect(await get('foo')).
|
|
82
|
+
expect(await get('foo')).toBe('bar');
|
|
78
83
|
});
|
|
79
84
|
|
|
80
85
|
it('should be able to delete values', async () => {
|
|
@@ -83,29 +88,61 @@ export function describeAztecMultiMap(
|
|
|
83
88
|
|
|
84
89
|
await multiMap.delete('foo');
|
|
85
90
|
|
|
86
|
-
expect(await get('foo')).
|
|
87
|
-
expect(await get('baz')).
|
|
91
|
+
expect(await get('foo')).toBe(undefined);
|
|
92
|
+
expect(await get('baz')).toBe('qux');
|
|
88
93
|
});
|
|
89
94
|
|
|
90
95
|
it('should be able to get size of the map', async () => {
|
|
91
96
|
await multiMap.set('foo', 'bar');
|
|
92
|
-
expect(await size()).
|
|
97
|
+
expect(await size()).toBe(1);
|
|
93
98
|
await multiMap.set('baz', 'qux');
|
|
94
|
-
expect(await size()).
|
|
99
|
+
expect(await size()).toBe(2);
|
|
95
100
|
|
|
96
101
|
await multiMap.delete('foo');
|
|
97
|
-
expect(await size()).
|
|
102
|
+
expect(await size()).toBe(1);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('returns 0 for empty multimap size', async () => {
|
|
106
|
+
expect(await size()).toBe(0);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('calculates size correctly with multiple values per key', async () => {
|
|
110
|
+
expect(await size()).toBe(0);
|
|
111
|
+
|
|
112
|
+
// Add multiple values for same key
|
|
113
|
+
await multiMap.set('key1', 'value1');
|
|
114
|
+
expect(await size()).toBe(1);
|
|
115
|
+
await multiMap.set('key1', 'value2');
|
|
116
|
+
expect(await size()).toBe(2);
|
|
117
|
+
await multiMap.set('key1', 'value3');
|
|
118
|
+
expect(await size()).toBe(3);
|
|
119
|
+
|
|
120
|
+
// Add values for different key
|
|
121
|
+
await multiMap.set('key2', 'value4');
|
|
122
|
+
expect(await size()).toBe(4);
|
|
123
|
+
|
|
124
|
+
// Delete one value from key1
|
|
125
|
+
await multiMap.deleteValue('key1', 'value2');
|
|
126
|
+
expect(await size()).toBe(3);
|
|
127
|
+
|
|
128
|
+
// Delete entire key
|
|
129
|
+
await multiMap.delete('key1');
|
|
130
|
+
expect(await size()).toBe(1);
|
|
131
|
+
|
|
132
|
+
// Delete last key
|
|
133
|
+
await multiMap.delete('key2');
|
|
134
|
+
expect(await size()).toBe(0);
|
|
98
135
|
});
|
|
99
136
|
|
|
100
137
|
it('should be able to iterate over entries when there are no keys', async () => {
|
|
101
|
-
expect(await entries()).
|
|
138
|
+
expect(await entries()).toEqual([]);
|
|
102
139
|
});
|
|
103
140
|
|
|
104
141
|
it('should be able to iterate over entries', async () => {
|
|
105
142
|
await multiMap.set('foo', 'bar');
|
|
106
143
|
await multiMap.set('baz', 'qux');
|
|
107
144
|
|
|
108
|
-
expect(await entries()).
|
|
145
|
+
expect(await entries()).toEqual([
|
|
109
146
|
['baz', 'qux'],
|
|
110
147
|
['foo', 'bar'],
|
|
111
148
|
]);
|
|
@@ -115,28 +152,28 @@ export function describeAztecMultiMap(
|
|
|
115
152
|
await multiMap.set('foo', 'bar');
|
|
116
153
|
await multiMap.set('baz', 'quux');
|
|
117
154
|
|
|
118
|
-
expect(await values()).
|
|
155
|
+
expect(await values()).toEqual(['quux', 'bar']);
|
|
119
156
|
});
|
|
120
157
|
|
|
121
158
|
it('should be able to iterate over keys', async () => {
|
|
122
159
|
await multiMap.set('foo', 'bar');
|
|
123
160
|
await multiMap.set('baz', 'qux');
|
|
124
161
|
|
|
125
|
-
expect(await keys()).
|
|
162
|
+
expect(await keys()).toEqual(['baz', 'foo']);
|
|
126
163
|
});
|
|
127
164
|
|
|
128
165
|
it('should be able to get multiple values for a single key', async () => {
|
|
129
166
|
await multiMap.set('foo', 'bar');
|
|
130
167
|
await multiMap.set('foo', 'baz');
|
|
131
168
|
|
|
132
|
-
expect(await getValues('foo')).
|
|
169
|
+
expect(await getValues('foo')).toEqual(['bar', 'baz']);
|
|
133
170
|
});
|
|
134
171
|
|
|
135
172
|
it('should ignore multiple identical values', async () => {
|
|
136
173
|
await multiMap.set('foo', 'bar');
|
|
137
174
|
await multiMap.set('foo', 'bar');
|
|
138
175
|
|
|
139
|
-
expect(await getValues('foo')).
|
|
176
|
+
expect(await getValues('foo')).toEqual(['bar']);
|
|
140
177
|
});
|
|
141
178
|
|
|
142
179
|
it('should be able to delete individual values for a single key', async () => {
|
|
@@ -146,22 +183,22 @@ export function describeAztecMultiMap(
|
|
|
146
183
|
|
|
147
184
|
await multiMap.deleteValue('foo', '2');
|
|
148
185
|
|
|
149
|
-
expect(await getValues('foo')).
|
|
186
|
+
expect(await getValues('foo')).toEqual(['1', '3']);
|
|
150
187
|
});
|
|
151
188
|
|
|
152
189
|
it('should be able to get size of the map with duplicate keys', async () => {
|
|
153
190
|
await multiMap.set('foo', '1');
|
|
154
191
|
await multiMap.set('foo', '2');
|
|
155
192
|
await multiMap.set('foo', '3');
|
|
156
|
-
expect(await size()).
|
|
193
|
+
expect(await size()).toBe(3);
|
|
157
194
|
|
|
158
195
|
await multiMap.set('bar', '1');
|
|
159
196
|
await multiMap.set('bar', '2');
|
|
160
197
|
await multiMap.set('bar', '3');
|
|
161
|
-
expect(await size()).
|
|
198
|
+
expect(await size()).toBe(6);
|
|
162
199
|
|
|
163
200
|
await multiMap.deleteValue('foo', '2');
|
|
164
|
-
expect(await size()).
|
|
201
|
+
expect(await size()).toBe(5);
|
|
165
202
|
});
|
|
166
203
|
|
|
167
204
|
it('should be able to delete the last and first values for a key', async () => {
|
|
@@ -171,11 +208,11 @@ export function describeAztecMultiMap(
|
|
|
171
208
|
|
|
172
209
|
await multiMap.deleteValue('foo', '1');
|
|
173
210
|
|
|
174
|
-
expect(await getValues('foo')).
|
|
211
|
+
expect(await getValues('foo')).toEqual(['2', '3']);
|
|
175
212
|
|
|
176
213
|
await multiMap.deleteValue('foo', '3');
|
|
177
214
|
|
|
178
|
-
expect(await getValues('foo')).
|
|
215
|
+
expect(await getValues('foo')).toEqual(['2']);
|
|
179
216
|
});
|
|
180
217
|
|
|
181
218
|
it('should be able to fully clear a key', async () => {
|
|
@@ -187,7 +224,7 @@ export function describeAztecMultiMap(
|
|
|
187
224
|
await multiMap.deleteValue('foo', '3');
|
|
188
225
|
await multiMap.deleteValue('foo', '2');
|
|
189
226
|
|
|
190
|
-
expect(await getValues('foo')).
|
|
227
|
+
expect(await getValues('foo')).toEqual([]);
|
|
191
228
|
});
|
|
192
229
|
|
|
193
230
|
it('should be able to insert after deletion', async () => {
|
|
@@ -198,12 +235,12 @@ export function describeAztecMultiMap(
|
|
|
198
235
|
await multiMap.deleteValue('foo', '2');
|
|
199
236
|
await multiMap.set('foo', 'bar');
|
|
200
237
|
|
|
201
|
-
expect(await getValues('foo')).
|
|
238
|
+
expect(await getValues('foo')).toEqual(['1', '3', 'bar']);
|
|
202
239
|
|
|
203
240
|
// Delete the just-added entry
|
|
204
241
|
await multiMap.deleteValue('foo', 'bar');
|
|
205
242
|
|
|
206
|
-
expect(await getValues('foo')).
|
|
243
|
+
expect(await getValues('foo')).toEqual(['1', '3']);
|
|
207
244
|
|
|
208
245
|
// Reinsert the initially deleted key
|
|
209
246
|
await multiMap.set('foo', '2');
|
|
@@ -211,7 +248,7 @@ export function describeAztecMultiMap(
|
|
|
211
248
|
// LMDB and IndexedDB behave differently here, the former ordering by value and the latter by insertion. This is
|
|
212
249
|
// fine because there is no expectation for values in a multimap to be ordered.
|
|
213
250
|
const values = (await getValues('foo')).sort((a, b) => a.localeCompare(b));
|
|
214
|
-
expect(values).
|
|
251
|
+
expect(values).toEqual(['1', '2', '3']);
|
|
215
252
|
|
|
216
253
|
// Fully clear the key
|
|
217
254
|
await multiMap.deleteValue('foo', '1');
|
|
@@ -221,7 +258,7 @@ export function describeAztecMultiMap(
|
|
|
221
258
|
// Insert some more
|
|
222
259
|
await multiMap.set('foo', 'baz');
|
|
223
260
|
await multiMap.set('foo', 'qux');
|
|
224
|
-
expect(await getValues('foo')).
|
|
261
|
+
expect(await getValues('foo')).toEqual(['baz', 'qux']);
|
|
225
262
|
});
|
|
226
263
|
|
|
227
264
|
it('supports range queries', async () => {
|
|
@@ -230,13 +267,106 @@ export function describeAztecMultiMap(
|
|
|
230
267
|
await multiMap.set('c', 'c');
|
|
231
268
|
await multiMap.set('d', 'd');
|
|
232
269
|
|
|
233
|
-
expect(await keys({ start: 'b', end: 'c' })).
|
|
234
|
-
expect(await keys({ start: 'b' })).
|
|
235
|
-
expect(await keys({ end: 'c' })).
|
|
236
|
-
expect(await keys({ start: 'b', end: 'c', reverse: true })).
|
|
237
|
-
expect(await keys({ start: 'b', limit: 1 })).
|
|
238
|
-
expect(await keys({ start: 'b', reverse: true })).
|
|
239
|
-
expect(await keys({ end: 'b', reverse: true })).
|
|
270
|
+
expect(await keys({ start: 'b', end: 'c' })).toEqual(['b']);
|
|
271
|
+
expect(await keys({ start: 'b' })).toEqual(['b', 'c', 'd']);
|
|
272
|
+
expect(await keys({ end: 'c' })).toEqual(['a', 'b']);
|
|
273
|
+
expect(await keys({ start: 'b', end: 'c', reverse: true })).toEqual(['c']);
|
|
274
|
+
expect(await keys({ start: 'b', limit: 1 })).toEqual(['b']);
|
|
275
|
+
expect(await keys({ start: 'b', reverse: true })).toEqual(['d', 'c']);
|
|
276
|
+
expect(await keys({ end: 'b', reverse: true })).toEqual(['b', 'a']);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('returns 0 for missing key', async () => {
|
|
280
|
+
expect(await getValueCount('missing')).toBe(0);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('counts a single value', async () => {
|
|
284
|
+
await multiMap.set('foo', 'bar');
|
|
285
|
+
expect(await getValueCount('foo')).toBe(1);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('counts multiple distinct values for same key', async () => {
|
|
289
|
+
await multiMap.set('foo', 'bar');
|
|
290
|
+
await multiMap.set('foo', 'baz');
|
|
291
|
+
await multiMap.set('foo', 'qux');
|
|
292
|
+
expect(await getValueCount('foo')).toBe(3);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('does not increase count for duplicate inserts', async () => {
|
|
296
|
+
await multiMap.set('foo', 'bar');
|
|
297
|
+
await multiMap.set('foo', 'bar');
|
|
298
|
+
await multiMap.set('foo', 'baz');
|
|
299
|
+
await multiMap.set('foo', 'baz');
|
|
300
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
301
|
+
expect((await getValues('foo')).sort()).toEqual(['bar', 'baz'].sort());
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('decrements when deleting a single value', async () => {
|
|
305
|
+
await multiMap.set('foo', '1');
|
|
306
|
+
await multiMap.set('foo', '2');
|
|
307
|
+
await multiMap.set('foo', '3');
|
|
308
|
+
expect(await getValueCount('foo')).toBe(3);
|
|
309
|
+
await multiMap.deleteValue('foo', '2');
|
|
310
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
311
|
+
expect((await getValues('foo')).sort()).toEqual(['1', '3'].sort());
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('does not change count when deleting a non-existent value', async () => {
|
|
315
|
+
await multiMap.set('foo', '1');
|
|
316
|
+
await multiMap.set('foo', '3');
|
|
317
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
318
|
+
await multiMap.deleteValue('foo', '2');
|
|
319
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it('clears all values when deleting a key', async () => {
|
|
323
|
+
await multiMap.set('foo', 'bar');
|
|
324
|
+
await multiMap.set('foo', 'baz');
|
|
325
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
326
|
+
await multiMap.delete('foo');
|
|
327
|
+
expect(await getValueCount('foo')).toBe(0);
|
|
328
|
+
expect(await getValues('foo')).toEqual([]);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('count equals enumerated values length', async () => {
|
|
332
|
+
await multiMap.set('foo', '1');
|
|
333
|
+
await multiMap.set('foo', '2');
|
|
334
|
+
const vals = await getValues('foo');
|
|
335
|
+
expect(await getValueCount('foo')).toBe(vals.length);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('sum of per-key counts equals total size', async () => {
|
|
339
|
+
await multiMap.set('foo', '1');
|
|
340
|
+
await multiMap.set('foo', '2');
|
|
341
|
+
await multiMap.set('bar', '3');
|
|
342
|
+
await multiMap.set('bar', '4');
|
|
343
|
+
await multiMap.set('baz', '5');
|
|
344
|
+
|
|
345
|
+
const allKeys = await keys();
|
|
346
|
+
const uniqueKeys = Array.from(new Set(allKeys));
|
|
347
|
+
const counts = await Promise.all(uniqueKeys.map(k => getValueCount(k)));
|
|
348
|
+
const sum = counts.reduce((s, n) => s + n, 0);
|
|
349
|
+
expect(sum).toBe(await size());
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it('supports sparse slots: delete middle, reinsert new, count remains correct', async () => {
|
|
353
|
+
await multiMap.set('foo', '1');
|
|
354
|
+
await multiMap.set('foo', '2');
|
|
355
|
+
await multiMap.set('foo', '3');
|
|
356
|
+
expect(await getValueCount('foo')).toBe(3);
|
|
357
|
+
await multiMap.deleteValue('foo', '2');
|
|
358
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
359
|
+
await multiMap.set('foo', '4');
|
|
360
|
+
expect(await getValueCount('foo')).toBe(3);
|
|
361
|
+
expect((await getValues('foo')).sort()).toEqual(['1', '3', '4'].sort());
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it('multiple keys are independent', async () => {
|
|
365
|
+
await multiMap.set('foo', '1');
|
|
366
|
+
await multiMap.set('foo', '2');
|
|
367
|
+
await multiMap.set('bar', '3');
|
|
368
|
+
expect(await getValueCount('foo')).toBe(2);
|
|
369
|
+
expect(await getValueCount('bar')).toBe(1);
|
|
240
370
|
});
|
|
241
371
|
});
|
|
242
372
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { toArray } from '@aztec/foundation/iterable';
|
|
2
2
|
|
|
3
|
-
import { expect } from 'chai';
|
|
4
|
-
|
|
5
3
|
import type { Range } from './common.js';
|
|
6
4
|
import type { AztecAsyncSet, AztecSet } from './set.js';
|
|
7
5
|
import type { AztecAsyncKVStore, AztecKVStore } from './store.js';
|
|
@@ -41,9 +39,9 @@ export function describeAztecSet(
|
|
|
41
39
|
await set.add('foo');
|
|
42
40
|
await set.add('baz');
|
|
43
41
|
|
|
44
|
-
expect(await has('foo')).
|
|
45
|
-
expect(await has('baz')).
|
|
46
|
-
expect(await has('bar')).
|
|
42
|
+
expect(await has('foo')).toBe(true);
|
|
43
|
+
expect(await has('baz')).toBe(true);
|
|
44
|
+
expect(await has('bar')).toBe(false);
|
|
47
45
|
});
|
|
48
46
|
|
|
49
47
|
it('should be able to delete values', async () => {
|
|
@@ -52,15 +50,15 @@ export function describeAztecSet(
|
|
|
52
50
|
|
|
53
51
|
await set.delete('foo');
|
|
54
52
|
|
|
55
|
-
expect(await has('foo')).
|
|
56
|
-
expect(await has('baz')).
|
|
53
|
+
expect(await has('foo')).toBe(false);
|
|
54
|
+
expect(await has('baz')).toBe(true);
|
|
57
55
|
});
|
|
58
56
|
|
|
59
57
|
it('should be able to iterate over entries', async () => {
|
|
60
58
|
await set.add('baz');
|
|
61
59
|
await set.add('foo');
|
|
62
60
|
|
|
63
|
-
expect(await entries()).
|
|
61
|
+
expect(await entries()).toEqual(['baz', 'foo']);
|
|
64
62
|
});
|
|
65
63
|
|
|
66
64
|
it('supports range queries', async () => {
|
|
@@ -69,13 +67,13 @@ export function describeAztecSet(
|
|
|
69
67
|
await set.add('c');
|
|
70
68
|
await set.add('d');
|
|
71
69
|
|
|
72
|
-
expect(await entries({ start: 'b', end: 'c' })).
|
|
73
|
-
expect(await entries({ start: 'b' })).
|
|
74
|
-
expect(await entries({ end: 'c' })).
|
|
75
|
-
expect(await entries({ start: 'b', end: 'c', reverse: true })).
|
|
76
|
-
expect(await entries({ start: 'b', limit: 1 })).
|
|
77
|
-
expect(await entries({ start: 'b', reverse: true })).
|
|
78
|
-
expect(await entries({ end: 'b', reverse: true })).
|
|
70
|
+
expect(await entries({ start: 'b', end: 'c' })).toEqual(['b']);
|
|
71
|
+
expect(await entries({ start: 'b' })).toEqual(['b', 'c', 'd']);
|
|
72
|
+
expect(await entries({ end: 'c' })).toEqual(['a', 'b']);
|
|
73
|
+
expect(await entries({ start: 'b', end: 'c', reverse: true })).toEqual(['c']);
|
|
74
|
+
expect(await entries({ start: 'b', limit: 1 })).toEqual(['b']);
|
|
75
|
+
expect(await entries({ start: 'b', reverse: true })).toEqual(['d', 'c']);
|
|
76
|
+
expect(await entries({ end: 'b', reverse: true })).toEqual(['b', 'a']);
|
|
79
77
|
});
|
|
80
78
|
});
|
|
81
79
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { expect } from 'chai';
|
|
2
|
-
|
|
3
1
|
import type { AztecAsyncSingleton, AztecSingleton } from './singleton.js';
|
|
4
2
|
import type { AztecAsyncKVStore, AztecKVStore } from './store.js';
|
|
5
3
|
import { isSyncStore } from './utils.js';
|
|
@@ -29,18 +27,18 @@ export function describeAztecSingleton(
|
|
|
29
27
|
}
|
|
30
28
|
|
|
31
29
|
it('returns undefined if the value is not set', async () => {
|
|
32
|
-
expect(await get()).
|
|
30
|
+
expect(await get()).toBe(undefined);
|
|
33
31
|
});
|
|
34
32
|
|
|
35
33
|
it('should be able to set and get values', async () => {
|
|
36
|
-
expect(await singleton.set('foo')).
|
|
37
|
-
expect(await get()).
|
|
34
|
+
expect(await singleton.set('foo')).toBe(true);
|
|
35
|
+
expect(await get()).toBe('foo');
|
|
38
36
|
});
|
|
39
37
|
|
|
40
38
|
it('overwrites the value if it is set again', async () => {
|
|
41
|
-
expect(await singleton.set('foo')).
|
|
42
|
-
expect(await singleton.set('bar')).
|
|
43
|
-
expect(await get()).
|
|
39
|
+
expect(await singleton.set('foo')).toBe(true);
|
|
40
|
+
expect(await singleton.set('bar')).toBe(true);
|
|
41
|
+
expect(await get()).toBe('bar');
|
|
44
42
|
});
|
|
45
43
|
});
|
|
46
44
|
}
|
package/src/interfaces/utils.ts
CHANGED
package/src/lmdb/index.ts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
2
|
+
import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
|
|
2
3
|
|
|
3
4
|
import { join } from 'path';
|
|
4
5
|
|
|
5
|
-
import
|
|
6
|
-
import { initStoreForRollup } from '../utils.js';
|
|
6
|
+
import { initStoreForRollupAndSchemaVersion } from '../utils.js';
|
|
7
7
|
import { AztecLmdbStore } from './store.js';
|
|
8
8
|
|
|
9
9
|
export { AztecLmdbStore } from './store.js';
|
|
10
10
|
|
|
11
|
-
export function createStore(
|
|
11
|
+
export function createStore(
|
|
12
|
+
name: string,
|
|
13
|
+
config: DataStoreConfig,
|
|
14
|
+
schemaVersion: number | undefined = undefined,
|
|
15
|
+
log: Logger = createLogger('kv-store'),
|
|
16
|
+
) {
|
|
12
17
|
let { dataDirectory } = config;
|
|
13
18
|
if (typeof dataDirectory !== 'undefined') {
|
|
14
19
|
dataDirectory = join(dataDirectory, name);
|
|
@@ -21,8 +26,8 @@ export function createStore(name: string, config: DataStoreConfig, log: Logger =
|
|
|
21
26
|
);
|
|
22
27
|
|
|
23
28
|
const store = AztecLmdbStore.open(dataDirectory, config.dataStoreMapSizeKb, false);
|
|
24
|
-
if (config.
|
|
25
|
-
return
|
|
29
|
+
if (config.rollupAddress) {
|
|
30
|
+
return initStoreForRollupAndSchemaVersion(store, schemaVersion, config.rollupAddress, log);
|
|
26
31
|
}
|
|
27
32
|
return store;
|
|
28
33
|
}
|
package/src/lmdb/multi_map.ts
CHANGED
|
@@ -29,6 +29,22 @@ export class LmdbAztecMultiMap<K extends Key, V extends Value>
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
getValueCountAsync(key: K): Promise<number> {
|
|
33
|
+
const transaction = this.db.useReadTransaction();
|
|
34
|
+
try {
|
|
35
|
+
const values = this.db.getValues(this.slot(key), {
|
|
36
|
+
transaction,
|
|
37
|
+
});
|
|
38
|
+
let count = 0;
|
|
39
|
+
for (const _ of values) {
|
|
40
|
+
count++;
|
|
41
|
+
}
|
|
42
|
+
return Promise.resolve(count);
|
|
43
|
+
} finally {
|
|
44
|
+
transaction.done();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
32
48
|
async deleteValue(key: K, val: V): Promise<void> {
|
|
33
49
|
await this.db.remove(this.slot(key), [key, val]);
|
|
34
50
|
}
|
package/src/lmdb/store.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { randomBytes } from '@aztec/foundation/crypto';
|
|
1
|
+
import { randomBytes } from '@aztec/foundation/crypto/random';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
3
|
|
|
4
4
|
import { promises as fs, mkdirSync } from 'fs';
|
|
@@ -147,21 +147,25 @@ export class AztecLmdbStore implements AztecKVStore, AztecAsyncKVStore {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
/**
|
|
150
|
-
* Clears all entries in the store & sub DBs.
|
|
150
|
+
* Clears all entries in the store & sub DBs atomically within a single transaction.
|
|
151
151
|
*/
|
|
152
152
|
async clear() {
|
|
153
|
-
await this.#
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
await this.#rootDb.transaction(async () => {
|
|
154
|
+
await this.#data.clearAsync();
|
|
155
|
+
await this.#multiMapData.clearAsync();
|
|
156
|
+
await this.#rootDb.clearAsync();
|
|
157
|
+
});
|
|
156
158
|
}
|
|
157
159
|
|
|
158
160
|
/**
|
|
159
|
-
* Drops the database & sub DBs.
|
|
161
|
+
* Drops the database & sub DBs atomically within a single transaction.
|
|
160
162
|
*/
|
|
161
163
|
async drop() {
|
|
162
|
-
await this.#
|
|
163
|
-
|
|
164
|
-
|
|
164
|
+
await this.#rootDb.transaction(async () => {
|
|
165
|
+
await this.#data.drop();
|
|
166
|
+
await this.#multiMapData.drop();
|
|
167
|
+
await this.#rootDb.drop();
|
|
168
|
+
});
|
|
165
169
|
}
|
|
166
170
|
|
|
167
171
|
/**
|
package/src/lmdb-v2/array.ts
CHANGED
|
@@ -4,8 +4,8 @@ import type { AztecAsyncArray } from '../interfaces/array.js';
|
|
|
4
4
|
import type { Value } from '../interfaces/common.js';
|
|
5
5
|
import type { AztecAsyncSingleton } from '../interfaces/singleton.js';
|
|
6
6
|
import type { ReadTransaction } from './read_transaction.js';
|
|
7
|
-
|
|
8
|
-
import {
|
|
7
|
+
import type { AztecLMDBStoreV2 } from './store.js';
|
|
8
|
+
import { execInReadTx, execInWriteTx } from './tx-helpers.js';
|
|
9
9
|
import { deserializeKey, serializeKey } from './utils.js';
|
|
10
10
|
|
|
11
11
|
export class LMDBArray<T extends Value> implements AztecAsyncArray<T> {
|