@event-driven-io/emmett 0.23.0-alpha.5 → 0.23.0-alpha.7

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/dist/index.js CHANGED
@@ -17,18 +17,6 @@ import {
17
17
  parseDateFromUtcYYYYMMDD
18
18
  } from "./chunk-AEEEXE2R.js";
19
19
 
20
- // src/eventStore/eventStore.ts
21
- var canCreateEventStoreSession = (eventStore) => "withSession" in eventStore;
22
- var nulloSessionFactory = (eventStore) => ({
23
- withSession: (callback) => {
24
- const nulloSession = {
25
- eventStore,
26
- close: () => Promise.resolve()
27
- };
28
- return callback(nulloSession);
29
- }
30
- });
31
-
32
20
  // src/typing/command.ts
33
21
  var command = (type, data, metadata) => {
34
22
  return {
@@ -94,6 +82,25 @@ var accept = () => {
94
82
  return { kind: "Accept" };
95
83
  };
96
84
 
85
+ // src/eventStore/afterCommit/afterEventStoreCommitHandler.ts
86
+ async function tryPublishMessagesAfterCommit(messages, options, context) {
87
+ if (options?.onAfterCommit === void 0) return false;
88
+ try {
89
+ await options?.onAfterCommit(messages, context);
90
+ return true;
91
+ } catch (error2) {
92
+ console.error(`Error in on after commit hook`, error2);
93
+ return false;
94
+ }
95
+ }
96
+
97
+ // src/eventStore/afterCommit/forwardToMessageBus.ts
98
+ var forwardToMessageBus = (eventPublisher) => async (messages) => {
99
+ for (const message of messages) {
100
+ await eventPublisher.publish(message);
101
+ }
102
+ };
103
+
97
104
  // src/eventStore/events/index.ts
98
105
  var GlobalStreamCaughtUpType = "__emt:GlobalStreamCaughtUp";
99
106
  var isGlobalStreamCaughtUp = (event2) => event2.type === GlobalStreamCaughtUpType;
@@ -104,6 +111,18 @@ var globalStreamCaughtUp = (data) => event(GlobalStreamCaughtUpType, data, {
104
111
  var isSubscriptionEvent = (event2) => isGlobalStreamCaughtUp(event2);
105
112
  var isNotInternalEvent = (event2) => !isGlobalStreamCaughtUp(event2);
106
113
 
114
+ // src/eventStore/eventStore.ts
115
+ var canCreateEventStoreSession = (eventStore) => "withSession" in eventStore;
116
+ var nulloSessionFactory = (eventStore) => ({
117
+ withSession: (callback) => {
118
+ const nulloSession = {
119
+ eventStore,
120
+ close: () => Promise.resolve()
121
+ };
122
+ return callback(nulloSession);
123
+ }
124
+ });
125
+
107
126
  // src/eventStore/expectedVersion.ts
108
127
  var STREAM_EXISTS = "STREAM_EXISTS";
109
128
  var STREAM_DOES_NOT_EXIST = "STREAM_DOES_NOT_EXIST";
@@ -257,7 +276,7 @@ var StreamingCoordinator = () => {
257
276
 
258
277
  // src/eventStore/inMemoryEventStore.ts
259
278
  var InMemoryEventStoreDefaultStreamVersion = 0n;
260
- var getInMemoryEventStore = () => {
279
+ var getInMemoryEventStore = (eventStoreOptions) => {
261
280
  const streams = /* @__PURE__ */ new Map();
262
281
  const streamingCoordinator = StreamingCoordinator();
263
282
  const getAllEventsCount = () => {
@@ -325,6 +344,7 @@ var getInMemoryEventStore = () => {
325
344
  nextExpectedStreamVersion: positionOfLastEventInTheStream,
326
345
  createdNewStream: currentStreamVersion === InMemoryEventStoreDefaultStreamVersion
327
346
  };
347
+ await tryPublishMessagesAfterCommit(newEvents, eventStoreOptions?.hooks);
328
348
  return result;
329
349
  }
330
350
  //streamEvents: streamingCoordinator.stream,
@@ -371,6 +391,178 @@ var sum = (iterator) => {
371
391
  return sum2;
372
392
  };
373
393
 
394
+ // src/taskProcessing/taskProcessor.ts
395
+ var TaskProcessor = class {
396
+ constructor(options) {
397
+ this.options = options;
398
+ }
399
+ queue = [];
400
+ isProcessing = false;
401
+ activeTasks = 0;
402
+ activeGroups = /* @__PURE__ */ new Set();
403
+ enqueue(task, options) {
404
+ if (this.queue.length >= this.options.maxQueueSize) {
405
+ return Promise.reject(
406
+ new EmmettError(
407
+ "Too many pending connections. Please try again later."
408
+ )
409
+ );
410
+ }
411
+ return this.schedule(task, options);
412
+ }
413
+ waitForEndOfProcessing() {
414
+ return this.schedule(({ ack }) => Promise.resolve(ack()));
415
+ }
416
+ schedule(task, options) {
417
+ return promiseWithDeadline(
418
+ (resolve, reject) => {
419
+ const taskWithContext = () => {
420
+ return new Promise((resolveTask, failTask) => {
421
+ const taskPromise = task({
422
+ ack: resolveTask
423
+ });
424
+ taskPromise.then(resolve).catch((err) => {
425
+ failTask(err);
426
+ reject(err);
427
+ });
428
+ });
429
+ };
430
+ this.queue.push({ task: taskWithContext, options });
431
+ if (!this.isProcessing) {
432
+ this.ensureProcessing();
433
+ }
434
+ },
435
+ { deadline: this.options.maxTaskIdleTime }
436
+ );
437
+ }
438
+ ensureProcessing() {
439
+ if (this.isProcessing) return;
440
+ this.isProcessing = true;
441
+ this.processQueue();
442
+ }
443
+ processQueue() {
444
+ try {
445
+ while (this.activeTasks < this.options.maxActiveTasks && this.queue.length > 0) {
446
+ const item = this.takeFirstAvailableItem();
447
+ if (item === null) return;
448
+ const groupId = item.options?.taskGroupId;
449
+ if (groupId) {
450
+ this.activeGroups.add(groupId);
451
+ }
452
+ this.activeTasks++;
453
+ void this.executeItem(item);
454
+ }
455
+ } catch (error2) {
456
+ console.error(error2);
457
+ throw error2;
458
+ } finally {
459
+ this.isProcessing = false;
460
+ if (this.hasItemsToProcess() && this.activeTasks < this.options.maxActiveTasks) {
461
+ this.ensureProcessing();
462
+ }
463
+ }
464
+ }
465
+ async executeItem({ task, options }) {
466
+ try {
467
+ await task();
468
+ } finally {
469
+ this.activeTasks--;
470
+ if (options && options.taskGroupId) {
471
+ this.activeGroups.delete(options.taskGroupId);
472
+ }
473
+ this.ensureProcessing();
474
+ }
475
+ }
476
+ takeFirstAvailableItem = () => {
477
+ const taskIndex = this.queue.findIndex(
478
+ (item2) => !item2.options?.taskGroupId || !this.activeGroups.has(item2.options.taskGroupId)
479
+ );
480
+ if (taskIndex === -1) {
481
+ return null;
482
+ }
483
+ const [item] = this.queue.splice(taskIndex, 1);
484
+ return item ?? null;
485
+ };
486
+ hasItemsToProcess = () => this.queue.findIndex(
487
+ (item) => !item.options?.taskGroupId || !this.activeGroups.has(item.options.taskGroupId)
488
+ ) !== -1;
489
+ };
490
+ var DEFAULT_PROMISE_DEADLINE = 2147483647;
491
+ var promiseWithDeadline = (executor, options) => {
492
+ return new Promise((resolve, reject) => {
493
+ let taskStarted = false;
494
+ const maxWaitingTime = options.deadline || DEFAULT_PROMISE_DEADLINE;
495
+ let timeoutId = setTimeout(() => {
496
+ if (!taskStarted) {
497
+ reject(
498
+ new Error("Task was not started within the maximum waiting time")
499
+ );
500
+ }
501
+ }, maxWaitingTime);
502
+ executor((value) => {
503
+ taskStarted = true;
504
+ if (timeoutId) {
505
+ clearTimeout(timeoutId);
506
+ }
507
+ timeoutId = null;
508
+ resolve(value);
509
+ }, reject);
510
+ });
511
+ };
512
+
513
+ // src/utils/locking/index.ts
514
+ var InProcessLock = () => {
515
+ const taskProcessor = new TaskProcessor({
516
+ maxActiveTasks: Number.MAX_VALUE,
517
+ maxQueueSize: Number.MAX_VALUE
518
+ });
519
+ const locks = /* @__PURE__ */ new Map();
520
+ return {
521
+ async acquire({ lockId }) {
522
+ await new Promise((resolve, reject) => {
523
+ taskProcessor.enqueue(
524
+ ({ ack }) => {
525
+ locks.set(lockId, ack);
526
+ resolve();
527
+ return Promise.resolve();
528
+ },
529
+ { taskGroupId: lockId }
530
+ ).catch(reject);
531
+ });
532
+ },
533
+ async tryAcquire({ lockId }) {
534
+ if (locks.has(lockId)) {
535
+ return false;
536
+ }
537
+ await this.acquire({ lockId });
538
+ return true;
539
+ },
540
+ release({ lockId }) {
541
+ const ack = locks.get(lockId);
542
+ if (ack === void 0) {
543
+ return Promise.resolve(true);
544
+ }
545
+ locks.delete(lockId);
546
+ ack();
547
+ return Promise.resolve(true);
548
+ },
549
+ async withAcquire(handle, { lockId }) {
550
+ return taskProcessor.enqueue(
551
+ async ({ ack }) => {
552
+ locks.set(lockId, ack);
553
+ try {
554
+ return await handle();
555
+ } finally {
556
+ locks.delete(lockId);
557
+ ack();
558
+ }
559
+ },
560
+ { taskGroupId: lockId }
561
+ );
562
+ }
563
+ };
564
+ };
565
+
374
566
  // src/utils/merge.ts
375
567
  var merge = (array, item, where, onExisting, onNotFound = () => void 0) => {
376
568
  let wasFound = false;
@@ -1317,6 +1509,7 @@ export {
1317
1509
  GlobalStreamCaughtUpType,
1318
1510
  IllegalStateError,
1319
1511
  InMemoryEventStoreDefaultStreamVersion,
1512
+ InProcessLock,
1320
1513
  JSONParser,
1321
1514
  JsonDecoder,
1322
1515
  NO_CONCURRENCY_CHECK,
@@ -1328,6 +1521,7 @@ export {
1328
1521
  STREAM_EXISTS,
1329
1522
  StreamingCoordinator,
1330
1523
  StringDecoder,
1524
+ TaskProcessor,
1331
1525
  ValidationError,
1332
1526
  ValidationErrors,
1333
1527
  WrapEventStore,
@@ -1367,6 +1561,7 @@ export {
1367
1561
  error,
1368
1562
  event,
1369
1563
  formatDateToUtcYYYYMMDD,
1564
+ forwardToMessageBus,
1370
1565
  getInMemoryEventStore,
1371
1566
  getInMemoryMessageBus,
1372
1567
  globalStreamCaughtUp,
@@ -1398,6 +1593,7 @@ export {
1398
1593
  streamTrackingGlobalPosition,
1399
1594
  streamTransformations,
1400
1595
  sum,
1596
+ tryPublishMessagesAfterCommit,
1401
1597
  verifyThat
1402
1598
  };
1403
1599
  //# sourceMappingURL=index.js.map