@sentry/junior 0.85.0 → 0.87.0
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/{agent-hooks-AV7CHLUO.js → agent-hooks-NWOUB3UR.js} +7 -7
- package/dist/app.js +779 -356
- package/dist/chat/conversation-privacy.d.ts +12 -2
- package/dist/chat/conversations/sql/migrations.d.ts +1 -1
- package/dist/chat/conversations/sql/store.d.ts +9 -1
- package/dist/chat/conversations/store.d.ts +13 -0
- package/dist/chat/ingress/message-changed.d.ts +2 -0
- package/dist/chat/no-reply.d.ts +7 -0
- package/dist/chat/respond.d.ts +7 -1
- package/dist/chat/runtime/reply-executor.d.ts +2 -10
- package/dist/chat/runtime/slack-runtime.d.ts +5 -4
- package/dist/chat/runtime/turn.d.ts +7 -0
- package/dist/chat/services/persist-retry.d.ts +2 -0
- package/dist/chat/services/reply-delivery-plan.d.ts +0 -4
- package/dist/chat/services/turn-session-record.d.ts +31 -2
- package/dist/chat/slack/client.d.ts +33 -2
- package/dist/chat/slack/conversation-context.d.ts +15 -0
- package/dist/chat/state/turn-session.d.ts +9 -0
- package/dist/chat/task-execution/queue.d.ts +1 -1
- package/dist/chat/task-execution/slack-work.d.ts +10 -2
- package/dist/chat/task-execution/state.d.ts +44 -4
- package/dist/chat/task-execution/store.d.ts +21 -4
- package/dist/chat/task-execution/worker.d.ts +11 -4
- package/dist/chat/tools/slack/channel-access.d.ts +29 -0
- package/dist/chat/tools/slack/thread-read.d.ts +4 -1
- package/dist/{chunk-UVNV67EC.js → chunk-2NFV5FMB.js} +4 -4
- package/dist/{chunk-QTTTRBNB.js → chunk-6I6HBOQM.js} +80 -15
- package/dist/{chunk-ENEWQMRJ.js → chunk-6O5UI3RG.js} +1 -1
- package/dist/{chunk-GY7L6VCT.js → chunk-ACJJJEGG.js} +35 -17
- package/dist/{chunk-MHEV3T2Y.js → chunk-B6FQPS7A.js} +953 -795
- package/dist/{chunk-MTE5NRPJ.js → chunk-BRSQQRG6.js} +1 -1
- package/dist/{chunk-EENOFKDN.js → chunk-ENPSU7L7.js} +165 -27
- package/dist/{chunk-RUB77TGS.js → chunk-GB5DFM4D.js} +1 -1
- package/dist/{chunk-C2PSUWK3.js → chunk-GGD6WK6V.js} +124 -25
- package/dist/{chunk-SSUEWAVS.js → chunk-JRXCSSSU.js} +19 -4
- package/dist/{chunk-DR75T7J3.js → chunk-L7OHKDOX.js} +9 -5
- package/dist/{chunk-FYPO4K7C.js → chunk-RIB3M6YA.js} +2 -2
- package/dist/{chunk-BU2AWPEN.js → chunk-ZU2ALUVQ.js} +3 -2
- package/dist/cli/chat.js +4 -4
- package/dist/cli/plugins.js +7 -7
- package/dist/cli/snapshot-warmup.js +4 -4
- package/dist/cli/upgrade.js +10 -7
- package/dist/{db-S3HYBLUS.js → db-SZVUU7RB.js} +4 -4
- package/dist/instrumentation.js +1 -1
- package/dist/nitro.js +4 -4
- package/dist/reporting/conversations.d.ts +2 -1
- package/dist/reporting.js +95 -30
- package/dist/{runner-IMQH6V2B.js → runner-DMP3IQNM.js} +27 -13
- package/package.json +6 -6
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
getDefaultRedisStateAdapterFor,
|
|
6
6
|
getStateAdapter
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GB5DFM4D.js";
|
|
8
8
|
import {
|
|
9
9
|
parseDestination,
|
|
10
10
|
sameDestination
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-GGD6WK6V.js";
|
|
12
12
|
import {
|
|
13
13
|
getChatConfig
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-ZU2ALUVQ.js";
|
|
15
15
|
import {
|
|
16
16
|
parseStoredSlackRequester
|
|
17
17
|
} from "./chunk-IXTBFABZ.js";
|
|
@@ -38,11 +38,23 @@ var InvalidConversationRecordError = class extends Error {
|
|
|
38
38
|
this.name = "InvalidConversationRecordError";
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
|
+
function isInvalidConversationRecordError(error) {
|
|
42
|
+
return error instanceof InvalidConversationRecordError;
|
|
43
|
+
}
|
|
44
|
+
var ConversationMutationFencedError = class extends Error {
|
|
45
|
+
constructor(conversationId) {
|
|
46
|
+
super(
|
|
47
|
+
`Conversation mutation lock was lost before write for ${conversationId}`
|
|
48
|
+
);
|
|
49
|
+
this.name = "ConversationMutationFencedError";
|
|
50
|
+
}
|
|
51
|
+
};
|
|
41
52
|
var CONVERSATION_BY_ACTIVITY_INDEX_KEY = `${CONVERSATION_PREFIX}:by-activity`;
|
|
42
53
|
var CONVERSATION_ACTIVE_INDEX_KEY = `${CONVERSATION_PREFIX}:active`;
|
|
43
54
|
var CONVERSATION_WORK_LEASE_TTL_MS = 9e4;
|
|
44
55
|
var CONVERSATION_WORK_CHECK_IN_INTERVAL_MS = 15e3;
|
|
45
56
|
var CONVERSATION_WORK_STALE_ENQUEUE_MS = 6e4;
|
|
57
|
+
var CONVERSATION_WORK_MAX_DELIVERY_ATTEMPTS = 5;
|
|
46
58
|
function conversationKey(conversationId) {
|
|
47
59
|
return `${CONVERSATION_PREFIX}:${conversationId}`;
|
|
48
60
|
}
|
|
@@ -58,6 +70,15 @@ function now() {
|
|
|
58
70
|
function compareMessages(left, right) {
|
|
59
71
|
return left.createdAtMs - right.createdAtMs || left.receivedAtMs - right.receivedAtMs || left.inboundMessageId.localeCompare(right.inboundMessageId);
|
|
60
72
|
}
|
|
73
|
+
function inputHasAttachments(input) {
|
|
74
|
+
return Array.isArray(input.attachments) && input.attachments.length > 0;
|
|
75
|
+
}
|
|
76
|
+
function upgradedPendingMessage(stored, duplicate) {
|
|
77
|
+
if (!inputHasAttachments(duplicate.input) || inputHasAttachments(stored.input)) {
|
|
78
|
+
return stored;
|
|
79
|
+
}
|
|
80
|
+
return { ...stored, input: duplicate.input };
|
|
81
|
+
}
|
|
61
82
|
function compareIndexDescending(left, right) {
|
|
62
83
|
return right.score - left.score || right.conversationId.localeCompare(left.conversationId);
|
|
63
84
|
}
|
|
@@ -122,9 +143,13 @@ function normalizeMessage(value) {
|
|
|
122
143
|
createdAtMs,
|
|
123
144
|
receivedAtMs,
|
|
124
145
|
input,
|
|
125
|
-
injectedAtMs: toOptionalNumber(value.injectedAtMs)
|
|
146
|
+
injectedAtMs: toOptionalNumber(value.injectedAtMs),
|
|
147
|
+
attemptCount: toOptionalNumber(value.attemptCount)
|
|
126
148
|
};
|
|
127
149
|
}
|
|
150
|
+
function isFinalAttempt(message) {
|
|
151
|
+
return (message.attemptCount ?? 0) >= CONVERSATION_WORK_MAX_DELIVERY_ATTEMPTS - 1;
|
|
152
|
+
}
|
|
128
153
|
function normalizeRequester(value) {
|
|
129
154
|
return parseStoredSlackRequester(value);
|
|
130
155
|
}
|
|
@@ -517,7 +542,7 @@ async function withConversationMutation(args, callback) {
|
|
|
517
542
|
const state = await getConnectedState(args.state);
|
|
518
543
|
const lock = await acquireMutationLock(state, args.conversationId);
|
|
519
544
|
try {
|
|
520
|
-
return await callback(state);
|
|
545
|
+
return await callback(state, lock);
|
|
521
546
|
} finally {
|
|
522
547
|
await state.releaseLock(lock);
|
|
523
548
|
}
|
|
@@ -533,7 +558,7 @@ async function readConversation(state, conversationId) {
|
|
|
533
558
|
}
|
|
534
559
|
return conversation;
|
|
535
560
|
}
|
|
536
|
-
async function writeConversation(state, conversation) {
|
|
561
|
+
async function writeConversation(state, lock, conversation) {
|
|
537
562
|
const execution = executionWithPendingMessages(
|
|
538
563
|
conversation.execution,
|
|
539
564
|
conversation.execution.pendingMessages
|
|
@@ -542,6 +567,13 @@ async function writeConversation(state, conversation) {
|
|
|
542
567
|
...conversation,
|
|
543
568
|
execution
|
|
544
569
|
};
|
|
570
|
+
const fenced = await state.extendLock(
|
|
571
|
+
lock,
|
|
572
|
+
CONVERSATION_MUTATION_LOCK_TTL_MS
|
|
573
|
+
);
|
|
574
|
+
if (!fenced) {
|
|
575
|
+
throw new ConversationMutationFencedError(next.conversationId);
|
|
576
|
+
}
|
|
545
577
|
await state.set(
|
|
546
578
|
conversationKey(next.conversationId),
|
|
547
579
|
next,
|
|
@@ -605,7 +637,7 @@ async function appendInboundMessage(args) {
|
|
|
605
637
|
const nowMs = args.nowMs ?? now();
|
|
606
638
|
return await withConversationMutation(
|
|
607
639
|
{ conversationId: args.message.conversationId, state: args.state },
|
|
608
|
-
async (state) => {
|
|
640
|
+
async (state, lock) => {
|
|
609
641
|
const current = await readConversation(state, args.message.conversationId) ?? emptyConversation({
|
|
610
642
|
conversationId: args.message.conversationId,
|
|
611
643
|
destination: args.message.destination,
|
|
@@ -630,11 +662,15 @@ async function appendInboundMessage(args) {
|
|
|
630
662
|
const nextStatus = current.execution.status === "idle" ? "pending" : current.execution.status;
|
|
631
663
|
await writeConversation(
|
|
632
664
|
state,
|
|
665
|
+
lock,
|
|
633
666
|
withExecutionUpdate(
|
|
634
667
|
current,
|
|
635
668
|
{
|
|
636
669
|
...current.execution,
|
|
637
|
-
status: nextStatus
|
|
670
|
+
status: nextStatus,
|
|
671
|
+
pendingMessages: current.execution.pendingMessages.map(
|
|
672
|
+
(message) => message.inboundMessageId === args.message.inboundMessageId ? upgradedPendingMessage(message, args.message) : message
|
|
673
|
+
)
|
|
638
674
|
},
|
|
639
675
|
nowMs
|
|
640
676
|
)
|
|
@@ -650,6 +686,7 @@ async function appendInboundMessage(args) {
|
|
|
650
686
|
};
|
|
651
687
|
await writeConversation(
|
|
652
688
|
state,
|
|
689
|
+
lock,
|
|
653
690
|
withExecutionUpdate(
|
|
654
691
|
next,
|
|
655
692
|
{
|
|
@@ -673,7 +710,7 @@ async function appendInboundMessage(args) {
|
|
|
673
710
|
}
|
|
674
711
|
async function requestConversationWork(args) {
|
|
675
712
|
const nowMs = args.nowMs ?? now();
|
|
676
|
-
return await withConversationMutation(args, async (state) => {
|
|
713
|
+
return await withConversationMutation(args, async (state, lock) => {
|
|
677
714
|
const existing = await readConversation(state, args.conversationId);
|
|
678
715
|
if (existing) {
|
|
679
716
|
assertSameConversationDestination({
|
|
@@ -690,6 +727,7 @@ async function requestConversationWork(args) {
|
|
|
690
727
|
const status = current.execution.lease ? "awaiting_resume" : "pending";
|
|
691
728
|
await writeConversation(
|
|
692
729
|
state,
|
|
730
|
+
lock,
|
|
693
731
|
withExecutionUpdate(
|
|
694
732
|
{
|
|
695
733
|
...current,
|
|
@@ -708,7 +746,7 @@ async function requestConversationWork(args) {
|
|
|
708
746
|
async function recordConversationActivity(args) {
|
|
709
747
|
const nowMs = args.nowMs ?? now();
|
|
710
748
|
const activityAtMs = args.activityAtMs ?? nowMs;
|
|
711
|
-
await withConversationMutation(args, async (state) => {
|
|
749
|
+
await withConversationMutation(args, async (state, lock) => {
|
|
712
750
|
const existing = await readConversation(state, args.conversationId);
|
|
713
751
|
if (existing && args.destination) {
|
|
714
752
|
assertSameConversationDestination({
|
|
@@ -723,7 +761,7 @@ async function recordConversationActivity(args) {
|
|
|
723
761
|
nowMs,
|
|
724
762
|
source: args.source
|
|
725
763
|
});
|
|
726
|
-
await writeConversation(state, {
|
|
764
|
+
await writeConversation(state, lock, {
|
|
727
765
|
...current,
|
|
728
766
|
...current.destination ?? args.destination ? { destination: current.destination ?? args.destination } : {},
|
|
729
767
|
...current.source ?? args.source ? { source: current.source ?? args.source } : {},
|
|
@@ -741,7 +779,7 @@ async function recordConversationActivity(args) {
|
|
|
741
779
|
}
|
|
742
780
|
async function recordConversationExecution(args) {
|
|
743
781
|
const nowMs = args.updatedAtMs;
|
|
744
|
-
await withConversationMutation(args, async (state) => {
|
|
782
|
+
await withConversationMutation(args, async (state, lock) => {
|
|
745
783
|
const existing = await readConversation(state, args.conversationId);
|
|
746
784
|
if (existing && args.destination) {
|
|
747
785
|
assertSameConversationDestination({
|
|
@@ -758,6 +796,7 @@ async function recordConversationExecution(args) {
|
|
|
758
796
|
});
|
|
759
797
|
await writeConversation(
|
|
760
798
|
state,
|
|
799
|
+
lock,
|
|
761
800
|
withExecutionUpdate(
|
|
762
801
|
{
|
|
763
802
|
...current,
|
|
@@ -783,13 +822,14 @@ async function recordConversationExecution(args) {
|
|
|
783
822
|
}
|
|
784
823
|
async function markConversationWorkEnqueued(args) {
|
|
785
824
|
const nowMs = args.nowMs ?? now();
|
|
786
|
-
await withConversationMutation(args, async (state) => {
|
|
825
|
+
await withConversationMutation(args, async (state, lock) => {
|
|
787
826
|
const current = await readConversation(state, args.conversationId);
|
|
788
827
|
if (!current) {
|
|
789
828
|
return;
|
|
790
829
|
}
|
|
791
830
|
await writeConversation(
|
|
792
831
|
state,
|
|
832
|
+
lock,
|
|
793
833
|
withExecutionUpdate(
|
|
794
834
|
current,
|
|
795
835
|
{
|
|
@@ -803,13 +843,14 @@ async function markConversationWorkEnqueued(args) {
|
|
|
803
843
|
}
|
|
804
844
|
async function clearConsumedConversationWake(args) {
|
|
805
845
|
const nowMs = args.nowMs ?? now();
|
|
806
|
-
return await withConversationMutation(args, async (state) => {
|
|
846
|
+
return await withConversationMutation(args, async (state, lock) => {
|
|
807
847
|
const current = await readConversation(state, args.conversationId);
|
|
808
848
|
if (!current || hasRunnableWork(current) || current.execution.lastEnqueuedAtMs === void 0) {
|
|
809
849
|
return false;
|
|
810
850
|
}
|
|
811
851
|
await writeConversation(
|
|
812
852
|
state,
|
|
853
|
+
lock,
|
|
813
854
|
withExecutionUpdate(
|
|
814
855
|
current,
|
|
815
856
|
{
|
|
@@ -824,7 +865,7 @@ async function clearConsumedConversationWake(args) {
|
|
|
824
865
|
}
|
|
825
866
|
async function startConversationWork(args) {
|
|
826
867
|
const nowMs = args.nowMs ?? now();
|
|
827
|
-
return await withConversationMutation(args, async (state) => {
|
|
868
|
+
return await withConversationMutation(args, async (state, lock) => {
|
|
828
869
|
const current = await readConversation(state, args.conversationId);
|
|
829
870
|
if (!current) {
|
|
830
871
|
return { status: "no_work" };
|
|
@@ -846,6 +887,7 @@ async function startConversationWork(args) {
|
|
|
846
887
|
};
|
|
847
888
|
await writeConversation(
|
|
848
889
|
state,
|
|
890
|
+
lock,
|
|
849
891
|
withExecutionUpdate(
|
|
850
892
|
current,
|
|
851
893
|
{
|
|
@@ -867,13 +909,14 @@ async function startConversationWork(args) {
|
|
|
867
909
|
}
|
|
868
910
|
async function checkInConversationWork(args) {
|
|
869
911
|
const nowMs = args.nowMs ?? now();
|
|
870
|
-
return await withConversationMutation(args, async (state) => {
|
|
912
|
+
return await withConversationMutation(args, async (state, lock) => {
|
|
871
913
|
const current = await readConversation(state, args.conversationId);
|
|
872
914
|
if (!current || current.execution.lease?.token !== args.leaseToken) {
|
|
873
915
|
return false;
|
|
874
916
|
}
|
|
875
917
|
await writeConversation(
|
|
876
918
|
state,
|
|
919
|
+
lock,
|
|
877
920
|
withExecutionUpdate(
|
|
878
921
|
current,
|
|
879
922
|
{
|
|
@@ -904,12 +947,12 @@ async function drainConversationMailbox(args) {
|
|
|
904
947
|
if (pending.length === 0) {
|
|
905
948
|
return [];
|
|
906
949
|
}
|
|
907
|
-
const acknowledgedIds = await args.
|
|
908
|
-
const
|
|
950
|
+
const acknowledgedIds = await args.handle(pending);
|
|
951
|
+
const pendingIds = new Set(
|
|
909
952
|
pending.map((message) => message.inboundMessageId)
|
|
910
953
|
);
|
|
911
954
|
for (const inboundMessageId of acknowledgedIds ?? []) {
|
|
912
|
-
if (!
|
|
955
|
+
if (!pendingIds.has(inboundMessageId)) {
|
|
913
956
|
throw new Error(
|
|
914
957
|
`Conversation mailbox acknowledgement is not pending for ${args.conversationId}`
|
|
915
958
|
);
|
|
@@ -918,7 +961,7 @@ async function drainConversationMailbox(args) {
|
|
|
918
961
|
const drainedIds = new Set(
|
|
919
962
|
acknowledgedIds ?? pending.map((message) => message.inboundMessageId)
|
|
920
963
|
);
|
|
921
|
-
await withConversationMutation(args, async (state) => {
|
|
964
|
+
await withConversationMutation(args, async (state, lock) => {
|
|
922
965
|
const current = await readConversation(state, args.conversationId);
|
|
923
966
|
if (!current || current.execution.lease?.token !== args.leaseToken) {
|
|
924
967
|
throw new Error(
|
|
@@ -930,6 +973,7 @@ async function drainConversationMailbox(args) {
|
|
|
930
973
|
);
|
|
931
974
|
await writeConversation(
|
|
932
975
|
state,
|
|
976
|
+
lock,
|
|
933
977
|
withExecutionUpdate(
|
|
934
978
|
current,
|
|
935
979
|
{
|
|
@@ -943,10 +987,10 @@ async function drainConversationMailbox(args) {
|
|
|
943
987
|
});
|
|
944
988
|
return pending.filter((message) => drainedIds.has(message.inboundMessageId));
|
|
945
989
|
}
|
|
946
|
-
async function
|
|
990
|
+
async function ackMessages(args) {
|
|
947
991
|
const nowMs = args.nowMs ?? now();
|
|
948
992
|
const inboundMessageIds = new Set(args.inboundMessageIds);
|
|
949
|
-
return await withConversationMutation(args, async (state) => {
|
|
993
|
+
return await withConversationMutation(args, async (state, lock) => {
|
|
950
994
|
const current = await readConversation(state, args.conversationId);
|
|
951
995
|
if (!current || current.execution.lease?.token !== args.leaseToken) {
|
|
952
996
|
return false;
|
|
@@ -962,6 +1006,7 @@ async function markConversationMessagesInjected(args) {
|
|
|
962
1006
|
}
|
|
963
1007
|
await writeConversation(
|
|
964
1008
|
state,
|
|
1009
|
+
lock,
|
|
965
1010
|
withExecutionUpdate(
|
|
966
1011
|
current,
|
|
967
1012
|
{
|
|
@@ -976,7 +1021,7 @@ async function markConversationMessagesInjected(args) {
|
|
|
976
1021
|
}
|
|
977
1022
|
async function requestConversationContinuation(args) {
|
|
978
1023
|
const nowMs = args.nowMs ?? now();
|
|
979
|
-
return await withConversationMutation(args, async (state) => {
|
|
1024
|
+
return await withConversationMutation(args, async (state, lock) => {
|
|
980
1025
|
const current = await readConversation(state, args.conversationId);
|
|
981
1026
|
if (!current || current.execution.lease?.token !== args.leaseToken) {
|
|
982
1027
|
return false;
|
|
@@ -988,6 +1033,7 @@ async function requestConversationContinuation(args) {
|
|
|
988
1033
|
});
|
|
989
1034
|
await writeConversation(
|
|
990
1035
|
state,
|
|
1036
|
+
lock,
|
|
991
1037
|
withExecutionUpdate(
|
|
992
1038
|
current,
|
|
993
1039
|
{
|
|
@@ -1002,13 +1048,14 @@ async function requestConversationContinuation(args) {
|
|
|
1002
1048
|
}
|
|
1003
1049
|
async function releaseConversationWork(args) {
|
|
1004
1050
|
const nowMs = args.nowMs ?? now();
|
|
1005
|
-
return await withConversationMutation(args, async (state) => {
|
|
1051
|
+
return await withConversationMutation(args, async (state, lock) => {
|
|
1006
1052
|
const current = await readConversation(state, args.conversationId);
|
|
1007
1053
|
if (!current || current.execution.lease?.token !== args.leaseToken) {
|
|
1008
1054
|
return false;
|
|
1009
1055
|
}
|
|
1010
1056
|
await writeConversation(
|
|
1011
1057
|
state,
|
|
1058
|
+
lock,
|
|
1012
1059
|
withExecutionUpdate(
|
|
1013
1060
|
current,
|
|
1014
1061
|
{
|
|
@@ -1024,7 +1071,7 @@ async function releaseConversationWork(args) {
|
|
|
1024
1071
|
}
|
|
1025
1072
|
async function completeConversationWork(args) {
|
|
1026
1073
|
const nowMs = args.nowMs ?? now();
|
|
1027
|
-
return await withConversationMutation(args, async (state) => {
|
|
1074
|
+
return await withConversationMutation(args, async (state, lock) => {
|
|
1028
1075
|
const current = await readConversation(state, args.conversationId);
|
|
1029
1076
|
if (!current || current.execution.lease?.token !== args.leaseToken) {
|
|
1030
1077
|
return "lost_lease";
|
|
@@ -1034,6 +1081,7 @@ async function completeConversationWork(args) {
|
|
|
1034
1081
|
const runnable = needsRun || hasPending;
|
|
1035
1082
|
await writeConversation(
|
|
1036
1083
|
state,
|
|
1084
|
+
lock,
|
|
1037
1085
|
withExecutionUpdate(
|
|
1038
1086
|
current,
|
|
1039
1087
|
{
|
|
@@ -1048,15 +1096,101 @@ async function completeConversationWork(args) {
|
|
|
1048
1096
|
return runnable ? "pending" : "completed";
|
|
1049
1097
|
});
|
|
1050
1098
|
}
|
|
1099
|
+
async function recordAttemptFailure(args) {
|
|
1100
|
+
const nowMs = args.nowMs ?? now();
|
|
1101
|
+
return await withConversationMutation(args, async (state, lock) => {
|
|
1102
|
+
const current = await readConversation(state, args.conversationId);
|
|
1103
|
+
if (!current || current.execution.lease?.token !== args.leaseToken) {
|
|
1104
|
+
return {
|
|
1105
|
+
status: "lost_lease",
|
|
1106
|
+
pendingCount: 0,
|
|
1107
|
+
deadLetteredMessages: []
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
const pendingIds = new Set(
|
|
1111
|
+
current.execution.pendingMessages.map(
|
|
1112
|
+
(message) => message.inboundMessageId
|
|
1113
|
+
)
|
|
1114
|
+
);
|
|
1115
|
+
if (args.inboundMessageIds.length === 0 || args.inboundMessageIds.some((id) => !pendingIds.has(id))) {
|
|
1116
|
+
return {
|
|
1117
|
+
status: "skipped",
|
|
1118
|
+
pendingCount: current.execution.pendingMessages.length,
|
|
1119
|
+
deadLetteredMessages: []
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
const attemptedIds = new Set(args.inboundMessageIds);
|
|
1123
|
+
const deadLetteredMessages = [];
|
|
1124
|
+
const pendingMessages2 = [];
|
|
1125
|
+
for (const message of current.execution.pendingMessages) {
|
|
1126
|
+
if (!attemptedIds.has(message.inboundMessageId)) {
|
|
1127
|
+
pendingMessages2.push(message);
|
|
1128
|
+
continue;
|
|
1129
|
+
}
|
|
1130
|
+
const attempted = {
|
|
1131
|
+
...message,
|
|
1132
|
+
attemptCount: (message.attemptCount ?? 0) + 1
|
|
1133
|
+
};
|
|
1134
|
+
if (attempted.attemptCount >= CONVERSATION_WORK_MAX_DELIVERY_ATTEMPTS) {
|
|
1135
|
+
deadLetteredMessages.push(attempted);
|
|
1136
|
+
continue;
|
|
1137
|
+
}
|
|
1138
|
+
pendingMessages2.push(attempted);
|
|
1139
|
+
}
|
|
1140
|
+
await writeConversation(
|
|
1141
|
+
state,
|
|
1142
|
+
lock,
|
|
1143
|
+
withExecutionUpdate(
|
|
1144
|
+
current,
|
|
1145
|
+
{
|
|
1146
|
+
...current.execution,
|
|
1147
|
+
pendingMessages: pendingMessages2
|
|
1148
|
+
},
|
|
1149
|
+
nowMs
|
|
1150
|
+
)
|
|
1151
|
+
);
|
|
1152
|
+
return {
|
|
1153
|
+
status: "recorded",
|
|
1154
|
+
pendingCount: pendingMessages2.length,
|
|
1155
|
+
deadLetteredMessages
|
|
1156
|
+
};
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
async function deadLetterAttempt(args) {
|
|
1160
|
+
const nowMs = args.nowMs ?? now();
|
|
1161
|
+
return await withConversationMutation(args, async (state, lock) => {
|
|
1162
|
+
const current = await readConversation(state, args.conversationId);
|
|
1163
|
+
if (!current || current.execution.lease?.token !== args.leaseToken) {
|
|
1164
|
+
return "lost_lease";
|
|
1165
|
+
}
|
|
1166
|
+
const runnable = pendingMessages(current).length > 0;
|
|
1167
|
+
await writeConversation(
|
|
1168
|
+
state,
|
|
1169
|
+
lock,
|
|
1170
|
+
withExecutionUpdate(
|
|
1171
|
+
current,
|
|
1172
|
+
{
|
|
1173
|
+
...current.execution,
|
|
1174
|
+
lease: void 0,
|
|
1175
|
+
status: runnable ? "pending" : "failed",
|
|
1176
|
+
runId: runnable ? current.execution.runId : void 0
|
|
1177
|
+
},
|
|
1178
|
+
nowMs
|
|
1179
|
+
)
|
|
1180
|
+
);
|
|
1181
|
+
return runnable ? "pending" : "failed";
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1051
1184
|
async function clearExpiredConversationLease(args) {
|
|
1052
1185
|
const nowMs = args.nowMs ?? now();
|
|
1053
|
-
return await withConversationMutation(args, async (state) => {
|
|
1186
|
+
return await withConversationMutation(args, async (state, lock) => {
|
|
1054
1187
|
const current = await readConversation(state, args.conversationId);
|
|
1055
1188
|
if (!current?.execution.lease || current.execution.lease.expiresAtMs > nowMs) {
|
|
1056
1189
|
return false;
|
|
1057
1190
|
}
|
|
1058
1191
|
await writeConversation(
|
|
1059
1192
|
state,
|
|
1193
|
+
lock,
|
|
1060
1194
|
withExecutionUpdate(
|
|
1061
1195
|
current,
|
|
1062
1196
|
{
|
|
@@ -1120,8 +1254,10 @@ async function listConversationsByActivity(args = {}) {
|
|
|
1120
1254
|
}
|
|
1121
1255
|
|
|
1122
1256
|
export {
|
|
1257
|
+
isInvalidConversationRecordError,
|
|
1123
1258
|
CONVERSATION_WORK_CHECK_IN_INTERVAL_MS,
|
|
1124
1259
|
CONVERSATION_WORK_STALE_ENQUEUE_MS,
|
|
1260
|
+
isFinalAttempt,
|
|
1125
1261
|
getConversation,
|
|
1126
1262
|
getConversationWorkState,
|
|
1127
1263
|
appendInboundMessage,
|
|
@@ -1133,10 +1269,12 @@ export {
|
|
|
1133
1269
|
startConversationWork,
|
|
1134
1270
|
checkInConversationWork,
|
|
1135
1271
|
drainConversationMailbox,
|
|
1136
|
-
|
|
1272
|
+
ackMessages,
|
|
1137
1273
|
requestConversationContinuation,
|
|
1138
1274
|
releaseConversationWork,
|
|
1139
1275
|
completeConversationWork,
|
|
1276
|
+
recordAttemptFailure,
|
|
1277
|
+
deadLetterAttempt,
|
|
1140
1278
|
clearExpiredConversationLease,
|
|
1141
1279
|
removeActiveConversation,
|
|
1142
1280
|
listActiveConversationIds,
|