@event-driven-io/emmett-postgresql 0.42.0 → 0.42.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/dist/index.cjs +252 -132
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +203 -83
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -657,19 +657,39 @@ var reactor = (options) => {
|
|
|
657
657
|
type,
|
|
658
658
|
init,
|
|
659
659
|
start: async (startOptions) => {
|
|
660
|
-
if (isActive)
|
|
660
|
+
if (isActive) {
|
|
661
|
+
console.log(
|
|
662
|
+
`Processor ${processorId} with instance id ${instanceId} is already active. Start request ignored.`
|
|
663
|
+
);
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
console.log(
|
|
667
|
+
`Starting processor ${processorId} with instance id ${instanceId}`
|
|
668
|
+
);
|
|
661
669
|
await init(startOptions);
|
|
662
670
|
isActive = true;
|
|
663
671
|
closeSignal = onShutdown(() => close({}));
|
|
664
|
-
if (lastCheckpoint !== null)
|
|
672
|
+
if (lastCheckpoint !== null) {
|
|
673
|
+
console.log(
|
|
674
|
+
`Processor ${processorId} started with instance id ${instanceId}, checkpoint: ${JSONParser.stringify(lastCheckpoint)}`
|
|
675
|
+
);
|
|
665
676
|
return {
|
|
666
677
|
lastCheckpoint
|
|
667
678
|
};
|
|
679
|
+
}
|
|
668
680
|
return await processingScope(async (context) => {
|
|
669
681
|
if (hooks.onStart) {
|
|
682
|
+
console.log(
|
|
683
|
+
`Executing onStart hook for processor ${processorId} with instance id ${instanceId}`
|
|
684
|
+
);
|
|
670
685
|
await hooks.onStart(context);
|
|
671
686
|
}
|
|
672
|
-
if (startFrom && startFrom !== "CURRENT")
|
|
687
|
+
if (startFrom && startFrom !== "CURRENT") {
|
|
688
|
+
console.log(
|
|
689
|
+
`Processor ${processorId} with instance id ${instanceId} starting from: ${JSONParser.stringify(startFrom)}`
|
|
690
|
+
);
|
|
691
|
+
return startFrom;
|
|
692
|
+
}
|
|
673
693
|
if (checkpoints) {
|
|
674
694
|
const readResult = await checkpoints?.read(
|
|
675
695
|
{
|
|
@@ -680,7 +700,15 @@ var reactor = (options) => {
|
|
|
680
700
|
);
|
|
681
701
|
lastCheckpoint = readResult.lastCheckpoint;
|
|
682
702
|
}
|
|
683
|
-
if (lastCheckpoint === null)
|
|
703
|
+
if (lastCheckpoint === null) {
|
|
704
|
+
console.log(
|
|
705
|
+
`Processor ${processorId} with instance id ${instanceId} starting from: BEGINNING`
|
|
706
|
+
);
|
|
707
|
+
return "BEGINNING";
|
|
708
|
+
}
|
|
709
|
+
console.log(
|
|
710
|
+
`Checkpoint read for processor ${processorId} with instance id ${instanceId}: ${JSONParser.stringify(lastCheckpoint)}`
|
|
711
|
+
);
|
|
684
712
|
return {
|
|
685
713
|
lastCheckpoint
|
|
686
714
|
};
|
|
@@ -692,48 +720,64 @@ var reactor = (options) => {
|
|
|
692
720
|
},
|
|
693
721
|
handle: async (messages, partialContext) => {
|
|
694
722
|
if (!isActive) return Promise.resolve();
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
{
|
|
710
|
-
processorId,
|
|
711
|
-
version,
|
|
712
|
-
message: upcasted,
|
|
713
|
-
lastCheckpoint,
|
|
714
|
-
partition
|
|
715
|
-
},
|
|
723
|
+
try {
|
|
724
|
+
return await processingScope(async (context) => {
|
|
725
|
+
let result = void 0;
|
|
726
|
+
for (const message2 of messages) {
|
|
727
|
+
if (wasMessageHandled(message2, lastCheckpoint)) continue;
|
|
728
|
+
const upcasted = upcastRecordedMessage(
|
|
729
|
+
// TODO: Make it smarter
|
|
730
|
+
message2,
|
|
731
|
+
options.messageOptions?.schema?.versioning
|
|
732
|
+
);
|
|
733
|
+
if (canHandle !== void 0 && !canHandle.includes(upcasted.type))
|
|
734
|
+
continue;
|
|
735
|
+
const messageProcessingResult = await eachMessage(
|
|
736
|
+
upcasted,
|
|
716
737
|
context
|
|
717
738
|
);
|
|
718
|
-
if (
|
|
719
|
-
|
|
739
|
+
if (checkpoints) {
|
|
740
|
+
const storeCheckpointResult = await checkpoints.store(
|
|
741
|
+
{
|
|
742
|
+
processorId,
|
|
743
|
+
version,
|
|
744
|
+
message: upcasted,
|
|
745
|
+
lastCheckpoint,
|
|
746
|
+
partition
|
|
747
|
+
},
|
|
748
|
+
context
|
|
749
|
+
);
|
|
750
|
+
if (storeCheckpointResult.success) {
|
|
751
|
+
lastCheckpoint = storeCheckpointResult.newCheckpoint;
|
|
752
|
+
}
|
|
720
753
|
}
|
|
754
|
+
if (messageProcessingResult && messageProcessingResult.type === "STOP") {
|
|
755
|
+
isActive = false;
|
|
756
|
+
result = messageProcessingResult;
|
|
757
|
+
break;
|
|
758
|
+
}
|
|
759
|
+
if (stopAfter && stopAfter(upcasted)) {
|
|
760
|
+
isActive = false;
|
|
761
|
+
result = { type: "STOP", reason: "Stop condition reached" };
|
|
762
|
+
break;
|
|
763
|
+
}
|
|
764
|
+
if (messageProcessingResult && messageProcessingResult.type === "SKIP")
|
|
765
|
+
continue;
|
|
721
766
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
}, partialContext);
|
|
767
|
+
return result;
|
|
768
|
+
}, partialContext);
|
|
769
|
+
} catch (error2) {
|
|
770
|
+
console.log(
|
|
771
|
+
`Error during message processing for processor ${processorId} with instance id ${instanceId}. Stopping the processor.`,
|
|
772
|
+
error2
|
|
773
|
+
);
|
|
774
|
+
isActive = false;
|
|
775
|
+
return {
|
|
776
|
+
type: "STOP",
|
|
777
|
+
error: error2,
|
|
778
|
+
reason: "Error during message processing"
|
|
779
|
+
};
|
|
780
|
+
}
|
|
737
781
|
}
|
|
738
782
|
};
|
|
739
783
|
};
|
|
@@ -828,32 +872,40 @@ var postgreSQLEventStoreMessageBatchPuller = ({
|
|
|
828
872
|
let isRunning = false;
|
|
829
873
|
let start;
|
|
830
874
|
const pullMessages = async (options) => {
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
875
|
+
try {
|
|
876
|
+
const after = options.startFrom === "BEGINNING" ? 0n : options.startFrom === "END" ? (await readLastMessageGlobalPosition(executor)).currentGlobalPosition ?? 0n : options.startFrom.lastCheckpoint;
|
|
877
|
+
const readMessagesOptions = {
|
|
878
|
+
after,
|
|
879
|
+
batchSize
|
|
880
|
+
};
|
|
881
|
+
let waitTime = 100;
|
|
882
|
+
while (isRunning && !signal?.aborted) {
|
|
883
|
+
const { messages, currentGlobalPosition, areMessagesLeft } = await readMessagesBatch(executor, readMessagesOptions);
|
|
884
|
+
if (messages.length > 0) {
|
|
885
|
+
const result = await eachBatch(messages);
|
|
886
|
+
if (result && result.type === "STOP") {
|
|
887
|
+
isRunning = false;
|
|
888
|
+
break;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
readMessagesOptions.after = currentGlobalPosition;
|
|
892
|
+
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
893
|
+
if (stopWhen?.noMessagesLeft === true && !areMessagesLeft) {
|
|
894
|
+
console.log(
|
|
895
|
+
`No messages left to process after reaching global position ${currentGlobalPosition}. Stopping the puller.`
|
|
896
|
+
);
|
|
842
897
|
isRunning = false;
|
|
843
898
|
break;
|
|
844
899
|
}
|
|
900
|
+
if (!areMessagesLeft) {
|
|
901
|
+
waitTime = Math.min(waitTime * 2, 1e3);
|
|
902
|
+
} else {
|
|
903
|
+
waitTime = pullingFrequencyInMs;
|
|
904
|
+
}
|
|
845
905
|
}
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
isRunning = false;
|
|
850
|
-
break;
|
|
851
|
-
}
|
|
852
|
-
if (!areMessagesLeft) {
|
|
853
|
-
waitTime = Math.min(waitTime * 2, 1e3);
|
|
854
|
-
} else {
|
|
855
|
-
waitTime = pullingFrequencyInMs;
|
|
856
|
-
}
|
|
906
|
+
} catch (error) {
|
|
907
|
+
console.log("Error occurred during message pulling:", error);
|
|
908
|
+
throw error;
|
|
857
909
|
}
|
|
858
910
|
};
|
|
859
911
|
return {
|
|
@@ -883,7 +935,10 @@ var zipPostgreSQLEventStoreMessageBatchPullerStartFrom = (options) => {
|
|
|
883
935
|
};
|
|
884
936
|
|
|
885
937
|
// src/eventStore/consumers/postgreSQLEventStoreConsumer.ts
|
|
886
|
-
import {
|
|
938
|
+
import {
|
|
939
|
+
dumbo as dumbo6,
|
|
940
|
+
JSONSerializer as JSONSerializer2
|
|
941
|
+
} from "@event-driven-io/dumbo";
|
|
887
942
|
import { v7 as uuid7 } from "uuid";
|
|
888
943
|
|
|
889
944
|
// src/eventStore/consumers/postgreSQLProcessor.ts
|
|
@@ -1157,6 +1212,9 @@ var tryAcquireProcessorLock = async (execute, options) => {
|
|
|
1157
1212
|
})
|
|
1158
1213
|
)
|
|
1159
1214
|
);
|
|
1215
|
+
console.log(
|
|
1216
|
+
`Lock acquisition attempt for processor '${options.processorId}' with processor instance '${options.processorInstanceId}' and lock '${options.lockKey}' resulted in: ${acquired}`
|
|
1217
|
+
);
|
|
1160
1218
|
return acquired ? { acquired: true, checkpoint } : { acquired: false };
|
|
1161
1219
|
};
|
|
1162
1220
|
var tryAcquireProcessorLockWithRetry = async (execute, options) => {
|
|
@@ -1185,6 +1243,9 @@ var releaseProcessorLock = async (execute, options) => {
|
|
|
1185
1243
|
})
|
|
1186
1244
|
)
|
|
1187
1245
|
);
|
|
1246
|
+
console.log(
|
|
1247
|
+
`Lock for processor '${options.processorId}' with processor instance '${options.processorInstanceId}' and lock '${options.lockKey}' released: ${result}`
|
|
1248
|
+
);
|
|
1188
1249
|
return result;
|
|
1189
1250
|
};
|
|
1190
1251
|
|
|
@@ -1198,6 +1259,9 @@ var postgreSQLProcessorLock = (options) => {
|
|
|
1198
1259
|
return {
|
|
1199
1260
|
tryAcquire: async (context) => {
|
|
1200
1261
|
if (acquired) {
|
|
1262
|
+
console.log(
|
|
1263
|
+
`Lock for processor '${options.processorId}' is already acquired by this instance. Reusing the lock.`
|
|
1264
|
+
);
|
|
1201
1265
|
return true;
|
|
1202
1266
|
}
|
|
1203
1267
|
const result = await tryAcquireProcessorLockWithRetry(context.execute, {
|
|
@@ -1205,6 +1269,9 @@ var postgreSQLProcessorLock = (options) => {
|
|
|
1205
1269
|
lockKey
|
|
1206
1270
|
});
|
|
1207
1271
|
if (!result.acquired && options.lockAcquisitionPolicy?.type !== "skip") {
|
|
1272
|
+
console.log(
|
|
1273
|
+
`Failed to acquire lock for processor '${options.processorId}' with policy '${options.lockAcquisitionPolicy?.type}'.`
|
|
1274
|
+
);
|
|
1208
1275
|
throw new EmmettError(
|
|
1209
1276
|
`Failed to acquire lock for processor '${options.processorId}'`
|
|
1210
1277
|
);
|
|
@@ -1213,7 +1280,12 @@ var postgreSQLProcessorLock = (options) => {
|
|
|
1213
1280
|
return acquired;
|
|
1214
1281
|
},
|
|
1215
1282
|
release: async (context) => {
|
|
1216
|
-
if (!acquired)
|
|
1283
|
+
if (!acquired) {
|
|
1284
|
+
console.log(
|
|
1285
|
+
`Lock for processor '${options.processorId}' is not acquired by this instance. Skipping release.`
|
|
1286
|
+
);
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1217
1289
|
const { projection: projection2, ...releaseOptions } = options;
|
|
1218
1290
|
await releaseProcessorLock(context.execute, {
|
|
1219
1291
|
...releaseOptions,
|
|
@@ -4856,12 +4928,20 @@ var postgreSQLEventStoreConsumer = (options) => {
|
|
|
4856
4928
|
};
|
|
4857
4929
|
const result = await Promise.allSettled(
|
|
4858
4930
|
activeProcessors.map(async (s) => {
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4931
|
+
try {
|
|
4932
|
+
return await s.handle(messagesBatch, {
|
|
4933
|
+
connection: {
|
|
4934
|
+
connectionString: options.connectionString,
|
|
4935
|
+
pool
|
|
4936
|
+
}
|
|
4937
|
+
});
|
|
4938
|
+
} catch (error) {
|
|
4939
|
+
console.log(
|
|
4940
|
+
`Error during message batch processing for processor: ${s.id}`,
|
|
4941
|
+
error
|
|
4942
|
+
);
|
|
4943
|
+
throw error;
|
|
4944
|
+
}
|
|
4865
4945
|
})
|
|
4866
4946
|
);
|
|
4867
4947
|
return result.some(
|
|
@@ -4897,7 +4977,24 @@ var postgreSQLEventStoreConsumer = (options) => {
|
|
|
4897
4977
|
const postgresProcessors = processors;
|
|
4898
4978
|
for (const processor of postgresProcessors) {
|
|
4899
4979
|
if (processor.init) {
|
|
4900
|
-
|
|
4980
|
+
try {
|
|
4981
|
+
await processor.init(processorContext);
|
|
4982
|
+
} catch (error) {
|
|
4983
|
+
console.log(
|
|
4984
|
+
`Error during processor initialization for processor: ${processor.id}. Stopping it.`,
|
|
4985
|
+
error
|
|
4986
|
+
);
|
|
4987
|
+
await processor.close(processorContext).catch((closeError) => {
|
|
4988
|
+
console.log(
|
|
4989
|
+
`Error during processor cleanup after failed initialization for processor: ${processor.id}`,
|
|
4990
|
+
closeError
|
|
4991
|
+
);
|
|
4992
|
+
});
|
|
4993
|
+
console.log(
|
|
4994
|
+
`Processor ${processor.id} stopped successfully after failed initialization.`
|
|
4995
|
+
);
|
|
4996
|
+
throw error;
|
|
4997
|
+
}
|
|
4901
4998
|
}
|
|
4902
4999
|
}
|
|
4903
5000
|
isInitialized = true;
|
|
@@ -4926,11 +5023,20 @@ var postgreSQLEventStoreConsumer = (options) => {
|
|
|
4926
5023
|
return processor;
|
|
4927
5024
|
},
|
|
4928
5025
|
start: () => {
|
|
4929
|
-
if (isRunning)
|
|
4930
|
-
|
|
5026
|
+
if (isRunning) {
|
|
5027
|
+
console.log(
|
|
5028
|
+
"Consumer is already running. Returning the existing start promise."
|
|
5029
|
+
);
|
|
5030
|
+
return start;
|
|
5031
|
+
}
|
|
5032
|
+
if (processors.length === 0) {
|
|
5033
|
+
console.log(
|
|
5034
|
+
"Cannot start consumer without at least a single processor"
|
|
5035
|
+
);
|
|
4931
5036
|
throw new EmmettError(
|
|
4932
5037
|
"Cannot start consumer without at least a single processor"
|
|
4933
5038
|
);
|
|
5039
|
+
}
|
|
4934
5040
|
isRunning = true;
|
|
4935
5041
|
abortController = new AbortController();
|
|
4936
5042
|
messagePuller = postgreSQLEventStoreMessageBatchPuller({
|
|
@@ -4944,22 +5050,36 @@ var postgreSQLEventStoreConsumer = (options) => {
|
|
|
4944
5050
|
start = (async () => {
|
|
4945
5051
|
if (!isRunning) return;
|
|
4946
5052
|
if (!isInitialized) {
|
|
5053
|
+
console.log("Initializing consumer before starting message pulling.");
|
|
4947
5054
|
await init();
|
|
4948
5055
|
}
|
|
4949
5056
|
const startFrom = zipPostgreSQLEventStoreMessageBatchPullerStartFrom(
|
|
4950
5057
|
await Promise.all(
|
|
4951
5058
|
processors.map(async (o) => {
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
5059
|
+
try {
|
|
5060
|
+
const result = await o.start({
|
|
5061
|
+
execute: pool.execute,
|
|
5062
|
+
connection: {
|
|
5063
|
+
connectionString: options.connectionString,
|
|
5064
|
+
pool
|
|
5065
|
+
}
|
|
5066
|
+
});
|
|
5067
|
+
return result;
|
|
5068
|
+
} catch (error) {
|
|
5069
|
+
console.log(
|
|
5070
|
+
`Error during processor start position retrieval for processor: ${o.id}. Stopping it.`,
|
|
5071
|
+
error
|
|
5072
|
+
);
|
|
5073
|
+
throw error;
|
|
5074
|
+
}
|
|
4960
5075
|
})
|
|
4961
5076
|
)
|
|
4962
5077
|
);
|
|
5078
|
+
console.log(
|
|
5079
|
+
`Starting message pulling with start position: ${JSONSerializer2.serialize(
|
|
5080
|
+
startFrom
|
|
5081
|
+
)}. Waiting for messages...`
|
|
5082
|
+
);
|
|
4963
5083
|
await messagePuller.start({ startFrom });
|
|
4964
5084
|
await stopProcessors();
|
|
4965
5085
|
isRunning = false;
|