@sixb/sqlite 0.0.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/LICENSE +21 -0
- package/README.md +57 -0
- package/dist/action-run-storage.d.ts +29 -0
- package/dist/action-run-storage.d.ts.map +1 -0
- package/dist/agents/agent-storage.d.ts +25 -0
- package/dist/agents/agent-storage.d.ts.map +1 -0
- package/dist/agents/index.d.ts +6 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/messages.d.ts +14 -0
- package/dist/agents/messages.d.ts.map +1 -0
- package/dist/agents/rows.d.ts +77 -0
- package/dist/agents/rows.d.ts.map +1 -0
- package/dist/agents/runs.d.ts +26 -0
- package/dist/agents/runs.d.ts.map +1 -0
- package/dist/agents/threads.d.ts +14 -0
- package/dist/agents/threads.d.ts.map +1 -0
- package/dist/auth-storage/access-tokens.d.ts +33 -0
- package/dist/auth-storage/access-tokens.d.ts.map +1 -0
- package/dist/auth-storage/auth-storage.d.ts +46 -0
- package/dist/auth-storage/auth-storage.d.ts.map +1 -0
- package/dist/auth-storage/group-memberships.d.ts +21 -0
- package/dist/auth-storage/group-memberships.d.ts.map +1 -0
- package/dist/auth-storage/identities.d.ts +17 -0
- package/dist/auth-storage/identities.d.ts.map +1 -0
- package/dist/auth-storage/index.d.ts +3 -0
- package/dist/auth-storage/index.d.ts.map +1 -0
- package/dist/auth-storage/invitations.d.ts +28 -0
- package/dist/auth-storage/invitations.d.ts.map +1 -0
- package/dist/auth-storage/magic-links.d.ts +28 -0
- package/dist/auth-storage/magic-links.d.ts.map +1 -0
- package/dist/auth-storage/oidc-attempts.d.ts +18 -0
- package/dist/auth-storage/oidc-attempts.d.ts.map +1 -0
- package/dist/auth-storage/rows.d.ts +134 -0
- package/dist/auth-storage/rows.d.ts.map +1 -0
- package/dist/auth-storage/service-account-group-memberships.d.ts +17 -0
- package/dist/auth-storage/service-account-group-memberships.d.ts.map +1 -0
- package/dist/auth-storage/service-accounts.d.ts +14 -0
- package/dist/auth-storage/service-accounts.d.ts.map +1 -0
- package/dist/auth-storage/sessions.d.ts +55 -0
- package/dist/auth-storage/sessions.d.ts.map +1 -0
- package/dist/auth-storage/shared.d.ts +131 -0
- package/dist/auth-storage/shared.d.ts.map +1 -0
- package/dist/auth-storage/users.d.ts +19 -0
- package/dist/auth-storage/users.d.ts.map +1 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10204 -0
- package/dist/index.js.map +54 -0
- package/dist/latest-run-query.d.ts +22 -0
- package/dist/latest-run-query.d.ts.map +1 -0
- package/dist/migrations.d.ts +18 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/object-query-compiler.d.ts +44 -0
- package/dist/object-query-compiler.d.ts.map +1 -0
- package/dist/object-storage.d.ts +93 -0
- package/dist/object-storage.d.ts.map +1 -0
- package/dist/ontology-storage/commits.d.ts +14 -0
- package/dist/ontology-storage/commits.d.ts.map +1 -0
- package/dist/ontology-storage/index.d.ts +22 -0
- package/dist/ontology-storage/index.d.ts.map +1 -0
- package/dist/ontology-storage/materialization-session.d.ts +49 -0
- package/dist/ontology-storage/materialization-session.d.ts.map +1 -0
- package/dist/ontology-storage/materialization-state.d.ts +63 -0
- package/dist/ontology-storage/materialization-state.d.ts.map +1 -0
- package/dist/ontology-storage/materialization-writer.d.ts +15 -0
- package/dist/ontology-storage/materialization-writer.d.ts.map +1 -0
- package/dist/ontology-storage/materializations.d.ts +32 -0
- package/dist/ontology-storage/materializations.d.ts.map +1 -0
- package/dist/ontology-storage/outbox.d.ts +14 -0
- package/dist/ontology-storage/outbox.d.ts.map +1 -0
- package/dist/ontology-storage/shared.d.ts +91 -0
- package/dist/ontology-storage/shared.d.ts.map +1 -0
- package/dist/ontology-storage/sources.d.ts +26 -0
- package/dist/ontology-storage/sources.d.ts.map +1 -0
- package/dist/pipeline-run-storage.d.ts +26 -0
- package/dist/pipeline-run-storage.d.ts.map +1 -0
- package/dist/projection-run-storage.d.ts +32 -0
- package/dist/projection-run-storage.d.ts.map +1 -0
- package/dist/rules-storage.d.ts +33 -0
- package/dist/rules-storage.d.ts.map +1 -0
- package/dist/run-list-query.d.ts +27 -0
- package/dist/run-list-query.d.ts.map +1 -0
- package/dist/storage-errors.d.ts +2 -0
- package/dist/storage-errors.d.ts.map +1 -0
- package/dist/sync-run-storage.d.ts +23 -0
- package/dist/sync-run-storage.d.ts.map +1 -0
- package/dist/timeseries-storage.d.ts +41 -0
- package/dist/timeseries-storage.d.ts.map +1 -0
- package/dist/transactions.d.ts +15 -0
- package/dist/transactions.d.ts.map +1 -0
- package/dist/tsconfig.json +5 -0
- package/dist/validation.d.ts +5 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/webhook-delivery-storage.d.ts +27 -0
- package/dist/webhook-delivery-storage.d.ts.map +1 -0
- package/dist/webhook-run-storage.d.ts +22 -0
- package/dist/webhook-run-storage.d.ts.map +1 -0
- package/dist/workflow-intervention-storage.d.ts +26 -0
- package/dist/workflow-intervention-storage.d.ts.map +1 -0
- package/dist/workflow-run-storage.d.ts +63 -0
- package/dist/workflow-run-storage.d.ts.map +1 -0
- package/package.json +58 -0
- package/src/action-run-storage.ts +761 -0
- package/src/agents/agent-storage.ts +46 -0
- package/src/agents/index.ts +5 -0
- package/src/agents/messages.ts +162 -0
- package/src/agents/rows.ts +205 -0
- package/src/agents/runs.ts +389 -0
- package/src/agents/threads.ts +133 -0
- package/src/auth-storage/access-tokens.ts +289 -0
- package/src/auth-storage/auth-storage.ts +784 -0
- package/src/auth-storage/group-memberships.ts +52 -0
- package/src/auth-storage/identities.ts +98 -0
- package/src/auth-storage/index.ts +2 -0
- package/src/auth-storage/invitations.ts +258 -0
- package/src/auth-storage/magic-links.ts +149 -0
- package/src/auth-storage/oidc-attempts.ts +109 -0
- package/src/auth-storage/rows.ts +338 -0
- package/src/auth-storage/service-account-group-memberships.ts +161 -0
- package/src/auth-storage/service-accounts.ts +168 -0
- package/src/auth-storage/sessions.ts +230 -0
- package/src/auth-storage/shared.ts +707 -0
- package/src/auth-storage/users.ts +226 -0
- package/src/index.ts +292 -0
- package/src/latest-run-query.ts +49 -0
- package/src/migrations/001-initial-schema.sql +1068 -0
- package/src/migrations.ts +245 -0
- package/src/object-query-compiler.ts +1198 -0
- package/src/object-storage.ts +605 -0
- package/src/ontology-storage/commits.ts +127 -0
- package/src/ontology-storage/index.ts +35 -0
- package/src/ontology-storage/materialization-session.ts +393 -0
- package/src/ontology-storage/materialization-state.ts +901 -0
- package/src/ontology-storage/materialization-writer.ts +394 -0
- package/src/ontology-storage/materializations.ts +838 -0
- package/src/ontology-storage/outbox.ts +237 -0
- package/src/ontology-storage/shared.ts +269 -0
- package/src/ontology-storage/sources.ts +653 -0
- package/src/pipeline-run-storage.ts +506 -0
- package/src/projection-run-storage.ts +592 -0
- package/src/rules-storage.ts +375 -0
- package/src/run-list-query.ts +98 -0
- package/src/sql.d.ts +4 -0
- package/src/storage-errors.ts +3 -0
- package/src/sync-run-storage.ts +299 -0
- package/src/timeseries-storage.ts +212 -0
- package/src/transactions.ts +96 -0
- package/src/validation.ts +30 -0
- package/src/webhook-delivery-storage.ts +272 -0
- package/src/webhook-run-storage.ts +240 -0
- package/src/workflow-intervention-storage.ts +398 -0
- package/src/workflow-run-storage.ts +1148 -0
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite"
|
|
2
|
+
import type { DatasetVersionRef } from "@sixb/core/lake-storage"
|
|
3
|
+
import type {
|
|
4
|
+
FinishPipelineRunInput,
|
|
5
|
+
FinishPipelineStepRunInput,
|
|
6
|
+
ListLatestPipelineRunsInput,
|
|
7
|
+
ListLatestPipelineRunsResult,
|
|
8
|
+
ListPipelineRunsInput,
|
|
9
|
+
ListPipelineRunsResult,
|
|
10
|
+
ListPipelineStepRunsInput,
|
|
11
|
+
ListPipelineStepRunsResult,
|
|
12
|
+
PipelineRunFailure,
|
|
13
|
+
PipelineRunRecord,
|
|
14
|
+
PipelineRunStorage,
|
|
15
|
+
PipelineStepRunRecord,
|
|
16
|
+
StartPipelineRunInput,
|
|
17
|
+
StartPipelineStepRunInput,
|
|
18
|
+
} from "@sixb/core/storage"
|
|
19
|
+
import { PipelineRunError } from "@sixb/core/storage"
|
|
20
|
+
import { queryLatestRunsByOwnerId } from "./latest-run-query"
|
|
21
|
+
import { installFreshSqliteSchema } from "./migrations"
|
|
22
|
+
import {
|
|
23
|
+
appendRunListFilters,
|
|
24
|
+
hasEmptyStatuses,
|
|
25
|
+
queryRunList,
|
|
26
|
+
type SqliteValue,
|
|
27
|
+
} from "./run-list-query"
|
|
28
|
+
import { isUniqueConstraintError } from "./storage-errors"
|
|
29
|
+
import {
|
|
30
|
+
closeSqliteStoreConnection,
|
|
31
|
+
openSqliteStoreConnection,
|
|
32
|
+
type SqliteStoreConnection,
|
|
33
|
+
} from "./transactions"
|
|
34
|
+
|
|
35
|
+
export interface SqlitePipelineRunStorageOptions {
|
|
36
|
+
/** Path to SQLite database file. Defaults to ':memory:' for in-memory database. */
|
|
37
|
+
path?: string
|
|
38
|
+
/** Internal shared connection used by bundled SqliteStorage. */
|
|
39
|
+
connection?: SqliteStoreConnection
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class SqlitePipelineRunStorage implements PipelineRunStorage {
|
|
43
|
+
private readonly connection: SqliteStoreConnection
|
|
44
|
+
private readonly db: Database
|
|
45
|
+
|
|
46
|
+
constructor(options: SqlitePipelineRunStorageOptions = {}) {
|
|
47
|
+
this.connection = openSqliteStoreConnection(options)
|
|
48
|
+
this.db = this.connection.db
|
|
49
|
+
|
|
50
|
+
if (this.connection.installFreshSchema) {
|
|
51
|
+
installFreshSqliteSchema(this.db)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async start(input: StartPipelineRunInput): Promise<PipelineRunRecord> {
|
|
56
|
+
const startedAt = input.startedAt ?? new Date()
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
this.db
|
|
60
|
+
.query(
|
|
61
|
+
`
|
|
62
|
+
INSERT INTO pipeline_runs (
|
|
63
|
+
project_id,
|
|
64
|
+
id,
|
|
65
|
+
pipeline_id,
|
|
66
|
+
status,
|
|
67
|
+
started_at
|
|
68
|
+
) VALUES (?, ?, ?, ?, ?)
|
|
69
|
+
`
|
|
70
|
+
)
|
|
71
|
+
.run(input.projectId, input.id, input.pipelineId, "running", startedAt.toISOString())
|
|
72
|
+
} catch (error) {
|
|
73
|
+
if (isUniqueConstraintError(error)) {
|
|
74
|
+
throw new PipelineRunError(
|
|
75
|
+
`[SixbSqlite] Pipeline run '${input.id}' already exists for project '${input.projectId}'.`
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
throw error
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const record = await this.getById({ projectId: input.projectId, id: input.id })
|
|
83
|
+
if (!record) {
|
|
84
|
+
throw new PipelineRunError(
|
|
85
|
+
`[SixbSqlite] Failed to load pipeline run '${input.id}' for project '${input.projectId}'.`
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return record
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async finish(input: FinishPipelineRunInput): Promise<PipelineRunRecord> {
|
|
93
|
+
return this.db.transaction(() => {
|
|
94
|
+
const existing = this.db
|
|
95
|
+
.query("SELECT * FROM pipeline_runs WHERE project_id = ? AND id = ?")
|
|
96
|
+
.get(input.projectId, input.id) as PipelineRunDatabaseRow | null
|
|
97
|
+
|
|
98
|
+
if (!existing) {
|
|
99
|
+
throw new PipelineRunError(
|
|
100
|
+
`[SixbSqlite] Pipeline run '${input.id}' not found for project '${input.projectId}'.`
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (existing.status !== "running") {
|
|
105
|
+
throw new PipelineRunError(
|
|
106
|
+
`[SixbSqlite] Pipeline run '${input.id}' for project '${input.projectId}' is already terminal.`
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
this.db
|
|
111
|
+
.query(
|
|
112
|
+
`
|
|
113
|
+
UPDATE pipeline_runs
|
|
114
|
+
SET
|
|
115
|
+
status = ?,
|
|
116
|
+
finished_at = ?,
|
|
117
|
+
output_dataset_id = ?,
|
|
118
|
+
output_version_id = ?,
|
|
119
|
+
error_name = ?,
|
|
120
|
+
error_message = ?
|
|
121
|
+
WHERE project_id = ? AND id = ?
|
|
122
|
+
`
|
|
123
|
+
)
|
|
124
|
+
.run(
|
|
125
|
+
input.status,
|
|
126
|
+
(input.finishedAt ?? new Date()).toISOString(),
|
|
127
|
+
input.status === "succeeded" ? (input.output?.datasetId ?? null) : null,
|
|
128
|
+
input.status === "succeeded" ? (input.output?.versionId ?? null) : null,
|
|
129
|
+
input.status === "succeeded" ? null : (input.error?.name ?? null),
|
|
130
|
+
input.status === "succeeded" ? null : (input.error?.message ?? null),
|
|
131
|
+
input.projectId,
|
|
132
|
+
input.id
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
const updated = this.db
|
|
136
|
+
.query("SELECT * FROM pipeline_runs WHERE project_id = ? AND id = ?")
|
|
137
|
+
.get(input.projectId, input.id) as PipelineRunDatabaseRow
|
|
138
|
+
|
|
139
|
+
return rowToPipelineRunRecord(updated)
|
|
140
|
+
})()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async startStep(input: StartPipelineStepRunInput): Promise<PipelineStepRunRecord> {
|
|
144
|
+
return this.db.transaction(() => {
|
|
145
|
+
const pipelineRun = this.db
|
|
146
|
+
.query("SELECT * FROM pipeline_runs WHERE project_id = ? AND id = ?")
|
|
147
|
+
.get(input.projectId, input.pipelineRunId) as PipelineRunDatabaseRow | null
|
|
148
|
+
|
|
149
|
+
if (!pipelineRun) {
|
|
150
|
+
throw new PipelineRunError(
|
|
151
|
+
`[SixbSqlite] Pipeline run '${input.pipelineRunId}' not found for project '${input.projectId}'.`
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (pipelineRun.status !== "running") {
|
|
156
|
+
throw new PipelineRunError(
|
|
157
|
+
`[SixbSqlite] Pipeline run '${input.pipelineRunId}' for project '${input.projectId}' is already terminal.`
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (pipelineRun.pipeline_id !== input.pipelineId) {
|
|
162
|
+
throw new PipelineRunError(
|
|
163
|
+
`[SixbSqlite] Pipeline step run '${input.id}' pipeline '${input.pipelineId}' does not match pipeline run '${input.pipelineRunId}' pipeline '${pipelineRun.pipeline_id}'.`
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const startedAt = input.startedAt ?? new Date()
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
this.db
|
|
171
|
+
.query(
|
|
172
|
+
`
|
|
173
|
+
INSERT INTO pipeline_step_runs (
|
|
174
|
+
project_id,
|
|
175
|
+
id,
|
|
176
|
+
pipeline_run_id,
|
|
177
|
+
pipeline_id,
|
|
178
|
+
step_id,
|
|
179
|
+
dataset_id,
|
|
180
|
+
mode,
|
|
181
|
+
status,
|
|
182
|
+
started_at,
|
|
183
|
+
inputs
|
|
184
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
185
|
+
`
|
|
186
|
+
)
|
|
187
|
+
.run(
|
|
188
|
+
input.projectId,
|
|
189
|
+
input.id,
|
|
190
|
+
input.pipelineRunId,
|
|
191
|
+
input.pipelineId,
|
|
192
|
+
input.stepId,
|
|
193
|
+
input.datasetId,
|
|
194
|
+
input.mode,
|
|
195
|
+
"running",
|
|
196
|
+
startedAt.toISOString(),
|
|
197
|
+
serializeDatasetVersionRefs(input.inputs)
|
|
198
|
+
)
|
|
199
|
+
} catch (error) {
|
|
200
|
+
if (isUniqueConstraintError(error)) {
|
|
201
|
+
throw new PipelineRunError(
|
|
202
|
+
`[SixbSqlite] Pipeline step run '${input.id}' already exists for project '${input.projectId}'.`
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
throw error
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const row = this.db
|
|
210
|
+
.query("SELECT * FROM pipeline_step_runs WHERE project_id = ? AND id = ?")
|
|
211
|
+
.get(input.projectId, input.id) as PipelineStepRunDatabaseRow | null
|
|
212
|
+
|
|
213
|
+
if (!row) {
|
|
214
|
+
throw new PipelineRunError(
|
|
215
|
+
`[SixbSqlite] Failed to load pipeline step run '${input.id}' for project '${input.projectId}'.`
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return rowToPipelineStepRunRecord(row)
|
|
220
|
+
})()
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async finishStep(input: FinishPipelineStepRunInput): Promise<PipelineStepRunRecord> {
|
|
224
|
+
assertOptionalNonNegativeInteger(input.rowsWritten, "rowsWritten")
|
|
225
|
+
|
|
226
|
+
return this.db.transaction(() => {
|
|
227
|
+
const existing = this.db
|
|
228
|
+
.query("SELECT * FROM pipeline_step_runs WHERE project_id = ? AND id = ?")
|
|
229
|
+
.get(input.projectId, input.id) as PipelineStepRunDatabaseRow | null
|
|
230
|
+
|
|
231
|
+
if (!existing) {
|
|
232
|
+
throw new PipelineRunError(
|
|
233
|
+
`[SixbSqlite] Pipeline step run '${input.id}' not found for project '${input.projectId}'.`
|
|
234
|
+
)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (existing.status !== "running") {
|
|
238
|
+
throw new PipelineRunError(
|
|
239
|
+
`[SixbSqlite] Pipeline step run '${input.id}' for project '${input.projectId}' is already terminal.`
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (input.status === "succeeded" && input.output.datasetId !== existing.dataset_id) {
|
|
244
|
+
throw new PipelineRunError(
|
|
245
|
+
`[SixbSqlite] Pipeline step run '${input.id}' output dataset '${input.output.datasetId}' does not match '${existing.dataset_id}'.`
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
this.db
|
|
250
|
+
.query(
|
|
251
|
+
`
|
|
252
|
+
UPDATE pipeline_step_runs
|
|
253
|
+
SET
|
|
254
|
+
status = ?,
|
|
255
|
+
finished_at = ?,
|
|
256
|
+
output_version_id = ?,
|
|
257
|
+
rows_written = ?,
|
|
258
|
+
error_name = ?,
|
|
259
|
+
error_message = ?
|
|
260
|
+
WHERE project_id = ? AND id = ?
|
|
261
|
+
`
|
|
262
|
+
)
|
|
263
|
+
.run(
|
|
264
|
+
input.status,
|
|
265
|
+
(input.finishedAt ?? new Date()).toISOString(),
|
|
266
|
+
input.status === "succeeded" ? input.output.versionId : null,
|
|
267
|
+
input.rowsWritten ?? existing.rows_written ?? null,
|
|
268
|
+
input.status === "succeeded" ? null : (input.error?.name ?? null),
|
|
269
|
+
input.status === "succeeded" ? null : (input.error?.message ?? null),
|
|
270
|
+
input.projectId,
|
|
271
|
+
input.id
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
const updated = this.db
|
|
275
|
+
.query("SELECT * FROM pipeline_step_runs WHERE project_id = ? AND id = ?")
|
|
276
|
+
.get(input.projectId, input.id) as PipelineStepRunDatabaseRow
|
|
277
|
+
|
|
278
|
+
return rowToPipelineStepRunRecord(updated)
|
|
279
|
+
})()
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async getById(params: { projectId: string; id: string }): Promise<PipelineRunRecord | null> {
|
|
283
|
+
const row = this.db
|
|
284
|
+
.query("SELECT * FROM pipeline_runs WHERE project_id = ? AND id = ?")
|
|
285
|
+
.get(params.projectId, params.id) as PipelineRunDatabaseRow | null
|
|
286
|
+
|
|
287
|
+
return row ? rowToPipelineRunRecord(row) : null
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
async list(input: ListPipelineRunsInput): Promise<ListPipelineRunsResult> {
|
|
291
|
+
if (hasEmptyStatuses(input) || input.pipelineIds?.length === 0) {
|
|
292
|
+
return {
|
|
293
|
+
runs: [],
|
|
294
|
+
hasMore: false,
|
|
295
|
+
total: 0,
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const whereClauses = ["project_id = ?"]
|
|
300
|
+
const args: SqliteValue[] = [input.projectId]
|
|
301
|
+
|
|
302
|
+
if (input.pipelineId) {
|
|
303
|
+
whereClauses.push("pipeline_id = ?")
|
|
304
|
+
args.push(input.pipelineId)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (input.pipelineIds) {
|
|
308
|
+
whereClauses.push(`pipeline_id IN (${input.pipelineIds.map(() => "?").join(", ")})`)
|
|
309
|
+
args.push(...input.pipelineIds)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
appendRunListFilters(whereClauses, args, input)
|
|
313
|
+
|
|
314
|
+
const { rows, total, hasMore } = queryRunList<PipelineRunDatabaseRow>({
|
|
315
|
+
db: this.db,
|
|
316
|
+
tableName: "pipeline_runs",
|
|
317
|
+
whereClauses,
|
|
318
|
+
args,
|
|
319
|
+
order: input.order,
|
|
320
|
+
limit: input.limit,
|
|
321
|
+
offset: input.offset,
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
return {
|
|
325
|
+
runs: rows.map(rowToPipelineRunRecord),
|
|
326
|
+
hasMore,
|
|
327
|
+
total,
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
async listLatestByPipelineIds(
|
|
332
|
+
input: ListLatestPipelineRunsInput
|
|
333
|
+
): Promise<ListLatestPipelineRunsResult> {
|
|
334
|
+
const rows = queryLatestRunsByOwnerId<PipelineRunDatabaseRow>({
|
|
335
|
+
db: this.db,
|
|
336
|
+
tableName: "pipeline_runs",
|
|
337
|
+
ownerColumn: "pipeline_id",
|
|
338
|
+
ownerIds: input.pipelineIds,
|
|
339
|
+
projectId: input.projectId,
|
|
340
|
+
ownerIdFor: (row) => row.pipeline_id,
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
return {
|
|
344
|
+
runs: rows.map(rowToPipelineRunRecord),
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
async listSteps(input: ListPipelineStepRunsInput): Promise<ListPipelineStepRunsResult> {
|
|
349
|
+
if (hasEmptyStatuses(input)) {
|
|
350
|
+
return {
|
|
351
|
+
steps: [],
|
|
352
|
+
hasMore: false,
|
|
353
|
+
total: 0,
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const whereClauses = ["project_id = ?"]
|
|
358
|
+
const args: SqliteValue[] = [input.projectId]
|
|
359
|
+
|
|
360
|
+
if (input.pipelineRunId) {
|
|
361
|
+
whereClauses.push("pipeline_run_id = ?")
|
|
362
|
+
args.push(input.pipelineRunId)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (input.pipelineId) {
|
|
366
|
+
whereClauses.push("pipeline_id = ?")
|
|
367
|
+
args.push(input.pipelineId)
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (input.stepId) {
|
|
371
|
+
whereClauses.push("step_id = ?")
|
|
372
|
+
args.push(input.stepId)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (input.datasetId) {
|
|
376
|
+
whereClauses.push("dataset_id = ?")
|
|
377
|
+
args.push(input.datasetId)
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
appendRunListFilters(whereClauses, args, input)
|
|
381
|
+
|
|
382
|
+
const { rows, total, hasMore } = queryRunList<PipelineStepRunDatabaseRow>({
|
|
383
|
+
db: this.db,
|
|
384
|
+
tableName: "pipeline_step_runs",
|
|
385
|
+
whereClauses,
|
|
386
|
+
args,
|
|
387
|
+
order: input.order,
|
|
388
|
+
limit: input.limit,
|
|
389
|
+
offset: input.offset,
|
|
390
|
+
})
|
|
391
|
+
|
|
392
|
+
return {
|
|
393
|
+
steps: rows.map(rowToPipelineStepRunRecord),
|
|
394
|
+
hasMore,
|
|
395
|
+
total,
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
close(): void {
|
|
400
|
+
closeSqliteStoreConnection(this.connection)
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function serializeDatasetVersionRefs(refs: readonly DatasetVersionRef[]): string {
|
|
405
|
+
return JSON.stringify(refs)
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function parseDatasetVersionRefs(value: string): readonly DatasetVersionRef[] {
|
|
409
|
+
return JSON.parse(value) as readonly DatasetVersionRef[]
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function toFailure(row: {
|
|
413
|
+
readonly error_name: string | null
|
|
414
|
+
readonly error_message: string | null
|
|
415
|
+
}): PipelineRunFailure | undefined {
|
|
416
|
+
if (!row.error_message) {
|
|
417
|
+
return undefined
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return {
|
|
421
|
+
name: row.error_name ?? undefined,
|
|
422
|
+
message: row.error_message,
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
function rowToPipelineRunRecord(row: PipelineRunDatabaseRow): PipelineRunRecord {
|
|
427
|
+
return {
|
|
428
|
+
id: row.id,
|
|
429
|
+
projectId: row.project_id,
|
|
430
|
+
pipelineId: row.pipeline_id,
|
|
431
|
+
status: row.status,
|
|
432
|
+
startedAt: new Date(row.started_at),
|
|
433
|
+
finishedAt: row.finished_at ? new Date(row.finished_at) : undefined,
|
|
434
|
+
output:
|
|
435
|
+
row.output_dataset_id && row.output_version_id
|
|
436
|
+
? {
|
|
437
|
+
datasetId: row.output_dataset_id,
|
|
438
|
+
versionId: row.output_version_id,
|
|
439
|
+
}
|
|
440
|
+
: undefined,
|
|
441
|
+
error: toFailure(row),
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function rowToPipelineStepRunRecord(row: PipelineStepRunDatabaseRow): PipelineStepRunRecord {
|
|
446
|
+
return {
|
|
447
|
+
id: row.id,
|
|
448
|
+
projectId: row.project_id,
|
|
449
|
+
pipelineRunId: row.pipeline_run_id,
|
|
450
|
+
pipelineId: row.pipeline_id,
|
|
451
|
+
stepId: row.step_id,
|
|
452
|
+
datasetId: row.dataset_id,
|
|
453
|
+
mode: row.mode,
|
|
454
|
+
status: row.status,
|
|
455
|
+
startedAt: new Date(row.started_at),
|
|
456
|
+
finishedAt: row.finished_at ? new Date(row.finished_at) : undefined,
|
|
457
|
+
inputs: parseDatasetVersionRefs(row.inputs),
|
|
458
|
+
output: row.output_version_id
|
|
459
|
+
? {
|
|
460
|
+
datasetId: row.dataset_id,
|
|
461
|
+
versionId: row.output_version_id,
|
|
462
|
+
}
|
|
463
|
+
: undefined,
|
|
464
|
+
rowsWritten: row.rows_written ?? undefined,
|
|
465
|
+
error: toFailure(row),
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function assertOptionalNonNegativeInteger(value: number | undefined, fieldName: string): void {
|
|
470
|
+
if (value !== undefined && (!Number.isInteger(value) || value < 0)) {
|
|
471
|
+
throw new PipelineRunError(
|
|
472
|
+
`[SixbSqlite] Pipeline run ${fieldName} must be a non-negative integer.`
|
|
473
|
+
)
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
interface PipelineRunDatabaseRow {
|
|
478
|
+
project_id: string
|
|
479
|
+
id: string
|
|
480
|
+
pipeline_id: string
|
|
481
|
+
status: PipelineRunRecord["status"]
|
|
482
|
+
started_at: string
|
|
483
|
+
finished_at: string | null
|
|
484
|
+
output_dataset_id: string | null
|
|
485
|
+
output_version_id: string | null
|
|
486
|
+
error_name: string | null
|
|
487
|
+
error_message: string | null
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
interface PipelineStepRunDatabaseRow {
|
|
491
|
+
project_id: string
|
|
492
|
+
id: string
|
|
493
|
+
pipeline_run_id: string
|
|
494
|
+
pipeline_id: string
|
|
495
|
+
step_id: string
|
|
496
|
+
dataset_id: string
|
|
497
|
+
mode: PipelineStepRunRecord["mode"]
|
|
498
|
+
status: PipelineStepRunRecord["status"]
|
|
499
|
+
started_at: string
|
|
500
|
+
finished_at: string | null
|
|
501
|
+
inputs: string
|
|
502
|
+
output_version_id: string | null
|
|
503
|
+
rows_written: number | null
|
|
504
|
+
error_name: string | null
|
|
505
|
+
error_message: string | null
|
|
506
|
+
}
|