event-storage 0.8.0 → 0.9.1
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 +50 -541
- package/package.json +22 -21
- package/src/Clock.js +20 -8
- package/src/EventStore.js +244 -51
- package/src/EventStream.js +169 -16
- package/src/Index/ReadableIndex.js +9 -3
- package/src/Index/WritableIndex.js +10 -4
- package/src/JoinEventStream.js +32 -30
- package/src/Partition/ReadablePartition.js +105 -46
- package/src/Partition/WritablePartition.js +73 -14
- package/src/Storage/ReadableStorage.js +136 -13
- package/src/Storage/WritableStorage.js +169 -24
- package/src/Watcher.js +1 -0
- package/src/WatchesFile.js +6 -5
- package/src/metadataUtil.js +79 -0
- package/src/util.js +71 -70
- package/test/Consumer.spec.js +0 -455
- package/test/EventStore.spec.js +0 -632
- package/test/EventStream.spec.js +0 -120
- package/test/Index.spec.js +0 -591
- package/test/JoinEventStream.spec.js +0 -113
- package/test/Partition.spec.js +0 -488
- package/test/Storage.spec.js +0 -1017
- package/test/Watcher.spec.js +0 -131
package/test/EventStore.spec.js
DELETED
|
@@ -1,632 +0,0 @@
|
|
|
1
|
-
const expect = require('expect.js');
|
|
2
|
-
const fs = require('fs-extra');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const EventStore = require('../src/EventStore');
|
|
5
|
-
|
|
6
|
-
const storageDirectory = __dirname + '/data';
|
|
7
|
-
|
|
8
|
-
describe('EventStore', function() {
|
|
9
|
-
|
|
10
|
-
let eventstore;
|
|
11
|
-
|
|
12
|
-
beforeEach(function () {
|
|
13
|
-
fs.emptyDirSync(storageDirectory);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
afterEach(function () {
|
|
17
|
-
if (eventstore) {
|
|
18
|
-
eventstore.close();
|
|
19
|
-
}
|
|
20
|
-
eventstore = null;
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('basically works', function(done) {
|
|
24
|
-
eventstore = new EventStore({
|
|
25
|
-
storageDirectory
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
let events = [{foo: 'bar'}, {foo: 'baz'}, {foo: 'quux'}];
|
|
29
|
-
eventstore.on('ready', () => {
|
|
30
|
-
eventstore.commit('foo-bar', events, () => {
|
|
31
|
-
const stream = eventstore.getEventStream('foo-bar');
|
|
32
|
-
let i = 0;
|
|
33
|
-
for (let event of stream) {
|
|
34
|
-
expect(event).to.eql(events[i++]);
|
|
35
|
-
}
|
|
36
|
-
done();
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('can be created with custom name', function(done) {
|
|
42
|
-
eventstore = new EventStore('custom-store', {
|
|
43
|
-
storageDirectory
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
eventstore.commit('foo-bar', [{ type: 'foo'}], () => {
|
|
47
|
-
expect(fs.existsSync(path.join(storageDirectory, 'custom-store.foo-bar'))).to.be(true);
|
|
48
|
-
done();
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('throws when scanning of stream directory fails', function() {
|
|
53
|
-
const fs = require('fs');
|
|
54
|
-
const originalReaddir = fs.readdir;
|
|
55
|
-
fs.readdir = (dir, callback) => callback(new Error('Something went wrong!'), null);
|
|
56
|
-
|
|
57
|
-
expect(() => new EventStore({
|
|
58
|
-
storageDirectory
|
|
59
|
-
})).to.throwError(/Something went wrong!/);
|
|
60
|
-
fs.readdir = originalReaddir;
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('repairs torn writes', function(done) {
|
|
64
|
-
eventstore = new EventStore({
|
|
65
|
-
storageDirectory
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
const events = [{foo: 'bar'.repeat(500)}];
|
|
69
|
-
eventstore.on('ready', () => {
|
|
70
|
-
eventstore.commit('foo-bar', events, () => {
|
|
71
|
-
// Simulate a torn write (but indexes are still written)
|
|
72
|
-
fs.truncateSync(eventstore.storage.getPartition('foo-bar').fileName, 512);
|
|
73
|
-
|
|
74
|
-
// The previous instance was not closed, so the lock still exists
|
|
75
|
-
eventstore = new EventStore({
|
|
76
|
-
storageDirectory,
|
|
77
|
-
storageConfig: {
|
|
78
|
-
lock: EventStore.LOCK_RECLAIM
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
eventstore.on('ready', () => {
|
|
82
|
-
expect(eventstore.length).to.be(0);
|
|
83
|
-
expect(eventstore.getStreamVersion('foo-bar')).to.be(0);
|
|
84
|
-
done();
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('throws when trying to open non-existing store read-only', function() {
|
|
91
|
-
expect(() => new EventStore({
|
|
92
|
-
storageDirectory,
|
|
93
|
-
readOnly: true
|
|
94
|
-
})).to.throwError();
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('can open read-only', function(done) {
|
|
98
|
-
eventstore = new EventStore({
|
|
99
|
-
storageDirectory
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
let events = [{foo: 'bar'}, {foo: 'baz'}, {foo: 'quux'}];
|
|
103
|
-
eventstore.on('ready', () => {
|
|
104
|
-
eventstore.commit('foo-bar', events, () => {
|
|
105
|
-
let readstore = new EventStore({
|
|
106
|
-
storageDirectory,
|
|
107
|
-
readOnly: true
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
readstore.on('ready', () => {
|
|
111
|
-
const stream = readstore.getEventStream('foo-bar');
|
|
112
|
-
let i = 0;
|
|
113
|
-
for (let event of stream) {
|
|
114
|
-
expect(event).to.eql(events[i++]);
|
|
115
|
-
}
|
|
116
|
-
readstore.close();
|
|
117
|
-
done();
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
describe('commit', function() {
|
|
124
|
-
|
|
125
|
-
it('throws when no stream name specified', function() {
|
|
126
|
-
eventstore = new EventStore({
|
|
127
|
-
storageDirectory
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
expect(() => eventstore.commit({ foo: 'bar' })).to.throwError();
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('throws when no events specified', function() {
|
|
134
|
-
eventstore = new EventStore({
|
|
135
|
-
storageDirectory
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
expect(() => eventstore.commit('foo-bar')).to.throwError();
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it('throws when opened in read-only mode', function() {
|
|
142
|
-
eventstore = new EventStore({
|
|
143
|
-
storageDirectory
|
|
144
|
-
});
|
|
145
|
-
eventstore.close();
|
|
146
|
-
|
|
147
|
-
eventstore = new EventStore({
|
|
148
|
-
storageDirectory,
|
|
149
|
-
readOnly: true
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
expect(() => eventstore.commit('foo-bar', { foo: 'bar' })).to.throwError();
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('can commit a single event', function() {
|
|
156
|
-
eventstore = new EventStore({
|
|
157
|
-
storageDirectory
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
eventstore.commit('foo-bar', { foo: 'bar' });
|
|
161
|
-
expect(eventstore.length).to.be(1);
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it('can commit multiple events at once', function() {
|
|
165
|
-
eventstore = new EventStore({
|
|
166
|
-
storageDirectory
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
eventstore.commit('foo-bar', [{ foo: 'bar' }, { bar: 'baz' }, { baz: 'quux' }]);
|
|
170
|
-
expect(eventstore.length).to.be(3);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it('invokes callback when finished', function(done) {
|
|
174
|
-
eventstore = new EventStore({
|
|
175
|
-
storageDirectory
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
eventstore.commit('foo-bar', [{ foo: 'bar' }], (commit) => {
|
|
179
|
-
expect(eventstore.length).to.be(1);
|
|
180
|
-
expect(commit.streamName).to.be('foo-bar');
|
|
181
|
-
expect(commit.streamVersion).to.be(0);
|
|
182
|
-
expect(commit.events).to.eql([{ foo: 'bar' }]);
|
|
183
|
-
done();
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it('invokes callback when finished with optimistic concurrency check', function(done) {
|
|
188
|
-
eventstore = new EventStore({
|
|
189
|
-
storageDirectory
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
eventstore.commit('foo-bar', [{ foo: 'bar' }], EventStore.ExpectedVersion.EmptyStream, (commit) => {
|
|
193
|
-
expect(eventstore.length).to.be(1);
|
|
194
|
-
expect(commit.streamName).to.be('foo-bar');
|
|
195
|
-
expect(commit.streamVersion).to.be(0);
|
|
196
|
-
expect(commit.events).to.eql([{ foo: 'bar' }]);
|
|
197
|
-
done();
|
|
198
|
-
});
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
it('invokes callback when finished with optimistic concurrency check and metdata', function(done) {
|
|
202
|
-
eventstore = new EventStore({
|
|
203
|
-
storageDirectory
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
eventstore.commit('foo-bar', [{ foo: 'bar' }], EventStore.ExpectedVersion.EmptyStream, {}, (commit) => {
|
|
207
|
-
expect(eventstore.length).to.be(1);
|
|
208
|
-
expect(commit.streamName).to.be('foo-bar');
|
|
209
|
-
expect(commit.streamVersion).to.be(0);
|
|
210
|
-
expect(commit.events).to.eql([{ foo: 'bar' }]);
|
|
211
|
-
done();
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
it('invokes "commit" event when finished', function(done) {
|
|
216
|
-
eventstore = new EventStore({
|
|
217
|
-
storageDirectory
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
eventstore.on('commit', (commit) => {
|
|
221
|
-
expect(eventstore.length).to.be(1);
|
|
222
|
-
expect(commit.streamName).to.be('foo-bar');
|
|
223
|
-
expect(commit.streamVersion).to.be(0);
|
|
224
|
-
expect(commit.events).to.eql([{ foo: 'bar' }]);
|
|
225
|
-
done();
|
|
226
|
-
});
|
|
227
|
-
eventstore.commit('foo-bar', [{ foo: 'bar' }]);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
it('throws an optimistic concurrency error if stream version does not match', function(done) {
|
|
231
|
-
eventstore = new EventStore({
|
|
232
|
-
storageDirectory
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
expect(() => eventstore.commit('foo-bar', { foo: 'bar' }, 1)).to.throwError(
|
|
236
|
-
e => expect(e).to.be.a(EventStore.OptimisticConcurrencyError)
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
eventstore.commit('foo-bar', { foo: 'bar' }, () => {
|
|
240
|
-
expect(() => eventstore.commit('foo-bar', { foo: 'baz' }, EventStore.ExpectedVersion.EmptyStream)).to.throwError(
|
|
241
|
-
e => expect(e).to.be.a(EventStore.OptimisticConcurrencyError)
|
|
242
|
-
);
|
|
243
|
-
expect(() => eventstore.commit('foo-bar', { foo: 'baz' }, 2)).to.throwError(
|
|
244
|
-
e => expect(e).to.be.a(EventStore.OptimisticConcurrencyError)
|
|
245
|
-
);
|
|
246
|
-
done();
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('does not throw an optimistic concurrency error if stream version matches', function(done) {
|
|
251
|
-
eventstore = new EventStore({
|
|
252
|
-
storageDirectory
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
expect(() => eventstore.commit('foo-bar', { foo: 'bar' }, EventStore.ExpectedVersion.EmptyStream)).to.not.throwError();
|
|
256
|
-
|
|
257
|
-
eventstore.commit('foo-bar', { foo: 'bar' }, () => {
|
|
258
|
-
expect(() => eventstore.commit('foo-bar', {foo: 'baz'}, 2)).to.not.throwError();
|
|
259
|
-
expect(() => eventstore.commit('foo-bar', {foo: 'baz'}, EventStore.ExpectedVersion.Any)).to.not.throwError();
|
|
260
|
-
done();
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it('uses metadata from argument for commit', function(done) {
|
|
265
|
-
eventstore = new EventStore({
|
|
266
|
-
storageDirectory
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
eventstore.commit('foo-bar', [{ foo: 'bar' }], { commitId: 1, committedAt: 12345, quux: 'quux' }, (commit) => {
|
|
270
|
-
expect(commit.commitId).to.be(1);
|
|
271
|
-
expect(commit.committedAt).to.be(12345);
|
|
272
|
-
expect(commit.quux).to.be('quux');
|
|
273
|
-
|
|
274
|
-
const stream = eventstore.getEventStream('foo-bar');
|
|
275
|
-
const storedEvent = stream.next();
|
|
276
|
-
expect(storedEvent.metadata.commitId).to.be(1);
|
|
277
|
-
expect(storedEvent.metadata.committedAt).to.be(12345);
|
|
278
|
-
expect(storedEvent.metadata.quux).to.be('quux');
|
|
279
|
-
done();
|
|
280
|
-
});
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
describe('createEventStream', function() {
|
|
286
|
-
|
|
287
|
-
it('throws when trying to recreate existing stream', function(done) {
|
|
288
|
-
eventstore = new EventStore({
|
|
289
|
-
storageDirectory
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
eventstore.commit('foo-bar', [{ type: 'foo' }], () => {
|
|
293
|
-
expect(() => eventstore.createEventStream('foo-bar', event => event.payload.type === 'foo')).to.throwError();
|
|
294
|
-
done();
|
|
295
|
-
});
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
it('can create new streams on existing events', function(done) {
|
|
299
|
-
eventstore = new EventStore({
|
|
300
|
-
storageDirectory
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
eventstore.commit('foo-bar', [{ type: 'foo' }], () => {
|
|
304
|
-
const stream = eventstore.createEventStream('my-foo-bar', event => event.payload.type === 'foo');
|
|
305
|
-
expect(stream.events.length).to.be(1);
|
|
306
|
-
expect(stream.events[0]).to.eql({ type: 'foo' });
|
|
307
|
-
done();
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
describe('getStreamVersion', function() {
|
|
314
|
-
|
|
315
|
-
it('returns -1 if the stream does not exist', function() {
|
|
316
|
-
eventstore = new EventStore({
|
|
317
|
-
storageDirectory
|
|
318
|
-
});
|
|
319
|
-
expect(eventstore.getStreamVersion('foo')).to.be(-1);
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
it('returns 0 if the stream is empty', function() {
|
|
323
|
-
eventstore = new EventStore({
|
|
324
|
-
storageDirectory
|
|
325
|
-
});
|
|
326
|
-
eventstore.createEventStream('foo', () => true);
|
|
327
|
-
expect(eventstore.getStreamVersion('foo')).to.be(0);
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
it('returns the version of the stream', function(done) {
|
|
331
|
-
eventstore = new EventStore({
|
|
332
|
-
storageDirectory
|
|
333
|
-
});
|
|
334
|
-
eventstore.commit('foo', [{ type: 'foo' }], () => {
|
|
335
|
-
expect(eventstore.getStreamVersion('foo')).to.be(1);
|
|
336
|
-
done();
|
|
337
|
-
});
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
describe('getEventStream', function() {
|
|
343
|
-
|
|
344
|
-
it('can open existing streams', function(done) {
|
|
345
|
-
eventstore = new EventStore({
|
|
346
|
-
storageDirectory
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
eventstore.commit('foo-bar', [{ foo: 'bar' }]);
|
|
350
|
-
eventstore.close();
|
|
351
|
-
|
|
352
|
-
eventstore = new EventStore({
|
|
353
|
-
storageDirectory
|
|
354
|
-
});
|
|
355
|
-
eventstore.on('ready', () => {
|
|
356
|
-
const stream = eventstore.getEventStream('foo-bar');
|
|
357
|
-
expect(stream.events.length).to.be(1);
|
|
358
|
-
done();
|
|
359
|
-
});
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
it('can iterate events in reverse order', function() {
|
|
363
|
-
eventstore = new EventStore({
|
|
364
|
-
storageDirectory
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
for (let i=1; i<=20; i++) {
|
|
368
|
-
eventstore.commit('foo-bar', [{key: i}]);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
let reverseStream = eventstore.getEventStream('foo-bar', -1, 0);
|
|
372
|
-
let i = 20;
|
|
373
|
-
for (let event of reverseStream) {
|
|
374
|
-
expect(event).to.eql({ key: i-- });
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
it('can open streams created in writer', function(done) {
|
|
379
|
-
eventstore = new EventStore({
|
|
380
|
-
storageDirectory
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
const readstore = new EventStore({
|
|
384
|
-
storageDirectory,
|
|
385
|
-
readOnly: true
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
expect(readstore.getStreamVersion('foo')).to.be(-1);
|
|
389
|
-
|
|
390
|
-
readstore.on('stream-available', (streamName) => {
|
|
391
|
-
if (streamName === 'foo') {
|
|
392
|
-
expect(readstore.getStreamVersion('foo')).to.be(0);
|
|
393
|
-
readstore.close();
|
|
394
|
-
done();
|
|
395
|
-
}
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
eventstore.createEventStream('foo', { type: 'foo' });
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
it('needs to be tested further.');
|
|
402
|
-
});
|
|
403
|
-
|
|
404
|
-
describe('getAllEvents', function() {
|
|
405
|
-
|
|
406
|
-
it('returns stream for all events', function (done) {
|
|
407
|
-
eventstore = new EventStore({
|
|
408
|
-
storageDirectory
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
for (let i=1; i<=20; i++) {
|
|
412
|
-
eventstore.commit('foo-bar', [{key: i}]);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
eventstore.on('ready', () => {
|
|
416
|
-
const stream = eventstore.getAllEvents();
|
|
417
|
-
expect(stream.events.length).to.be(20);
|
|
418
|
-
done();
|
|
419
|
-
});
|
|
420
|
-
});
|
|
421
|
-
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
describe('fromStreams', function() {
|
|
425
|
-
|
|
426
|
-
it('throws when not specifying a join stream name', function() {
|
|
427
|
-
eventstore = new EventStore({
|
|
428
|
-
storageDirectory
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
expect(() => eventstore.fromStreams()).to.throwError();
|
|
432
|
-
});
|
|
433
|
-
|
|
434
|
-
it('throws when not specifying an array of stream names to join', function() {
|
|
435
|
-
eventstore = new EventStore({
|
|
436
|
-
storageDirectory
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
expect(() => eventstore.fromStreams('join-foo-bar')).to.throwError();
|
|
440
|
-
});
|
|
441
|
-
|
|
442
|
-
it('throws when specifying a non-existing stream to join', function() {
|
|
443
|
-
eventstore = new EventStore({
|
|
444
|
-
storageDirectory
|
|
445
|
-
});
|
|
446
|
-
|
|
447
|
-
expect(() => eventstore.fromStreams('join-foo-bar', ['foo-bar', 'baz'])).to.throwError(/does not exist/);
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
it('iterates events from multiple streams in correct order', function(done) {
|
|
451
|
-
eventstore = new EventStore({
|
|
452
|
-
storageDirectory
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
eventstore.commit('foo', { key: 1 }, () => {
|
|
456
|
-
eventstore.commit('bar', { key: 2}, () => {
|
|
457
|
-
eventstore.commit('foo', { key: 3 }, () => {
|
|
458
|
-
eventstore.commit('bar', { key: 4}, () => {
|
|
459
|
-
let joinStream = eventstore.fromStreams('foobar', ['foo','bar']);
|
|
460
|
-
let key = 1;
|
|
461
|
-
for (let event of joinStream) {
|
|
462
|
-
expect(event.key).to.be(key);
|
|
463
|
-
key++;
|
|
464
|
-
}
|
|
465
|
-
expect(key).to.be(5);
|
|
466
|
-
done();
|
|
467
|
-
});
|
|
468
|
-
});
|
|
469
|
-
});
|
|
470
|
-
});
|
|
471
|
-
});
|
|
472
|
-
|
|
473
|
-
it('iterates events from multiple streams in reverse order', function() {
|
|
474
|
-
eventstore = new EventStore({
|
|
475
|
-
storageDirectory
|
|
476
|
-
});
|
|
477
|
-
|
|
478
|
-
for (let i=1; i<=20; i++) {
|
|
479
|
-
eventstore.commit(i % 2 ? 'foo' : 'bar', [{key: i}]);
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
let reverseStream = eventstore.fromStreams('foo-bar', ['foo', 'bar'],-1, 0);
|
|
483
|
-
let i = 20;
|
|
484
|
-
for (let event of reverseStream) {
|
|
485
|
-
expect(event).to.eql({ key: i-- });
|
|
486
|
-
}
|
|
487
|
-
expect(i).to.be(0);
|
|
488
|
-
});
|
|
489
|
-
|
|
490
|
-
});
|
|
491
|
-
|
|
492
|
-
describe('getEventStreamForCategory', function() {
|
|
493
|
-
|
|
494
|
-
it('throws when not specifying category without streams', function () {
|
|
495
|
-
eventstore = new EventStore({
|
|
496
|
-
storageDirectory
|
|
497
|
-
});
|
|
498
|
-
|
|
499
|
-
expect(() => eventstore.getEventStreamForCategory('non-existing-category')).to.throwError();
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
it('iterates events for all streams with a given category prefix', function () {
|
|
503
|
-
eventstore = new EventStore({
|
|
504
|
-
storageDirectory
|
|
505
|
-
});
|
|
506
|
-
|
|
507
|
-
eventstore.commit('bar', [{key: 0}]);
|
|
508
|
-
for (let i=1; i<=20; i++) {
|
|
509
|
-
eventstore.commit('foo-' + i, [{key: i}]);
|
|
510
|
-
}
|
|
511
|
-
eventstore.commit('foobar', [{key: 21}]);
|
|
512
|
-
|
|
513
|
-
let categoryStream = eventstore.getEventStreamForCategory('foo');
|
|
514
|
-
let i = 1;
|
|
515
|
-
for (let event of categoryStream) {
|
|
516
|
-
expect(event).to.eql({ key: i++ });
|
|
517
|
-
}
|
|
518
|
-
expect(i).to.be(21);
|
|
519
|
-
});
|
|
520
|
-
|
|
521
|
-
it('works with a dedicated stream for the category', function () {
|
|
522
|
-
eventstore = new EventStore({
|
|
523
|
-
storageDirectory
|
|
524
|
-
});
|
|
525
|
-
|
|
526
|
-
eventstore.createEventStream('foo', e => e.stream.startsWith('foo-'));
|
|
527
|
-
for (let i=1; i<=20; i++) {
|
|
528
|
-
eventstore.commit('foo-' + i, [{key: i}]);
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
let categoryStream = eventstore.getEventStreamForCategory('foo');
|
|
532
|
-
let i = 1;
|
|
533
|
-
for (let event of categoryStream) {
|
|
534
|
-
expect(event).to.eql({ key: i++ });
|
|
535
|
-
}
|
|
536
|
-
expect(i).to.be(21);
|
|
537
|
-
});
|
|
538
|
-
|
|
539
|
-
});
|
|
540
|
-
|
|
541
|
-
describe('createEventStream', function() {
|
|
542
|
-
|
|
543
|
-
it('throws in read-only mode', function () {
|
|
544
|
-
eventstore = new EventStore({
|
|
545
|
-
storageDirectory
|
|
546
|
-
});
|
|
547
|
-
|
|
548
|
-
let readstore = new EventStore({
|
|
549
|
-
storageDirectory,
|
|
550
|
-
readOnly: true
|
|
551
|
-
});
|
|
552
|
-
expect(() => readstore.createEventStream('foo-bar', () => true)).to.throwError();
|
|
553
|
-
readstore.close();
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
it('throws when trying to re-create stream', function () {
|
|
557
|
-
eventstore = new EventStore({
|
|
558
|
-
storageDirectory
|
|
559
|
-
});
|
|
560
|
-
eventstore.createEventStream('foo-bar', () => true)
|
|
561
|
-
|
|
562
|
-
expect(() => eventstore.createEventStream('foo-bar', () => true)).to.throwError();
|
|
563
|
-
});
|
|
564
|
-
});
|
|
565
|
-
|
|
566
|
-
describe('deleteEventStream', function() {
|
|
567
|
-
|
|
568
|
-
it('throws in read-only mode', function(done) {
|
|
569
|
-
eventstore = new EventStore({
|
|
570
|
-
storageDirectory
|
|
571
|
-
});
|
|
572
|
-
eventstore.createEventStream('foo-bar', () => true);
|
|
573
|
-
|
|
574
|
-
let readstore = new EventStore({
|
|
575
|
-
storageDirectory,
|
|
576
|
-
readOnly: true
|
|
577
|
-
});
|
|
578
|
-
readstore.on('ready', () => {
|
|
579
|
-
expect(() => readstore.deleteEventStream('foo-bar')).to.throwError();
|
|
580
|
-
readstore.close();
|
|
581
|
-
done();
|
|
582
|
-
});
|
|
583
|
-
});
|
|
584
|
-
|
|
585
|
-
it('removes the stream persistently', function(done) {
|
|
586
|
-
eventstore = new EventStore({
|
|
587
|
-
storageDirectory
|
|
588
|
-
});
|
|
589
|
-
|
|
590
|
-
eventstore.commit('foo-bar', [{ foo: 'bar' }], () => {
|
|
591
|
-
expect(fs.existsSync(storageDirectory + '/streams/eventstore.stream-foo-bar.index')).to.be(true);
|
|
592
|
-
eventstore.deleteEventStream('foo-bar');
|
|
593
|
-
expect(eventstore.getEventStream('foo-bar')).to.be(false);
|
|
594
|
-
expect(fs.existsSync(storageDirectory + '/streams/eventstore.stream-foo-bar.index')).to.be(false);
|
|
595
|
-
done();
|
|
596
|
-
});
|
|
597
|
-
});
|
|
598
|
-
|
|
599
|
-
it('is noop for non-existing stream', function(done) {
|
|
600
|
-
eventstore = new EventStore({
|
|
601
|
-
storageDirectory
|
|
602
|
-
});
|
|
603
|
-
|
|
604
|
-
eventstore.commit('foo-bar', [{ foo: 'bar' }], () => {
|
|
605
|
-
eventstore.deleteEventStream('bar');
|
|
606
|
-
expect(eventstore.getEventStream('foo-bar')).to.not.be(false);
|
|
607
|
-
done();
|
|
608
|
-
});
|
|
609
|
-
});
|
|
610
|
-
|
|
611
|
-
});
|
|
612
|
-
|
|
613
|
-
describe('getConsumer', function() {
|
|
614
|
-
|
|
615
|
-
it('returns a consumer for the given stream', function(done) {
|
|
616
|
-
eventstore = new EventStore({
|
|
617
|
-
storageDirectory
|
|
618
|
-
});
|
|
619
|
-
eventstore.createEventStream('foo-bar', event => event.payload.foo === 'bar');
|
|
620
|
-
|
|
621
|
-
const consumer = eventstore.getConsumer('foo-bar', 'consumer1');
|
|
622
|
-
consumer.on('data', event => {
|
|
623
|
-
expect(event.id).to.be(2);
|
|
624
|
-
done();
|
|
625
|
-
});
|
|
626
|
-
eventstore.commit('foo', { foo: 'baz', id: 1 });
|
|
627
|
-
eventstore.commit('foo', { foo: 'bar', id: 2 });
|
|
628
|
-
});
|
|
629
|
-
|
|
630
|
-
});
|
|
631
|
-
|
|
632
|
-
});
|