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