@rivet-dev/flue 0.0.0-stack-fix-rivetkit-route-all-actor-sqlite-through-envoy-when-local-sqlite-is-not-compiled-pppnpqnl.0cdbf72
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 +26 -0
- package/dist/agent-coordinator.d.ts +89 -0
- package/dist/agent-coordinator.d.ts.map +1 -0
- package/dist/agent-coordinator.js +346 -0
- package/dist/agent-coordinator.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +3 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +2 -0
- package/dist/internal.js.map +1 -0
- package/dist/registry-ops-async.d.ts +7 -0
- package/dist/registry-ops-async.d.ts.map +1 -0
- package/dist/registry-ops-async.js +12 -0
- package/dist/registry-ops-async.js.map +1 -0
- package/dist/rivet-db.d.ts +7 -0
- package/dist/rivet-db.d.ts.map +1 -0
- package/dist/rivet-db.js +65 -0
- package/dist/rivet-db.js.map +1 -0
- package/dist/run-store-composite.d.ts +3 -0
- package/dist/run-store-composite.d.ts.map +1 -0
- package/dist/run-store-composite.js +43 -0
- package/dist/run-store-composite.js.map +1 -0
- package/dist/runtime.d.ts +8 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +7 -0
- package/dist/runtime.js.map +1 -0
- package/dist/stores/async-db.d.ts +10 -0
- package/dist/stores/async-db.d.ts.map +1 -0
- package/dist/stores/async-db.js +5 -0
- package/dist/stores/async-db.js.map +1 -0
- package/dist/stores/attachment-store.d.ts +4 -0
- package/dist/stores/attachment-store.d.ts.map +1 -0
- package/dist/stores/attachment-store.js +59 -0
- package/dist/stores/attachment-store.js.map +1 -0
- package/dist/stores/constants.d.ts +11 -0
- package/dist/stores/constants.d.ts.map +1 -0
- package/dist/stores/constants.js +11 -0
- package/dist/stores/constants.js.map +1 -0
- package/dist/stores/conversation-stream-store.d.ts +4 -0
- package/dist/stores/conversation-stream-store.d.ts.map +1 -0
- package/dist/stores/conversation-stream-store.js +35 -0
- package/dist/stores/conversation-stream-store.js.map +1 -0
- package/dist/stores/event-stream-store.d.ts +6 -0
- package/dist/stores/event-stream-store.d.ts.map +1 -0
- package/dist/stores/event-stream-store.js +156 -0
- package/dist/stores/event-stream-store.js.map +1 -0
- package/dist/stores/helpers.d.ts +2 -0
- package/dist/stores/helpers.d.ts.map +1 -0
- package/dist/stores/helpers.js +6 -0
- package/dist/stores/helpers.js.map +1 -0
- package/dist/stores/index.d.ts +11 -0
- package/dist/stores/index.d.ts.map +1 -0
- package/dist/stores/index.js +23 -0
- package/dist/stores/index.js.map +1 -0
- package/dist/stores/listener-registry.d.ts +6 -0
- package/dist/stores/listener-registry.d.ts.map +1 -0
- package/dist/stores/listener-registry.js +27 -0
- package/dist/stores/listener-registry.js.map +1 -0
- package/dist/stores/run-store.d.ts +4 -0
- package/dist/stores/run-store.d.ts.map +1 -0
- package/dist/stores/run-store.js +117 -0
- package/dist/stores/run-store.js.map +1 -0
- package/dist/stores/schema.d.ts +3 -0
- package/dist/stores/schema.d.ts.map +1 -0
- package/dist/stores/schema.js +241 -0
- package/dist/stores/schema.js.map +1 -0
- package/dist/stores/submission-store.d.ts +4 -0
- package/dist/stores/submission-store.d.ts.map +1 -0
- package/dist/stores/submission-store.js +261 -0
- package/dist/stores/submission-store.js.map +1 -0
- package/dist/target.d.ts +8 -0
- package/dist/target.d.ts.map +1 -0
- package/dist/target.js +420 -0
- package/dist/target.js.map +1 -0
- package/dist/workflow-coordinator.d.ts +71 -0
- package/dist/workflow-coordinator.d.ts.map +1 -0
- package/dist/workflow-coordinator.js +154 -0
- package/dist/workflow-coordinator.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT } from './constants.js';
|
|
2
|
+
import { clampLimit } from './helpers.js';
|
|
3
|
+
export function createAsyncRunStore(db) {
|
|
4
|
+
return new AsyncRunStore(db);
|
|
5
|
+
}
|
|
6
|
+
class AsyncRunStore {
|
|
7
|
+
db;
|
|
8
|
+
constructor(db) {
|
|
9
|
+
this.db = db;
|
|
10
|
+
}
|
|
11
|
+
async createRun(input) {
|
|
12
|
+
await this.db.query(`INSERT OR IGNORE INTO flue_runs
|
|
13
|
+
(run_id, workflow_name, status, started_at, payload, traceparent, tracestate,
|
|
14
|
+
ended_at, is_error, duration_ms, result, error)
|
|
15
|
+
VALUES (?, ?, 'active', ?, ?, ?, ?, NULL, NULL, NULL, NULL, NULL)`, [input.runId, input.workflowName, input.startedAt, serializeJson(input.input),
|
|
16
|
+
input.traceCarrier?.traceparent ?? null, input.traceCarrier?.tracestate ?? null]);
|
|
17
|
+
}
|
|
18
|
+
async endRun(input) {
|
|
19
|
+
await this.db.query(`UPDATE flue_runs
|
|
20
|
+
SET status = ?, ended_at = ?, is_error = ?, duration_ms = ?, result = ?, error = ?
|
|
21
|
+
WHERE run_id = ?`, [
|
|
22
|
+
input.isError ? 'errored' : 'completed',
|
|
23
|
+
input.endedAt,
|
|
24
|
+
input.isError ? 1 : 0,
|
|
25
|
+
input.durationMs,
|
|
26
|
+
serializeJson(input.result),
|
|
27
|
+
serializeJson(input.error),
|
|
28
|
+
input.runId,
|
|
29
|
+
]);
|
|
30
|
+
}
|
|
31
|
+
async getRun(runId) {
|
|
32
|
+
const rows = await this.db.query('SELECT * FROM flue_runs WHERE run_id = ? LIMIT 1', [runId]);
|
|
33
|
+
const row = rows[0];
|
|
34
|
+
return row ? rowToRunRecord(row) : null;
|
|
35
|
+
}
|
|
36
|
+
async lookupRun(runId) {
|
|
37
|
+
const rows = await this.db.query(`SELECT run_id, workflow_name
|
|
38
|
+
FROM flue_runs WHERE run_id = ? LIMIT 1`, [runId]);
|
|
39
|
+
const row = rows[0];
|
|
40
|
+
return row ? { runId: String(row.run_id), workflowName: String(row.workflow_name) } : null;
|
|
41
|
+
}
|
|
42
|
+
async listRuns(opts = {}) {
|
|
43
|
+
const limit = clampLimit(opts.limit, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT);
|
|
44
|
+
const cursor = decodeRunCursor(opts.cursor);
|
|
45
|
+
const wheres = [];
|
|
46
|
+
const bindings = [];
|
|
47
|
+
if (opts.status) {
|
|
48
|
+
wheres.push('status = ?');
|
|
49
|
+
bindings.push(opts.status);
|
|
50
|
+
}
|
|
51
|
+
if (opts.workflowName) {
|
|
52
|
+
wheres.push('workflow_name = ?');
|
|
53
|
+
bindings.push(opts.workflowName);
|
|
54
|
+
}
|
|
55
|
+
if (cursor) {
|
|
56
|
+
wheres.push('(started_at < ? OR (started_at = ? AND run_id < ?))');
|
|
57
|
+
bindings.push(cursor.startedAt, cursor.startedAt, cursor.runId);
|
|
58
|
+
}
|
|
59
|
+
const where = wheres.length > 0 ? `WHERE ${wheres.join(' AND ')}` : '';
|
|
60
|
+
const rows = await this.db.query(`SELECT run_id, workflow_name, status, started_at, ended_at, duration_ms, is_error
|
|
61
|
+
FROM flue_runs ${where}
|
|
62
|
+
ORDER BY started_at DESC, run_id DESC
|
|
63
|
+
LIMIT ?`, [...bindings, limit + 1]);
|
|
64
|
+
const hasMore = rows.length > limit;
|
|
65
|
+
const page = (hasMore ? rows.slice(0, limit) : rows).map(rowToRunPointer);
|
|
66
|
+
const last = page.at(-1);
|
|
67
|
+
return { runs: page, nextCursor: hasMore && last ? encodeRunCursor(last) : undefined };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function serializeJson(value) {
|
|
71
|
+
return JSON.stringify(value) ?? null;
|
|
72
|
+
}
|
|
73
|
+
function rowToRunRecord(row) {
|
|
74
|
+
return {
|
|
75
|
+
runId: String(row.run_id),
|
|
76
|
+
workflowName: String(row.workflow_name),
|
|
77
|
+
status: String(row.status),
|
|
78
|
+
startedAt: String(row.started_at),
|
|
79
|
+
...(typeof row.payload === 'string' ? { input: JSON.parse(row.payload) } : {}),
|
|
80
|
+
...(typeof row.traceparent === 'string' ? { traceCarrier: {
|
|
81
|
+
traceparent: row.traceparent,
|
|
82
|
+
...(typeof row.tracestate === 'string' ? { tracestate: row.tracestate } : {}),
|
|
83
|
+
} } : {}),
|
|
84
|
+
...(typeof row.ended_at === 'string' ? { endedAt: row.ended_at } : {}),
|
|
85
|
+
...(row.is_error === null || row.is_error === undefined ? {} : { isError: Boolean(row.is_error) }),
|
|
86
|
+
...(row.duration_ms != null ? { durationMs: Number(row.duration_ms) } : {}),
|
|
87
|
+
...(typeof row.result === 'string' ? { result: JSON.parse(row.result) } : {}),
|
|
88
|
+
...(typeof row.error === 'string' ? { error: JSON.parse(row.error) } : {}),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function rowToRunPointer(row) {
|
|
92
|
+
return {
|
|
93
|
+
runId: String(row.run_id),
|
|
94
|
+
workflowName: String(row.workflow_name),
|
|
95
|
+
status: String(row.status),
|
|
96
|
+
startedAt: String(row.started_at),
|
|
97
|
+
...(typeof row.ended_at === 'string' ? { endedAt: row.ended_at } : {}),
|
|
98
|
+
...(row.duration_ms != null ? { durationMs: Number(row.duration_ms) } : {}),
|
|
99
|
+
...(row.is_error === null || row.is_error === undefined ? {} : { isError: Boolean(row.is_error) }),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function encodeRunCursor(pointer) {
|
|
103
|
+
return Buffer.from(JSON.stringify({ s: pointer.startedAt, r: pointer.runId })).toString('base64url');
|
|
104
|
+
}
|
|
105
|
+
function decodeRunCursor(cursor) {
|
|
106
|
+
if (!cursor)
|
|
107
|
+
return undefined;
|
|
108
|
+
try {
|
|
109
|
+
const decoded = JSON.parse(Buffer.from(cursor, 'base64url').toString('utf8'));
|
|
110
|
+
if (typeof decoded.s === 'string' && typeof decoded.r === 'string') {
|
|
111
|
+
return { startedAt: decoded.s, runId: decoded.r };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch { }
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=run-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-store.js","sourceRoot":"","sources":["../../src/stores/run-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/stores/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,eAAe,CAAC;AAmBhE,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBxE"}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { FLUE_SCHEMA_VERSION, DURABILITY_DEFAULT_MAX_ATTEMPTS } from './constants.js';
|
|
2
|
+
/*
|
|
3
|
+
@upstream-schema-provenance
|
|
4
|
+
{
|
|
5
|
+
"repository": "https://github.com/rivet-dev/flue",
|
|
6
|
+
"commit": "e79d5712820af588094a4e67a3ceafc816770396",
|
|
7
|
+
"sources": [
|
|
8
|
+
"packages/runtime/src/sql-agent-execution-store.ts",
|
|
9
|
+
"packages/runtime/src/sql-run-store.ts",
|
|
10
|
+
"packages/runtime/src/sql-attachment-store.ts",
|
|
11
|
+
"packages/runtime/src/sql-persisted-chunk-store.ts",
|
|
12
|
+
"packages/runtime/src/runtime/event-stream-store.ts",
|
|
13
|
+
"packages/runtime/src/runtime/conversation-stream-store.ts"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
*/
|
|
17
|
+
// Rivet-local tables not copied from those sources: flue_meta, flue_sessions,
|
|
18
|
+
// and flue_session_entries.
|
|
19
|
+
export async function ensureAsyncSqlSchema(db) {
|
|
20
|
+
await db.transaction(async (tx) => {
|
|
21
|
+
await tx.query(`
|
|
22
|
+
CREATE TABLE IF NOT EXISTS flue_meta (
|
|
23
|
+
key TEXT PRIMARY KEY,
|
|
24
|
+
value TEXT NOT NULL
|
|
25
|
+
)
|
|
26
|
+
`);
|
|
27
|
+
const versionRows = await tx.query(`SELECT value FROM flue_meta WHERE key = 'schema_version'`);
|
|
28
|
+
const storedVersion = versionRows[0]?.value;
|
|
29
|
+
if (storedVersion === undefined || storedVersion === null) {
|
|
30
|
+
await tx.query(`INSERT OR IGNORE INTO flue_meta (key, value) VALUES ('schema_version', ?)`, [
|
|
31
|
+
String(FLUE_SCHEMA_VERSION),
|
|
32
|
+
]);
|
|
33
|
+
}
|
|
34
|
+
else if (String(storedVersion) !== String(FLUE_SCHEMA_VERSION)) {
|
|
35
|
+
throw new Error(`[flue] Persisted store schema version ${String(storedVersion)} is not supported by this adapter.`);
|
|
36
|
+
}
|
|
37
|
+
await ensureTables(tx);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async function ensureTables(tx) {
|
|
41
|
+
await tx.query(`
|
|
42
|
+
CREATE TABLE IF NOT EXISTS flue_sessions (
|
|
43
|
+
id TEXT PRIMARY KEY,
|
|
44
|
+
data TEXT NOT NULL
|
|
45
|
+
)
|
|
46
|
+
`);
|
|
47
|
+
await tx.query(`
|
|
48
|
+
CREATE TABLE IF NOT EXISTS flue_session_entries (
|
|
49
|
+
session_id TEXT NOT NULL,
|
|
50
|
+
entry_id TEXT NOT NULL,
|
|
51
|
+
position INTEGER NOT NULL,
|
|
52
|
+
data TEXT NOT NULL,
|
|
53
|
+
PRIMARY KEY (session_id, entry_id)
|
|
54
|
+
)
|
|
55
|
+
`);
|
|
56
|
+
await tx.query(`
|
|
57
|
+
CREATE INDEX IF NOT EXISTS flue_session_entries_session_position_idx
|
|
58
|
+
ON flue_session_entries (session_id, position ASC)
|
|
59
|
+
`);
|
|
60
|
+
await tx.query(`
|
|
61
|
+
CREATE TABLE IF NOT EXISTS flue_image_chunks (
|
|
62
|
+
owner_kind TEXT NOT NULL,
|
|
63
|
+
owner_id TEXT NOT NULL,
|
|
64
|
+
owner_part TEXT NOT NULL,
|
|
65
|
+
image_id TEXT NOT NULL,
|
|
66
|
+
chunk_index INTEGER NOT NULL,
|
|
67
|
+
chunk_count INTEGER NOT NULL,
|
|
68
|
+
data TEXT NOT NULL,
|
|
69
|
+
PRIMARY KEY (owner_kind, owner_id, owner_part, image_id, chunk_index)
|
|
70
|
+
)
|
|
71
|
+
`);
|
|
72
|
+
await tx.query(`
|
|
73
|
+
CREATE TABLE IF NOT EXISTS flue_agent_submissions (
|
|
74
|
+
sequence INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
75
|
+
submission_id TEXT NOT NULL UNIQUE,
|
|
76
|
+
session_key TEXT NOT NULL,
|
|
77
|
+
kind TEXT NOT NULL,
|
|
78
|
+
payload TEXT NOT NULL,
|
|
79
|
+
status TEXT NOT NULL,
|
|
80
|
+
accepted_at INTEGER NOT NULL,
|
|
81
|
+
canonical_ready_at INTEGER,
|
|
82
|
+
attempt_id TEXT,
|
|
83
|
+
input_applied_at INTEGER,
|
|
84
|
+
recovery_requested_at INTEGER,
|
|
85
|
+
abort_requested_at INTEGER,
|
|
86
|
+
started_at INTEGER,
|
|
87
|
+
settled_at INTEGER,
|
|
88
|
+
error TEXT,
|
|
89
|
+
attempt_count INTEGER NOT NULL DEFAULT 0,
|
|
90
|
+
max_retry INTEGER NOT NULL DEFAULT ${DURABILITY_DEFAULT_MAX_ATTEMPTS},
|
|
91
|
+
timeout_at INTEGER NOT NULL DEFAULT 0,
|
|
92
|
+
owner_id TEXT,
|
|
93
|
+
lease_expires_at INTEGER NOT NULL DEFAULT 0,
|
|
94
|
+
settlement_record_id TEXT,
|
|
95
|
+
settlement_record TEXT
|
|
96
|
+
)
|
|
97
|
+
`);
|
|
98
|
+
await tx.query(`
|
|
99
|
+
CREATE INDEX IF NOT EXISTS flue_agent_submissions_status_sequence_idx
|
|
100
|
+
ON flue_agent_submissions (status, sequence ASC)
|
|
101
|
+
`);
|
|
102
|
+
await tx.query(`
|
|
103
|
+
CREATE INDEX IF NOT EXISTS flue_agent_submissions_session_status_sequence_idx
|
|
104
|
+
ON flue_agent_submissions (session_key, status, sequence ASC)
|
|
105
|
+
`);
|
|
106
|
+
await tx.query(`
|
|
107
|
+
CREATE TABLE IF NOT EXISTS flue_agent_turn_journals (
|
|
108
|
+
submission_id TEXT PRIMARY KEY,
|
|
109
|
+
session_key TEXT NOT NULL,
|
|
110
|
+
kind TEXT NOT NULL,
|
|
111
|
+
attempt_id TEXT NOT NULL,
|
|
112
|
+
operation_id TEXT NOT NULL,
|
|
113
|
+
turn_id TEXT NOT NULL,
|
|
114
|
+
phase TEXT NOT NULL,
|
|
115
|
+
revision INTEGER NOT NULL,
|
|
116
|
+
created_at INTEGER NOT NULL,
|
|
117
|
+
updated_at INTEGER NOT NULL,
|
|
118
|
+
checkpoint_leaf_id TEXT,
|
|
119
|
+
tool_request_json TEXT,
|
|
120
|
+
stream_key TEXT,
|
|
121
|
+
stream_consumed_at INTEGER,
|
|
122
|
+
committed INTEGER NOT NULL DEFAULT 0,
|
|
123
|
+
committed_leaf_id TEXT
|
|
124
|
+
)
|
|
125
|
+
`);
|
|
126
|
+
await tx.query(`
|
|
127
|
+
CREATE TABLE IF NOT EXISTS flue_agent_stream_chunks (
|
|
128
|
+
stream_key TEXT NOT NULL,
|
|
129
|
+
segment_index INTEGER NOT NULL,
|
|
130
|
+
body TEXT NOT NULL,
|
|
131
|
+
PRIMARY KEY (stream_key, segment_index)
|
|
132
|
+
)
|
|
133
|
+
`);
|
|
134
|
+
await tx.query(`
|
|
135
|
+
CREATE TABLE IF NOT EXISTS flue_agent_session_deletions (
|
|
136
|
+
session_key TEXT PRIMARY KEY,
|
|
137
|
+
started_at INTEGER NOT NULL
|
|
138
|
+
)
|
|
139
|
+
`);
|
|
140
|
+
await tx.query(`
|
|
141
|
+
CREATE TABLE IF NOT EXISTS flue_agent_dispatch_receipts (
|
|
142
|
+
dispatch_id TEXT PRIMARY KEY,
|
|
143
|
+
accepted_at INTEGER NOT NULL
|
|
144
|
+
)
|
|
145
|
+
`);
|
|
146
|
+
await tx.query(`
|
|
147
|
+
CREATE TABLE IF NOT EXISTS flue_agent_attempt_markers (
|
|
148
|
+
submission_id TEXT NOT NULL,
|
|
149
|
+
attempt_id TEXT NOT NULL,
|
|
150
|
+
created_at INTEGER NOT NULL,
|
|
151
|
+
PRIMARY KEY (submission_id, attempt_id)
|
|
152
|
+
)
|
|
153
|
+
`);
|
|
154
|
+
await tx.query(`
|
|
155
|
+
CREATE TABLE IF NOT EXISTS flue_runs (
|
|
156
|
+
run_id TEXT PRIMARY KEY,
|
|
157
|
+
workflow_name TEXT NOT NULL,
|
|
158
|
+
status TEXT NOT NULL,
|
|
159
|
+
started_at TEXT NOT NULL,
|
|
160
|
+
payload TEXT,
|
|
161
|
+
traceparent TEXT,
|
|
162
|
+
tracestate TEXT,
|
|
163
|
+
ended_at TEXT,
|
|
164
|
+
is_error INTEGER,
|
|
165
|
+
duration_ms INTEGER,
|
|
166
|
+
result TEXT,
|
|
167
|
+
error TEXT
|
|
168
|
+
)
|
|
169
|
+
`);
|
|
170
|
+
await tx.query(`
|
|
171
|
+
CREATE INDEX IF NOT EXISTS flue_runs_workflow_started_idx
|
|
172
|
+
ON flue_runs (workflow_name, started_at DESC)
|
|
173
|
+
`);
|
|
174
|
+
await tx.query(`
|
|
175
|
+
CREATE INDEX IF NOT EXISTS flue_runs_status_started_idx
|
|
176
|
+
ON flue_runs (status, started_at DESC, run_id DESC)
|
|
177
|
+
`);
|
|
178
|
+
await tx.query(`
|
|
179
|
+
CREATE TABLE IF NOT EXISTS flue_event_streams (
|
|
180
|
+
path TEXT PRIMARY KEY,
|
|
181
|
+
next_offset INTEGER NOT NULL DEFAULT 0,
|
|
182
|
+
closed INTEGER NOT NULL DEFAULT 0
|
|
183
|
+
)
|
|
184
|
+
`);
|
|
185
|
+
await tx.query(`
|
|
186
|
+
CREATE TABLE IF NOT EXISTS flue_event_stream_entries (
|
|
187
|
+
path TEXT NOT NULL,
|
|
188
|
+
seq INTEGER NOT NULL,
|
|
189
|
+
data TEXT NOT NULL,
|
|
190
|
+
PRIMARY KEY (path, seq)
|
|
191
|
+
)
|
|
192
|
+
`);
|
|
193
|
+
await tx.query(`
|
|
194
|
+
CREATE TABLE IF NOT EXISTS flue_event_stream_keys (
|
|
195
|
+
path TEXT NOT NULL,
|
|
196
|
+
key TEXT NOT NULL,
|
|
197
|
+
seq INTEGER NOT NULL,
|
|
198
|
+
data TEXT NOT NULL,
|
|
199
|
+
PRIMARY KEY (path, key)
|
|
200
|
+
)
|
|
201
|
+
`);
|
|
202
|
+
await tx.query(`
|
|
203
|
+
CREATE TABLE IF NOT EXISTS flue_conversation_streams (
|
|
204
|
+
path TEXT PRIMARY KEY,
|
|
205
|
+
identity_json TEXT NOT NULL,
|
|
206
|
+
producer_id TEXT,
|
|
207
|
+
producer_epoch INTEGER NOT NULL DEFAULT 0,
|
|
208
|
+
next_producer_sequence INTEGER NOT NULL DEFAULT 0,
|
|
209
|
+
next_offset INTEGER NOT NULL DEFAULT 0,
|
|
210
|
+
incarnation TEXT NOT NULL
|
|
211
|
+
)
|
|
212
|
+
`);
|
|
213
|
+
await tx.query(`
|
|
214
|
+
CREATE TABLE IF NOT EXISTS flue_conversation_stream_batches (
|
|
215
|
+
path TEXT NOT NULL,
|
|
216
|
+
seq INTEGER NOT NULL,
|
|
217
|
+
producer_id TEXT NOT NULL,
|
|
218
|
+
producer_epoch INTEGER NOT NULL,
|
|
219
|
+
producer_sequence INTEGER NOT NULL,
|
|
220
|
+
data TEXT NOT NULL,
|
|
221
|
+
submission_id TEXT,
|
|
222
|
+
attempt_id TEXT,
|
|
223
|
+
PRIMARY KEY (path, seq),
|
|
224
|
+
UNIQUE (path, producer_id, producer_epoch, producer_sequence)
|
|
225
|
+
)
|
|
226
|
+
`);
|
|
227
|
+
await tx.query(`
|
|
228
|
+
CREATE TABLE IF NOT EXISTS flue_attachments (
|
|
229
|
+
stream_path TEXT NOT NULL,
|
|
230
|
+
attachment_id TEXT NOT NULL,
|
|
231
|
+
conversation_id TEXT NOT NULL,
|
|
232
|
+
mime_type TEXT NOT NULL,
|
|
233
|
+
filename TEXT,
|
|
234
|
+
size INTEGER NOT NULL,
|
|
235
|
+
digest TEXT NOT NULL,
|
|
236
|
+
data TEXT NOT NULL,
|
|
237
|
+
PRIMARY KEY (stream_path, attachment_id)
|
|
238
|
+
)
|
|
239
|
+
`);
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/stores/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,+BAA+B,EAAE,MAAM,gBAAgB,CAAC;AAGtF;;;;;;;;;;;;;;EAcE;AACF,8EAA8E;AAC9E,4BAA4B;AAC5B,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,EAAc;IACxD,MAAM,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACjC,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;GAKd,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAC/F,MAAM,aAAa,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;QAC5C,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YAC3D,MAAM,EAAE,CAAC,KAAK,CAAC,2EAA2E,EAAE;gBAC3F,MAAM,CAAC,mBAAmB,CAAC;aAC3B,CAAC,CAAC;QACJ,CAAC;aAAM,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK,MAAM,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAClE,MAAM,IAAI,KAAK,CACd,yCAAyC,MAAM,CAAC,aAAa,CAAC,oCAAoC,CAClG,CAAC;QACH,CAAC;QAED,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,EAAkB;IAC7C,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;EAKd,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;;;;EAQd,CAAC,CAAC;IACH,MAAM,EAAE,CAAC,KAAK,CAAC;;;EAGd,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;;;;;;;EAWd,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;wCAkBwB,+BAA+B;;;;;;;EAOrE,CAAC,CAAC;IACH,MAAM,EAAE,CAAC,KAAK,CAAC;;;EAGd,CAAC,CAAC;IACH,MAAM,EAAE,CAAC,KAAK,CAAC;;;EAGd,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;EAmBd,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;;;EAOd,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;EAKd,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;EAKd,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;;;EAOd,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;EAed,CAAC,CAAC;IACH,MAAM,EAAE,CAAC,KAAK,CAAC;;;EAGd,CAAC,CAAC;IACH,MAAM,EAAE,CAAC,KAAK,CAAC;;;EAGd,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;;EAMd,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;;;EAOd,CAAC,CAAC;IACH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;;;;EAQd,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;;;;;;EAUd,CAAC,CAAC;IACH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;;;;;;;;;EAad,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;;;;;;;;EAYd,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submission-store.d.ts","sourceRoot":"","sources":["../../src/stores/submission-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKX,oBAAoB,EAMpB,MAAM,2BAA2B,CAAC;AAKnC,OAAO,KAAK,EAAE,UAAU,EAA+B,MAAM,eAAe,CAAC;AAqB7E,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,UAAU,GAAG,oBAAoB,CAE/E"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { createDispatchAgentSubmissionInput, createSessionStorageKey, } from '@flue/runtime/adapter-kit';
|
|
2
|
+
import { DURABILITY_DEFAULT_MAX_ATTEMPTS, DURABILITY_DEFAULT_TIMEOUT_MS, LEASE_DURATION_MS, SUBMISSION_HARNESS_NAME, SUBMISSION_SESSION_NAME, } from './constants.js';
|
|
3
|
+
const columns = [
|
|
4
|
+
'sequence', 'submission_id', 'session_key', 'kind', 'payload', 'status', 'accepted_at',
|
|
5
|
+
'canonical_ready_at', 'attempt_id', 'input_applied_at', 'recovery_requested_at',
|
|
6
|
+
'abort_requested_at', 'started_at', 'error', 'attempt_count', 'max_retry', 'timeout_at',
|
|
7
|
+
'owner_id', 'lease_expires_at',
|
|
8
|
+
].join(', ');
|
|
9
|
+
const prefixedColumns = (table) => columns
|
|
10
|
+
.split(', ')
|
|
11
|
+
.map((column) => `${table}.${column}`)
|
|
12
|
+
.join(', ');
|
|
13
|
+
export function createAsyncSubmissionStore(db) {
|
|
14
|
+
return new AsyncSubmissionStore(db);
|
|
15
|
+
}
|
|
16
|
+
class AsyncSubmissionStore {
|
|
17
|
+
db;
|
|
18
|
+
constructor(db) {
|
|
19
|
+
this.db = db;
|
|
20
|
+
}
|
|
21
|
+
async getSubmission(submissionId) {
|
|
22
|
+
const rows = await this.db.query(`SELECT ${columns} FROM flue_agent_submissions WHERE submission_id = ? LIMIT 1`, [submissionId]);
|
|
23
|
+
return rows[0] ? parseSubmission(rows[0]) : null;
|
|
24
|
+
}
|
|
25
|
+
async hasUnsettledSubmissions() {
|
|
26
|
+
return (await this.db.query(`SELECT 1 FROM flue_agent_submissions WHERE status IN ('queued', 'running', 'terminalizing') LIMIT 1`)).length > 0;
|
|
27
|
+
}
|
|
28
|
+
async listUnreadySubmissions() {
|
|
29
|
+
return this.readOperational(`SELECT ${columns} FROM flue_agent_submissions
|
|
30
|
+
WHERE status = 'queued' AND canonical_ready_at IS NULL ORDER BY sequence ASC`, [], 'queued');
|
|
31
|
+
}
|
|
32
|
+
async listRunnableSubmissions() {
|
|
33
|
+
return this.readOperational(`SELECT ${prefixedColumns('current')} FROM flue_agent_submissions AS current
|
|
34
|
+
WHERE current.status = 'queued' AND current.canonical_ready_at IS NOT NULL
|
|
35
|
+
AND NOT EXISTS (
|
|
36
|
+
SELECT 1 FROM flue_agent_submissions AS earlier
|
|
37
|
+
WHERE earlier.session_key = current.session_key
|
|
38
|
+
AND earlier.status IN ('queued', 'running', 'terminalizing')
|
|
39
|
+
AND earlier.sequence < current.sequence
|
|
40
|
+
) ORDER BY current.sequence ASC`, [], 'queued');
|
|
41
|
+
}
|
|
42
|
+
async listRunningSubmissions() {
|
|
43
|
+
return this.readOperational(`SELECT ${columns} FROM flue_agent_submissions WHERE status = 'running' ORDER BY sequence ASC`, [], 'active');
|
|
44
|
+
}
|
|
45
|
+
async listPendingSubmissionSettlements() {
|
|
46
|
+
const rows = await this.db.query(`SELECT submission_id, session_key, attempt_id, settlement_record_id, settlement_record
|
|
47
|
+
FROM flue_agent_submissions WHERE kind = 'direct' AND status = 'terminalizing'
|
|
48
|
+
ORDER BY sequence ASC`);
|
|
49
|
+
return rows.map(parseSettlement);
|
|
50
|
+
}
|
|
51
|
+
async replaceSubmissionAttempt(attempt, nextAttemptId, lease) {
|
|
52
|
+
const rows = await this.db.query(`UPDATE flue_agent_submissions
|
|
53
|
+
SET attempt_id = ?, recovery_requested_at = NULL, started_at = ?,
|
|
54
|
+
attempt_count = attempt_count + 1${lease ? ', owner_id = ?, lease_expires_at = ?' : ''}
|
|
55
|
+
WHERE submission_id = ? AND status = 'running' AND attempt_id = ?
|
|
56
|
+
RETURNING ${columns}`, lease
|
|
57
|
+
? [nextAttemptId, Date.now(), lease.ownerId, lease.leaseExpiresAt, attempt.submissionId, attempt.attemptId]
|
|
58
|
+
: [nextAttemptId, Date.now(), attempt.submissionId, attempt.attemptId]);
|
|
59
|
+
return rows[0] ? parseSubmission(rows[0]) : null;
|
|
60
|
+
}
|
|
61
|
+
admitDispatch(input) {
|
|
62
|
+
return this.admit(createDispatchAgentSubmissionInput(input));
|
|
63
|
+
}
|
|
64
|
+
async admitDirect(input) {
|
|
65
|
+
const result = await this.admit(input);
|
|
66
|
+
if (result.kind !== 'submission') {
|
|
67
|
+
throw new Error('[flue] Internal direct admission returned an unexpected result.');
|
|
68
|
+
}
|
|
69
|
+
return result.submission;
|
|
70
|
+
}
|
|
71
|
+
async markSubmissionCanonicalReady(submissionId) {
|
|
72
|
+
const rows = await this.db.query(`UPDATE flue_agent_submissions SET canonical_ready_at = COALESCE(canonical_ready_at, ?)
|
|
73
|
+
WHERE submission_id = ? AND status = 'queued' RETURNING ${columns}`, [Date.now(), submissionId]);
|
|
74
|
+
return rows[0] ? parseSubmission(rows[0]) : null;
|
|
75
|
+
}
|
|
76
|
+
async claimSubmission(claim) {
|
|
77
|
+
const now = Date.now();
|
|
78
|
+
const rows = await this.db.query(`UPDATE flue_agent_submissions AS current
|
|
79
|
+
SET status = 'running', attempt_id = ?, started_at = ?, attempt_count = attempt_count + 1,
|
|
80
|
+
max_retry = ?, timeout_at = CASE WHEN timeout_at = 0 THEN ? ELSE timeout_at END,
|
|
81
|
+
owner_id = ?, lease_expires_at = ?
|
|
82
|
+
WHERE current.submission_id = ? AND current.status = 'queued'
|
|
83
|
+
AND current.canonical_ready_at IS NOT NULL
|
|
84
|
+
AND NOT EXISTS (
|
|
85
|
+
SELECT 1 FROM flue_agent_submissions AS earlier
|
|
86
|
+
WHERE earlier.session_key = current.session_key
|
|
87
|
+
AND earlier.status IN ('queued', 'running', 'terminalizing')
|
|
88
|
+
AND earlier.sequence < current.sequence
|
|
89
|
+
) RETURNING ${columns}`, [claim.attemptId, now, DURABILITY_DEFAULT_MAX_ATTEMPTS,
|
|
90
|
+
now + DURABILITY_DEFAULT_TIMEOUT_MS, claim.ownerId, claim.leaseExpiresAt, claim.submissionId]);
|
|
91
|
+
return rows[0] ? parseSubmission(rows[0]) : null;
|
|
92
|
+
}
|
|
93
|
+
async markSubmissionInputApplied(attempt, durability) {
|
|
94
|
+
const now = Date.now();
|
|
95
|
+
return (await this.db.query(`UPDATE flue_agent_submissions
|
|
96
|
+
SET input_applied_at = COALESCE(input_applied_at, ?),
|
|
97
|
+
max_retry = CASE WHEN input_applied_at IS NULL THEN ? ELSE max_retry END,
|
|
98
|
+
timeout_at = CASE WHEN input_applied_at IS NULL THEN ? ELSE timeout_at END
|
|
99
|
+
WHERE submission_id = ? AND status = 'running' AND attempt_id = ? RETURNING submission_id`, [now, durability?.maxRetry ?? DURABILITY_DEFAULT_MAX_ATTEMPTS,
|
|
100
|
+
durability?.timeoutAt ?? now + DURABILITY_DEFAULT_TIMEOUT_MS,
|
|
101
|
+
attempt.submissionId, attempt.attemptId])).length > 0;
|
|
102
|
+
}
|
|
103
|
+
async requestSubmissionRecovery(attempt) {
|
|
104
|
+
return (await this.db.query(`UPDATE flue_agent_submissions SET recovery_requested_at = COALESCE(recovery_requested_at, ?)
|
|
105
|
+
WHERE submission_id = ? AND status = 'running' AND attempt_id = ? RETURNING submission_id`, [Date.now(), attempt.submissionId, attempt.attemptId])).length > 0;
|
|
106
|
+
}
|
|
107
|
+
async requestSessionAbort(sessionKey) {
|
|
108
|
+
const rows = await this.db.query(`UPDATE flue_agent_submissions SET abort_requested_at = COALESCE(abort_requested_at, ?)
|
|
109
|
+
WHERE session_key = ? AND status IN ('queued', 'running') RETURNING submission_id`, [Date.now(), sessionKey]);
|
|
110
|
+
return rows.map((row) => String(row.submission_id));
|
|
111
|
+
}
|
|
112
|
+
async requeueSubmissionBeforeInputApplied(attempt) {
|
|
113
|
+
return (await this.db.query(`UPDATE flue_agent_submissions
|
|
114
|
+
SET status = 'queued', attempt_id = NULL, recovery_requested_at = NULL,
|
|
115
|
+
started_at = NULL, owner_id = NULL, lease_expires_at = 0
|
|
116
|
+
WHERE submission_id = ? AND status = 'running' AND attempt_id = ?
|
|
117
|
+
AND input_applied_at IS NULL RETURNING submission_id`, [attempt.submissionId, attempt.attemptId])).length > 0;
|
|
118
|
+
}
|
|
119
|
+
async reserveSubmissionSettlement(attempt, settlement) {
|
|
120
|
+
if (settlement.record.id !== settlement.recordId)
|
|
121
|
+
return null;
|
|
122
|
+
const data = JSON.stringify(settlement.record);
|
|
123
|
+
let rows = await this.db.query(`UPDATE flue_agent_submissions
|
|
124
|
+
SET status = 'terminalizing', settlement_record_id = ?, settlement_record = ?
|
|
125
|
+
WHERE submission_id = ? AND kind = 'direct' AND status = 'running'
|
|
126
|
+
AND attempt_id = ? AND owner_id IS NOT NULL AND settlement_record_id IS NULL
|
|
127
|
+
RETURNING submission_id, session_key, attempt_id, settlement_record_id, settlement_record`, [settlement.recordId, data, attempt.submissionId, attempt.attemptId]);
|
|
128
|
+
if (!rows[0])
|
|
129
|
+
rows = await this.db.query(`SELECT submission_id, session_key, attempt_id, settlement_record_id, settlement_record
|
|
130
|
+
FROM flue_agent_submissions WHERE submission_id = ? AND status = 'terminalizing' AND attempt_id = ?`, [attempt.submissionId, attempt.attemptId]);
|
|
131
|
+
const row = rows[0];
|
|
132
|
+
if (!row || row.settlement_record_id !== settlement.recordId || row.settlement_record !== data)
|
|
133
|
+
return null;
|
|
134
|
+
return parseSettlement(row);
|
|
135
|
+
}
|
|
136
|
+
async finalizeSubmissionSettlement(attempt, recordId) {
|
|
137
|
+
return (await this.db.query(`UPDATE flue_agent_submissions SET status = 'settled', settled_at = ?
|
|
138
|
+
WHERE submission_id = ? AND status = 'terminalizing' AND attempt_id = ?
|
|
139
|
+
AND settlement_record_id = ? RETURNING submission_id`, [Date.now(), attempt.submissionId, attempt.attemptId, recordId])).length > 0;
|
|
140
|
+
}
|
|
141
|
+
completeSubmission(attempt) {
|
|
142
|
+
return this.settle(attempt, null);
|
|
143
|
+
}
|
|
144
|
+
failSubmission(attempt, error) {
|
|
145
|
+
return this.settle(attempt, error instanceof Error ? error.message : String(error));
|
|
146
|
+
}
|
|
147
|
+
async insertAttemptMarker(attempt) {
|
|
148
|
+
await this.db.query(`INSERT OR IGNORE INTO flue_agent_attempt_markers (submission_id, attempt_id, created_at) VALUES (?, ?, ?)`, [attempt.submissionId, attempt.attemptId, Date.now()]);
|
|
149
|
+
}
|
|
150
|
+
async deleteAttemptMarker(attempt) {
|
|
151
|
+
await this.db.query(`DELETE FROM flue_agent_attempt_markers WHERE submission_id = ? AND attempt_id = ?`, [attempt.submissionId, attempt.attemptId]);
|
|
152
|
+
}
|
|
153
|
+
async listAttemptMarkers() {
|
|
154
|
+
return (await this.db.query(`SELECT submission_id, attempt_id, created_at FROM flue_agent_attempt_markers`)).map((row) => ({
|
|
155
|
+
submissionId: String(row.submission_id),
|
|
156
|
+
attemptId: String(row.attempt_id),
|
|
157
|
+
createdAt: Number(row.created_at),
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
160
|
+
async renewLeases(ownerId, submissionIds) {
|
|
161
|
+
if (submissionIds.length === 0)
|
|
162
|
+
return;
|
|
163
|
+
await this.db.query(`UPDATE flue_agent_submissions SET lease_expires_at = ?
|
|
164
|
+
WHERE owner_id = ? AND status = 'running' AND submission_id IN (${submissionIds.map(() => '?').join(', ')})`, [Date.now() + LEASE_DURATION_MS, ownerId, ...submissionIds]);
|
|
165
|
+
}
|
|
166
|
+
listExpiredSubmissions() {
|
|
167
|
+
return this.readOperational(`SELECT ${columns} FROM flue_agent_submissions
|
|
168
|
+
WHERE status = 'running' AND lease_expires_at > 0 AND lease_expires_at < ? ORDER BY sequence ASC`, [Date.now()], 'active');
|
|
169
|
+
}
|
|
170
|
+
async admit(input) {
|
|
171
|
+
const payload = JSON.stringify(input);
|
|
172
|
+
const acceptedAt = Date.parse(input.acceptedAt);
|
|
173
|
+
if (!Number.isFinite(acceptedAt))
|
|
174
|
+
throw new Error('[flue] Submission acceptedAt is invalid.');
|
|
175
|
+
const sessionKey = createSessionStorageKey(input.id, SUBMISSION_HARNESS_NAME, SUBMISSION_SESSION_NAME);
|
|
176
|
+
return this.db.transaction(async (tx) => {
|
|
177
|
+
if (input.kind === 'dispatch') {
|
|
178
|
+
const receipts = await tx.query(`SELECT dispatch_id, accepted_at FROM flue_agent_dispatch_receipts WHERE dispatch_id = ? LIMIT 1`, [input.submissionId]);
|
|
179
|
+
if (receipts[0])
|
|
180
|
+
return {
|
|
181
|
+
kind: 'retained_receipt',
|
|
182
|
+
receipt: { submissionId: String(receipts[0].dispatch_id), acceptedAt: Number(receipts[0].accepted_at) },
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
await tx.query(`INSERT OR IGNORE INTO flue_agent_submissions
|
|
186
|
+
(submission_id, session_key, kind, payload, status, accepted_at)
|
|
187
|
+
VALUES (?, ?, ?, ?, 'queued', ?)`, [input.submissionId, sessionKey, input.kind, payload, acceptedAt]);
|
|
188
|
+
const rows = await tx.query(`SELECT ${columns} FROM flue_agent_submissions WHERE submission_id = ? LIMIT 1`, [input.submissionId]);
|
|
189
|
+
const row = rows[0];
|
|
190
|
+
if (!row)
|
|
191
|
+
throw new Error('[flue] Submission admission did not create a row.');
|
|
192
|
+
if (row.kind !== input.kind || row.payload !== payload)
|
|
193
|
+
return { kind: 'conflict' };
|
|
194
|
+
return { kind: 'submission', submission: parseSubmission(row) };
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
async settle(attempt, error) {
|
|
198
|
+
return (await this.db.query(`UPDATE flue_agent_submissions SET status = 'settled', settled_at = ?, error = ?
|
|
199
|
+
WHERE submission_id = ? AND status = 'running' AND attempt_id = ? RETURNING submission_id`, [Date.now(), error, attempt.submissionId, attempt.attemptId])).length > 0;
|
|
200
|
+
}
|
|
201
|
+
async readOperational(text, params, status) {
|
|
202
|
+
return this.db.transaction(async (tx) => {
|
|
203
|
+
const rows = await tx.query(text, params);
|
|
204
|
+
const output = [];
|
|
205
|
+
for (const row of rows) {
|
|
206
|
+
try {
|
|
207
|
+
output.push(parseSubmission(row));
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
await failMalformed(tx, Number(row.sequence), status, error);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return output;
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function parseSubmission(row) {
|
|
218
|
+
const input = JSON.parse(String(row.payload));
|
|
219
|
+
const status = String(row.status);
|
|
220
|
+
if (!['queued', 'running', 'terminalizing', 'settled'].includes(status)) {
|
|
221
|
+
throw new Error('[flue] Persisted submission status is invalid.');
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
sequence: Number(row.sequence),
|
|
225
|
+
submissionId: String(row.submission_id),
|
|
226
|
+
sessionKey: String(row.session_key),
|
|
227
|
+
kind: String(row.kind),
|
|
228
|
+
input,
|
|
229
|
+
status,
|
|
230
|
+
acceptedAt: Number(row.accepted_at),
|
|
231
|
+
canonicalReadyAt: row.canonical_ready_at == null ? null : Number(row.canonical_ready_at),
|
|
232
|
+
...(row.attempt_id == null ? {} : { attemptId: String(row.attempt_id) }),
|
|
233
|
+
...(row.input_applied_at == null ? {} : { inputAppliedAt: Number(row.input_applied_at) }),
|
|
234
|
+
...(row.recovery_requested_at == null ? {} : { recoveryRequestedAt: Number(row.recovery_requested_at) }),
|
|
235
|
+
...(row.abort_requested_at == null ? {} : { abortRequestedAt: Number(row.abort_requested_at) }),
|
|
236
|
+
...(row.started_at == null ? {} : { startedAt: Number(row.started_at) }),
|
|
237
|
+
...(row.error == null ? {} : { error: String(row.error) }),
|
|
238
|
+
attemptCount: Number(row.attempt_count),
|
|
239
|
+
maxRetry: Number(row.max_retry),
|
|
240
|
+
timeoutAt: Number(row.timeout_at),
|
|
241
|
+
...(row.owner_id == null ? {} : { ownerId: String(row.owner_id) }),
|
|
242
|
+
leaseExpiresAt: Number(row.lease_expires_at),
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
function parseSettlement(row) {
|
|
246
|
+
return {
|
|
247
|
+
submissionId: String(row.submission_id),
|
|
248
|
+
sessionKey: String(row.session_key),
|
|
249
|
+
attemptId: String(row.attempt_id),
|
|
250
|
+
recordId: String(row.settlement_record_id),
|
|
251
|
+
record: JSON.parse(String(row.settlement_record)),
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
async function failMalformed(runner, sequence, status, error) {
|
|
255
|
+
if (!Number.isFinite(sequence))
|
|
256
|
+
throw error;
|
|
257
|
+
await runner.query(`UPDATE flue_agent_submissions SET status = 'settled', settled_at = ?, error = ?
|
|
258
|
+
WHERE sequence = ? AND status = ?`, [Date.now(), error instanceof Error ? error.message : String(error), sequence,
|
|
259
|
+
status === 'queued' ? 'queued' : 'running']);
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=submission-store.js.map
|