@mondaydotcomorg/atp-runtime 0.18.4-rc.0 → 0.19.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/llm/replay.d.ts.map +1 -1
- package/dist/llm/replay.js +38 -26
- package/dist/llm/replay.js.map +1 -1
- package/package.json +1 -1
- package/src/llm/replay.ts +66 -44
package/dist/llm/replay.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/llm/replay.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,UAAU,aAAa;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACvB;
|
|
1
|
+
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/llm/replay.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,UAAU,aAAa;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACvB;AA2CD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAE/D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AA8CD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CA6BnE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE5E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAatD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAG9C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CAU7E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAG9C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAK3C;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAM3E;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACvB,GAAG,IAAI,CAGP;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,aAAa,EAAE,CAGnD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAG1C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CAG/E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAG5E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAM9E;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAK/D;AAwBD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,GAAE,MAAgB,GAAG,MAAM,CAa5E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAG7C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAC;CACvB,CAsBA"}
|
package/dist/llm/replay.js
CHANGED
|
@@ -4,6 +4,17 @@ import { AsyncLocalStorage } from 'async_hooks';
|
|
|
4
4
|
* Each execution has its own isolated state
|
|
5
5
|
*/
|
|
6
6
|
const executionStates = new Map();
|
|
7
|
+
/**
|
|
8
|
+
* Maximum number of execution states to keep in memory
|
|
9
|
+
* After this limit, old states are automatically cleaned up
|
|
10
|
+
*/
|
|
11
|
+
const MAX_EXECUTION_STATES = 100;
|
|
12
|
+
/**
|
|
13
|
+
* Automatic cleanup check counter
|
|
14
|
+
* Every N operations, we check if cleanup is needed
|
|
15
|
+
*/
|
|
16
|
+
let operationCounter = 0;
|
|
17
|
+
const CLEANUP_CHECK_INTERVAL = 50;
|
|
7
18
|
/**
|
|
8
19
|
* AsyncLocalStorage for execution ID - provides proper async context isolation
|
|
9
20
|
* This ensures each async execution chain has its own isolated execution ID
|
|
@@ -41,12 +52,19 @@ function getCurrentState() {
|
|
|
41
52
|
if (!executionId) {
|
|
42
53
|
throw new Error('No execution context set. Executor must call setCurrentExecutionId() before runtime API calls.');
|
|
43
54
|
}
|
|
44
|
-
|
|
55
|
+
// Automatic cleanup check (every N operations)
|
|
56
|
+
operationCounter++;
|
|
57
|
+
if (operationCounter >= CLEANUP_CHECK_INTERVAL) {
|
|
58
|
+
operationCounter = 0;
|
|
59
|
+
autoCleanup();
|
|
60
|
+
}
|
|
45
61
|
let state = executionStates.get(executionId);
|
|
46
62
|
if (!state) {
|
|
47
63
|
// State should have been initialized explicitly at execution start
|
|
48
64
|
// Create it now with a safe default to prevent crashes
|
|
49
|
-
console.warn('[STATE] State not initialized, creating with default. This should not happen.', {
|
|
65
|
+
console.warn('[STATE] State not initialized, creating with default. This should not happen.', {
|
|
66
|
+
executionId,
|
|
67
|
+
});
|
|
50
68
|
state = {
|
|
51
69
|
shouldPauseForClient: false,
|
|
52
70
|
replayResults: undefined,
|
|
@@ -57,9 +75,6 @@ function getCurrentState() {
|
|
|
57
75
|
};
|
|
58
76
|
executionStates.set(executionId, state);
|
|
59
77
|
}
|
|
60
|
-
else {
|
|
61
|
-
console.log(`[STATE] Found existing state: shouldPause=${state.shouldPauseForClient}, hasReplay=${!!state.replayResults}, seqNum=${state.callSequenceNumber}`);
|
|
62
|
-
}
|
|
63
78
|
return state;
|
|
64
79
|
}
|
|
65
80
|
/**
|
|
@@ -71,7 +86,6 @@ export function initializeExecutionState(shouldPause) {
|
|
|
71
86
|
if (!executionId) {
|
|
72
87
|
throw new Error('No execution context set. Executor must call setCurrentExecutionId() before initializeExecutionState().');
|
|
73
88
|
}
|
|
74
|
-
console.log(`[INIT] initializeExecutionState called: executionId=${executionId}, shouldPause=${shouldPause}, existingState=${executionStates.has(executionId)}`);
|
|
75
89
|
const existingState = executionStates.get(executionId);
|
|
76
90
|
if (existingState) {
|
|
77
91
|
existingState.shouldPauseForClient = shouldPause;
|
|
@@ -81,7 +95,6 @@ export function initializeExecutionState(shouldPause) {
|
|
|
81
95
|
if (!existingState.apiResultCache) {
|
|
82
96
|
existingState.apiResultCache = undefined;
|
|
83
97
|
}
|
|
84
|
-
console.log(`[INIT] Preserving existing state: replaySize=${existingState.replayResults?.size || 0}, counter=${existingState.callSequenceNumber}`);
|
|
85
98
|
return;
|
|
86
99
|
}
|
|
87
100
|
const state = {
|
|
@@ -92,7 +105,6 @@ export function initializeExecutionState(shouldPause) {
|
|
|
92
105
|
apiResultCache: undefined,
|
|
93
106
|
createdAt: Date.now(),
|
|
94
107
|
};
|
|
95
|
-
console.log(`[INIT] Creating new state: shouldPause=${shouldPause}`);
|
|
96
108
|
executionStates.set(executionId, state);
|
|
97
109
|
}
|
|
98
110
|
/**
|
|
@@ -130,31 +142,19 @@ export function shouldPauseForClient() {
|
|
|
130
142
|
* @param results - Map of sequence number to result for replaying callbacks
|
|
131
143
|
*/
|
|
132
144
|
export function setReplayMode(results) {
|
|
133
|
-
const executionId = currentExecutionId || executionContext.getStore();
|
|
134
|
-
console.log(`[REPLAY] setReplayMode called: executionId=${executionId}, replaySize=${results?.size || 0}, replayKeys=${results ? Array.from(results.keys()) : []}`);
|
|
135
145
|
const state = getCurrentState();
|
|
136
146
|
// Store replay results
|
|
137
|
-
const oldSize = state.replayResults?.size || 0;
|
|
138
147
|
state.replayResults = results;
|
|
139
148
|
// Always reset counter when setting replay mode
|
|
140
149
|
// - When entering replay mode with cached results: start from 0 to match first call
|
|
141
150
|
// - When clearing replay mode (results=undefined): reset to 0 for clean state
|
|
142
|
-
const oldCounter = state.callSequenceNumber;
|
|
143
151
|
state.callSequenceNumber = 0;
|
|
144
|
-
if (results && results.size > 0) {
|
|
145
|
-
console.log(`[REPLAY] Entering replay mode: ${oldCounter} -> 0 (have ${results.size} cached results)`);
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
console.log(`[REPLAY] Clearing replay mode: ${oldCounter} -> 0`);
|
|
149
|
-
}
|
|
150
|
-
console.log(`[REPLAY] setReplayMode completed: oldSize=${oldSize}, newSize=${state.replayResults?.size || 0}, callSequenceNumber=${state.callSequenceNumber}`);
|
|
151
152
|
}
|
|
152
153
|
/**
|
|
153
154
|
* Gets current call sequence number
|
|
154
155
|
*/
|
|
155
156
|
export function getCallSequenceNumber() {
|
|
156
157
|
const state = getCurrentState();
|
|
157
|
-
console.log(`[GET_SEQ] getCallSequenceNumber called: returning ${state.callSequenceNumber}, hasReplay=${!!state.replayResults}, replaySize=${state.replayResults?.size || 0}`);
|
|
158
158
|
return state.callSequenceNumber;
|
|
159
159
|
}
|
|
160
160
|
/**
|
|
@@ -164,7 +164,6 @@ export function nextSequenceNumber() {
|
|
|
164
164
|
const state = getCurrentState();
|
|
165
165
|
const current = state.callSequenceNumber;
|
|
166
166
|
state.callSequenceNumber++;
|
|
167
|
-
console.log(`[SEQUENCE] nextSequenceNumber: returning ${current}, next will be ${state.callSequenceNumber}, isReplay=${state.replayResults !== undefined}, replaySize=${state.replayResults?.size || 0}`);
|
|
168
167
|
return current;
|
|
169
168
|
}
|
|
170
169
|
/**
|
|
@@ -172,13 +171,9 @@ export function nextSequenceNumber() {
|
|
|
172
171
|
*/
|
|
173
172
|
export function getCachedResult(sequenceNumber) {
|
|
174
173
|
const state = getCurrentState();
|
|
175
|
-
console.log(`[CACHE] getCachedResult(${sequenceNumber}): hasReplayResults=${!!state.replayResults}, replayKeys=${state.replayResults ? Array.from(state.replayResults.keys()) : []}`);
|
|
176
174
|
if (state.replayResults && state.replayResults.has(sequenceNumber)) {
|
|
177
|
-
|
|
178
|
-
console.log(`[CACHE] Found cached result for sequence ${sequenceNumber}:`, JSON.stringify(result));
|
|
179
|
-
return result;
|
|
175
|
+
return state.replayResults.get(sequenceNumber);
|
|
180
176
|
}
|
|
181
|
-
console.log(`[CACHE] No cached result for sequence ${sequenceNumber}`);
|
|
182
177
|
return undefined;
|
|
183
178
|
}
|
|
184
179
|
/**
|
|
@@ -245,6 +240,23 @@ export function cleanupExecutionState(executionId) {
|
|
|
245
240
|
currentExecutionId = null;
|
|
246
241
|
}
|
|
247
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* Automatic cleanup when state count exceeds maximum
|
|
245
|
+
* Removes oldest states to keep memory usage bounded
|
|
246
|
+
*/
|
|
247
|
+
function autoCleanup() {
|
|
248
|
+
if (executionStates.size <= MAX_EXECUTION_STATES) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const entries = Array.from(executionStates.entries()).sort((a, b) => a[1].createdAt - b[1].createdAt);
|
|
252
|
+
const toRemove = executionStates.size - MAX_EXECUTION_STATES;
|
|
253
|
+
for (let i = 0; i < toRemove; i++) {
|
|
254
|
+
const entry = entries[i];
|
|
255
|
+
if (entry) {
|
|
256
|
+
executionStates.delete(entry[0]);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
248
260
|
/**
|
|
249
261
|
* Cleanup old execution states to prevent memory leaks
|
|
250
262
|
* Removes states older than the specified max age (default: 1 hour)
|
package/dist/llm/replay.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/llm/replay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAuBhD;;;GAGG;AACH,MAAM,eAAe,GAAG,IAAI,GAAG,EAA0B,CAAC;AAE1D;;;GAGG;AACH,MAAM,gBAAgB,GAAG,IAAI,iBAAiB,EAAU,CAAC;AAEzD;;;;GAIG;AACH,IAAI,kBAAkB,GAAkB,IAAI,CAAC;AAE7C;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAmB;IACxD,kBAAkB,GAAG,WAAW,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB;IACtC,kBAAkB,GAAG,IAAI,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe;IACvB,IAAI,WAAW,GAAG,kBAAkB,CAAC;IAErC,IAAI,CAAC,WAAW,EAAE,CAAC;QAClB,WAAW,GAAG,gBAAgB,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC;IACnD,CAAC;IAED,IAAI,CAAC,WAAW,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CACd,gGAAgG,CAChG,CAAC;IACH,CAAC;IAED,
|
|
1
|
+
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/llm/replay.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/llm/replay.ts
CHANGED
|
@@ -27,6 +27,19 @@ interface ExecutionState {
|
|
|
27
27
|
*/
|
|
28
28
|
const executionStates = new Map<string, ExecutionState>();
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Maximum number of execution states to keep in memory
|
|
32
|
+
* After this limit, old states are automatically cleaned up
|
|
33
|
+
*/
|
|
34
|
+
const MAX_EXECUTION_STATES = 100;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Automatic cleanup check counter
|
|
38
|
+
* Every N operations, we check if cleanup is needed
|
|
39
|
+
*/
|
|
40
|
+
let operationCounter = 0;
|
|
41
|
+
const CLEANUP_CHECK_INTERVAL = 50;
|
|
42
|
+
|
|
30
43
|
/**
|
|
31
44
|
* AsyncLocalStorage for execution ID - provides proper async context isolation
|
|
32
45
|
* This ensures each async execution chain has its own isolated execution ID
|
|
@@ -73,24 +86,29 @@ function getCurrentState(): ExecutionState {
|
|
|
73
86
|
);
|
|
74
87
|
}
|
|
75
88
|
|
|
76
|
-
|
|
89
|
+
// Automatic cleanup check (every N operations)
|
|
90
|
+
operationCounter++;
|
|
91
|
+
if (operationCounter >= CLEANUP_CHECK_INTERVAL) {
|
|
92
|
+
operationCounter = 0;
|
|
93
|
+
autoCleanup();
|
|
94
|
+
}
|
|
77
95
|
|
|
78
96
|
let state = executionStates.get(executionId);
|
|
79
97
|
if (!state) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
98
|
+
// State should have been initialized explicitly at execution start
|
|
99
|
+
// Create it now with a safe default to prevent crashes
|
|
100
|
+
console.warn('[STATE] State not initialized, creating with default. This should not happen.', {
|
|
101
|
+
executionId,
|
|
102
|
+
});
|
|
103
|
+
state = {
|
|
104
|
+
shouldPauseForClient: false,
|
|
105
|
+
replayResults: undefined,
|
|
106
|
+
callSequenceNumber: 0,
|
|
107
|
+
apiCallResults: [],
|
|
108
|
+
apiResultCache: undefined,
|
|
109
|
+
createdAt: Date.now(),
|
|
110
|
+
};
|
|
111
|
+
executionStates.set(executionId, state);
|
|
94
112
|
}
|
|
95
113
|
return state;
|
|
96
114
|
}
|
|
@@ -102,11 +120,11 @@ function getCurrentState(): ExecutionState {
|
|
|
102
120
|
export function initializeExecutionState(shouldPause: boolean): void {
|
|
103
121
|
const executionId = currentExecutionId || executionContext.getStore();
|
|
104
122
|
if (!executionId) {
|
|
105
|
-
throw new Error(
|
|
123
|
+
throw new Error(
|
|
124
|
+
'No execution context set. Executor must call setCurrentExecutionId() before initializeExecutionState().'
|
|
125
|
+
);
|
|
106
126
|
}
|
|
107
127
|
|
|
108
|
-
console.log(`[INIT] initializeExecutionState called: executionId=${executionId}, shouldPause=${shouldPause}, existingState=${executionStates.has(executionId)}`);
|
|
109
|
-
|
|
110
128
|
const existingState = executionStates.get(executionId);
|
|
111
129
|
if (existingState) {
|
|
112
130
|
existingState.shouldPauseForClient = shouldPause;
|
|
@@ -116,7 +134,6 @@ export function initializeExecutionState(shouldPause: boolean): void {
|
|
|
116
134
|
if (!existingState.apiResultCache) {
|
|
117
135
|
existingState.apiResultCache = undefined;
|
|
118
136
|
}
|
|
119
|
-
console.log(`[INIT] Preserving existing state: replaySize=${existingState.replayResults?.size || 0}, counter=${existingState.callSequenceNumber}`);
|
|
120
137
|
return;
|
|
121
138
|
}
|
|
122
139
|
|
|
@@ -128,7 +145,6 @@ export function initializeExecutionState(shouldPause: boolean): void {
|
|
|
128
145
|
apiResultCache: undefined,
|
|
129
146
|
createdAt: Date.now(),
|
|
130
147
|
};
|
|
131
|
-
console.log(`[INIT] Creating new state: shouldPause=${shouldPause}`);
|
|
132
148
|
executionStates.set(executionId, state);
|
|
133
149
|
}
|
|
134
150
|
|
|
@@ -148,7 +164,9 @@ export function runInExecutionContext<T>(executionId: string, fn: () => T): T {
|
|
|
148
164
|
export function setPauseForClient(pause: boolean): void {
|
|
149
165
|
const executionId = currentExecutionId || executionContext.getStore();
|
|
150
166
|
if (!executionId) {
|
|
151
|
-
throw new Error(
|
|
167
|
+
throw new Error(
|
|
168
|
+
'No execution context set. Executor must call setCurrentExecutionId() before setPauseForClient().'
|
|
169
|
+
);
|
|
152
170
|
}
|
|
153
171
|
|
|
154
172
|
const state = executionStates.get(executionId);
|
|
@@ -171,27 +189,15 @@ export function shouldPauseForClient(): boolean {
|
|
|
171
189
|
* @param results - Map of sequence number to result for replaying callbacks
|
|
172
190
|
*/
|
|
173
191
|
export function setReplayMode(results: Map<number, unknown> | undefined): void {
|
|
174
|
-
const executionId = currentExecutionId || executionContext.getStore();
|
|
175
|
-
console.log(`[REPLAY] setReplayMode called: executionId=${executionId}, replaySize=${results?.size || 0}, replayKeys=${results ? Array.from(results.keys()) : []}`);
|
|
176
192
|
const state = getCurrentState();
|
|
177
193
|
|
|
178
194
|
// Store replay results
|
|
179
|
-
const oldSize = state.replayResults?.size || 0;
|
|
180
195
|
state.replayResults = results;
|
|
181
196
|
|
|
182
197
|
// Always reset counter when setting replay mode
|
|
183
198
|
// - When entering replay mode with cached results: start from 0 to match first call
|
|
184
199
|
// - When clearing replay mode (results=undefined): reset to 0 for clean state
|
|
185
|
-
const oldCounter = state.callSequenceNumber;
|
|
186
200
|
state.callSequenceNumber = 0;
|
|
187
|
-
|
|
188
|
-
if (results && results.size > 0) {
|
|
189
|
-
console.log(`[REPLAY] Entering replay mode: ${oldCounter} -> 0 (have ${results.size} cached results)`);
|
|
190
|
-
} else {
|
|
191
|
-
console.log(`[REPLAY] Clearing replay mode: ${oldCounter} -> 0`);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
console.log(`[REPLAY] setReplayMode completed: oldSize=${oldSize}, newSize=${state.replayResults?.size || 0}, callSequenceNumber=${state.callSequenceNumber}`);
|
|
195
201
|
}
|
|
196
202
|
|
|
197
203
|
/**
|
|
@@ -199,7 +205,6 @@ export function setReplayMode(results: Map<number, unknown> | undefined): void {
|
|
|
199
205
|
*/
|
|
200
206
|
export function getCallSequenceNumber(): number {
|
|
201
207
|
const state = getCurrentState();
|
|
202
|
-
console.log(`[GET_SEQ] getCallSequenceNumber called: returning ${state.callSequenceNumber}, hasReplay=${!!state.replayResults}, replaySize=${state.replayResults?.size || 0}`);
|
|
203
208
|
return state.callSequenceNumber;
|
|
204
209
|
}
|
|
205
210
|
|
|
@@ -210,7 +215,6 @@ export function nextSequenceNumber(): number {
|
|
|
210
215
|
const state = getCurrentState();
|
|
211
216
|
const current = state.callSequenceNumber;
|
|
212
217
|
state.callSequenceNumber++;
|
|
213
|
-
console.log(`[SEQUENCE] nextSequenceNumber: returning ${current}, next will be ${state.callSequenceNumber}, isReplay=${state.replayResults !== undefined}, replaySize=${state.replayResults?.size || 0}`);
|
|
214
218
|
return current;
|
|
215
219
|
}
|
|
216
220
|
|
|
@@ -219,13 +223,9 @@ export function nextSequenceNumber(): number {
|
|
|
219
223
|
*/
|
|
220
224
|
export function getCachedResult(sequenceNumber: number): unknown | undefined {
|
|
221
225
|
const state = getCurrentState();
|
|
222
|
-
console.log(`[CACHE] getCachedResult(${sequenceNumber}): hasReplayResults=${!!state.replayResults}, replayKeys=${state.replayResults ? Array.from(state.replayResults.keys()) : []}`);
|
|
223
226
|
if (state.replayResults && state.replayResults.has(sequenceNumber)) {
|
|
224
|
-
|
|
225
|
-
console.log(`[CACHE] Found cached result for sequence ${sequenceNumber}:`, JSON.stringify(result));
|
|
226
|
-
return result;
|
|
227
|
+
return state.replayResults.get(sequenceNumber);
|
|
227
228
|
}
|
|
228
|
-
console.log(`[CACHE] No cached result for sequence ${sequenceNumber}`);
|
|
229
229
|
return undefined;
|
|
230
230
|
}
|
|
231
231
|
|
|
@@ -308,6 +308,28 @@ export function cleanupExecutionState(executionId: string): void {
|
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
+
/**
|
|
312
|
+
* Automatic cleanup when state count exceeds maximum
|
|
313
|
+
* Removes oldest states to keep memory usage bounded
|
|
314
|
+
*/
|
|
315
|
+
function autoCleanup(): void {
|
|
316
|
+
if (executionStates.size <= MAX_EXECUTION_STATES) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const entries = Array.from(executionStates.entries()).sort(
|
|
321
|
+
(a, b) => a[1].createdAt - b[1].createdAt
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
const toRemove = executionStates.size - MAX_EXECUTION_STATES;
|
|
325
|
+
for (let i = 0; i < toRemove; i++) {
|
|
326
|
+
const entry = entries[i];
|
|
327
|
+
if (entry) {
|
|
328
|
+
executionStates.delete(entry[0]);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
311
333
|
/**
|
|
312
334
|
* Cleanup old execution states to prevent memory leaks
|
|
313
335
|
* Removes states older than the specified max age (default: 1 hour)
|
|
@@ -315,7 +337,7 @@ export function cleanupExecutionState(executionId: string): void {
|
|
|
315
337
|
export function cleanupOldExecutionStates(maxAgeMs: number = 3600000): number {
|
|
316
338
|
const now = Date.now();
|
|
317
339
|
let cleaned = 0;
|
|
318
|
-
|
|
340
|
+
|
|
319
341
|
for (const [executionId, state] of executionStates.entries()) {
|
|
320
342
|
const age = now - state.createdAt;
|
|
321
343
|
if (age > maxAgeMs) {
|
|
@@ -323,7 +345,7 @@ export function cleanupOldExecutionStates(maxAgeMs: number = 3600000): number {
|
|
|
323
345
|
cleaned++;
|
|
324
346
|
}
|
|
325
347
|
}
|
|
326
|
-
|
|
348
|
+
|
|
327
349
|
return cleaned;
|
|
328
350
|
}
|
|
329
351
|
|
|
@@ -349,7 +371,7 @@ export function getExecutionStateStats(): {
|
|
|
349
371
|
const executionIds = Array.from(executionStates.keys());
|
|
350
372
|
let oldestAge: number | null = null;
|
|
351
373
|
let newestAge: number | null = null;
|
|
352
|
-
|
|
374
|
+
|
|
353
375
|
for (const state of executionStates.values()) {
|
|
354
376
|
const age = now - state.createdAt;
|
|
355
377
|
if (oldestAge === null || age > oldestAge) {
|
|
@@ -359,7 +381,7 @@ export function getExecutionStateStats(): {
|
|
|
359
381
|
newestAge = age;
|
|
360
382
|
}
|
|
361
383
|
}
|
|
362
|
-
|
|
384
|
+
|
|
363
385
|
return {
|
|
364
386
|
totalStates: executionStates.size,
|
|
365
387
|
oldestStateAge: oldestAge,
|