@sixb/sqlite 0.1.1 → 0.1.3
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 +18 -13
- package/dist/action-run-storage.d.ts +5 -2
- package/dist/action-run-storage.d.ts.map +1 -1
- package/dist/agents/agent-storage.d.ts +9 -5
- package/dist/agents/agent-storage.d.ts.map +1 -1
- package/dist/agents/checkpoints.d.ts +14 -0
- package/dist/agents/checkpoints.d.ts.map +1 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/messages.d.ts +2 -1
- package/dist/agents/messages.d.ts.map +1 -1
- package/dist/agents/rows.d.ts +21 -11
- package/dist/agents/rows.d.ts.map +1 -1
- package/dist/agents/runs.d.ts +3 -2
- package/dist/agents/runs.d.ts.map +1 -1
- package/dist/ai-cost-storage.d.ts +15 -0
- package/dist/ai-cost-storage.d.ts.map +1 -0
- package/dist/ai-usage-storage.d.ts +22 -0
- package/dist/ai-usage-storage.d.ts.map +1 -0
- package/dist/auth-storage/service-accounts.d.ts.map +1 -1
- package/dist/auth-storage/shared.d.ts +1 -10
- package/dist/auth-storage/shared.d.ts.map +1 -1
- package/dist/connector-connection-storage.d.ts +9 -0
- package/dist/connector-connection-storage.d.ts.map +1 -0
- package/dist/execution-storage.d.ts +14 -0
- package/dist/execution-storage.d.ts.map +1 -0
- package/dist/index.d.ts +14 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4633 -1066
- package/dist/index.js.map +33 -28
- package/dist/latest-run-query.d.ts.map +1 -1
- package/dist/migrations.d.ts +0 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/ontology-storage/materialization-session.d.ts +50 -8
- package/dist/ontology-storage/materialization-session.d.ts.map +1 -1
- package/dist/ontology-storage/materialization-state.d.ts +4 -5
- package/dist/ontology-storage/materialization-state.d.ts.map +1 -1
- package/dist/ontology-storage/materialization-writer.d.ts.map +1 -1
- package/dist/ontology-storage/materializations.d.ts +0 -2
- package/dist/ontology-storage/materializations.d.ts.map +1 -1
- package/dist/ontology-storage/outbox.d.ts.map +1 -1
- package/dist/ontology-storage/shared.d.ts +3 -3
- package/dist/ontology-storage/shared.d.ts.map +1 -1
- package/dist/ontology-storage/sources.d.ts.map +1 -1
- package/dist/pipeline-run-storage.d.ts +7 -2
- package/dist/pipeline-run-storage.d.ts.map +1 -1
- package/dist/projection-run-storage.d.ts +9 -2
- package/dist/projection-run-storage.d.ts.map +1 -1
- package/dist/run-list-query.d.ts +1 -1
- package/dist/run-list-query.d.ts.map +1 -1
- package/dist/sync-run-storage.d.ts +7 -2
- package/dist/sync-run-storage.d.ts.map +1 -1
- package/dist/testing.d.ts +6 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/transactions.d.ts +3 -0
- package/dist/transactions.d.ts.map +1 -1
- package/dist/webhook-run-storage.d.ts +9 -2
- package/dist/webhook-run-storage.d.ts.map +1 -1
- package/dist/workflow-run-storage.d.ts +7 -3
- package/dist/workflow-run-storage.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/action-run-storage.ts +51 -74
- package/src/agents/agent-storage.ts +11 -6
- package/src/agents/checkpoints.ts +175 -0
- package/src/agents/index.ts +1 -0
- package/src/agents/messages.ts +59 -0
- package/src/agents/rows.ts +52 -40
- package/src/agents/runs.ts +27 -21
- package/src/ai-cost-storage.ts +744 -0
- package/src/ai-usage-storage.ts +324 -0
- package/src/auth-storage/service-accounts.ts +14 -21
- package/src/auth-storage/shared.ts +0 -22
- package/src/connector-connection-storage.ts +784 -0
- package/src/execution-storage.ts +158 -0
- package/src/index.ts +69 -22
- package/src/latest-run-query.ts +7 -1
- package/src/migrations/004-executions.sql +142 -0
- package/src/migrations/005-workflow-executions.sql +7 -0
- package/src/migrations/006-narrow-ontology-source-root-index.sql +4 -0
- package/src/migrations/007-split-overrides.sql +154 -0
- package/src/migrations/008-action-executions.sql +4 -0
- package/src/migrations/009-agent-executions.sql +115 -0
- package/src/migrations/010-ai-usage-accounting-foundation.sql +74 -0
- package/src/migrations/011-sync-failure-record.sql +22 -0
- package/src/migrations/012-pipeline-failure-record.sql +45 -0
- package/src/migrations/013-workflow-failure-record.sql +45 -0
- package/src/migrations/014-agent-failure-record.sql +59 -0
- package/src/migrations/015-projection-failure-record.sql +20 -0
- package/src/migrations/016-webhook-run-failure-record.sql +19 -0
- package/src/migrations/017-action-failure-record.sql +65 -0
- package/src/migrations/018-ontology-outbox-failure-record.sql +80 -0
- package/src/migrations/019-webhook-delivery-failure-record.sql +62 -0
- package/src/migrations/020-drop-run-usage-projections.sql +7 -0
- package/src/migrations/021-sync-pipeline-executions.sql +101 -0
- package/src/migrations/022-projection-executions.sql +244 -0
- package/src/migrations/023-webhook-executions.sql +51 -0
- package/src/migrations/024-ontology-commit-executions.sql +58 -0
- package/src/migrations/025-connector-connections.sql +257 -0
- package/src/migrations/026-ai-cost-accounting.sql +57 -0
- package/src/migrations/027-agent-context-checkpoints.sql +28 -0
- package/src/migrations/028-object-override-edit-times.sql +3 -0
- package/src/migrations.ts +129 -4
- package/src/ontology-storage/materialization-session.ts +317 -143
- package/src/ontology-storage/materialization-state.ts +323 -112
- package/src/ontology-storage/materialization-writer.ts +145 -67
- package/src/ontology-storage/materializations.ts +67 -141
- package/src/ontology-storage/outbox.ts +10 -3
- package/src/ontology-storage/shared.ts +10 -4
- package/src/ontology-storage/sources.ts +4 -1
- package/src/pipeline-run-storage.ts +128 -43
- package/src/projection-run-storage.ts +209 -97
- package/src/run-list-query.ts +9 -4
- package/src/sync-run-storage.ts +118 -32
- package/src/testing.ts +20 -0
- package/src/transactions.ts +10 -3
- package/src/webhook-run-storage.ts +118 -74
- package/src/workflow-run-storage.ts +117 -131
- package/dist/validation.d.ts +0 -5
- package/dist/validation.d.ts.map +0 -1
- package/dist/webhook-delivery-storage.d.ts +0 -27
- package/dist/webhook-delivery-storage.d.ts.map +0 -1
- package/src/validation.ts +0 -30
- package/src/webhook-delivery-storage.ts +0 -272
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite"
|
|
2
|
+
import {
|
|
3
|
+
type ExecutionStorageRow,
|
|
4
|
+
executionRecordFromStorageRow,
|
|
5
|
+
executionRecordToStorageRow,
|
|
6
|
+
normalizeExecutionRecord,
|
|
7
|
+
validateExecutionRecordReferences,
|
|
8
|
+
} from "@sixb/core/internal/execution-storage"
|
|
9
|
+
import type { CreateExecutionInput, ExecutionRecord, ExecutionStorage } from "@sixb/core/storage"
|
|
10
|
+
import { ExecutionStorageError } from "@sixb/core/storage"
|
|
11
|
+
import type { SqliteAuthStorage } from "./auth-storage"
|
|
12
|
+
|
|
13
|
+
export class SqliteExecutionStorage implements ExecutionStorage {
|
|
14
|
+
constructor(
|
|
15
|
+
private readonly db: Database,
|
|
16
|
+
private readonly auth: SqliteAuthStorage
|
|
17
|
+
) {}
|
|
18
|
+
|
|
19
|
+
async create(input: CreateExecutionInput): Promise<ExecutionRecord> {
|
|
20
|
+
const record = normalizeExecutionRecord(input)
|
|
21
|
+
await validateExecutionRecordReferences(record, {
|
|
22
|
+
auth: this.auth,
|
|
23
|
+
getExecution: (params) => this.getById(params),
|
|
24
|
+
})
|
|
25
|
+
const row = executionRecordToStorageRow(record)
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
this.db
|
|
29
|
+
.query(
|
|
30
|
+
`
|
|
31
|
+
INSERT INTO executions (
|
|
32
|
+
project_id,
|
|
33
|
+
id,
|
|
34
|
+
executor_kind,
|
|
35
|
+
executor_id,
|
|
36
|
+
source_kind,
|
|
37
|
+
source_id,
|
|
38
|
+
requested_by_user_id,
|
|
39
|
+
requested_by_service_account_id,
|
|
40
|
+
correlation_id,
|
|
41
|
+
parent_execution_id,
|
|
42
|
+
authority_kind,
|
|
43
|
+
authority_user_id,
|
|
44
|
+
authority_service_account_id,
|
|
45
|
+
authority_session_id,
|
|
46
|
+
authority_access_token_id,
|
|
47
|
+
authority_primitive_kind,
|
|
48
|
+
authority_primitive_id,
|
|
49
|
+
authority_kernel_operation,
|
|
50
|
+
created_at
|
|
51
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
52
|
+
`
|
|
53
|
+
)
|
|
54
|
+
.run(
|
|
55
|
+
row.projectId,
|
|
56
|
+
row.id,
|
|
57
|
+
row.executorKind,
|
|
58
|
+
row.executorId,
|
|
59
|
+
row.sourceKind,
|
|
60
|
+
row.sourceId,
|
|
61
|
+
row.requestedByUserId,
|
|
62
|
+
row.requestedByServiceAccountId,
|
|
63
|
+
row.correlationId,
|
|
64
|
+
row.parentExecutionId,
|
|
65
|
+
row.authorityKind,
|
|
66
|
+
row.authorityUserId,
|
|
67
|
+
row.authorityServiceAccountId,
|
|
68
|
+
row.authoritySessionId,
|
|
69
|
+
row.authorityAccessTokenId,
|
|
70
|
+
row.authorityPrimitiveKind,
|
|
71
|
+
row.authorityPrimitiveId,
|
|
72
|
+
row.authorityKernelOperation,
|
|
73
|
+
row.createdAt.toISOString()
|
|
74
|
+
)
|
|
75
|
+
} catch (error) {
|
|
76
|
+
if (isDuplicateExecutionError(error)) {
|
|
77
|
+
throw new ExecutionStorageError(
|
|
78
|
+
"duplicate_execution",
|
|
79
|
+
`[SixbSqlite] Execution '${record.id}' already exists in project '${record.projectId}'.`,
|
|
80
|
+
{ cause: error }
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
throw error
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return executionRecordFromStorageRow(row)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async getById(params: {
|
|
90
|
+
readonly projectId: string
|
|
91
|
+
readonly id: string
|
|
92
|
+
}): Promise<ExecutionRecord | null> {
|
|
93
|
+
const row = this.db
|
|
94
|
+
.query(
|
|
95
|
+
`
|
|
96
|
+
SELECT *
|
|
97
|
+
FROM executions
|
|
98
|
+
WHERE project_id = ? AND id = ?
|
|
99
|
+
`
|
|
100
|
+
)
|
|
101
|
+
.get(params.projectId, params.id) as SqliteExecutionRow | null
|
|
102
|
+
|
|
103
|
+
return row ? executionRecordFromStorageRow(toStorageRow(row)) : null
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function toStorageRow(row: SqliteExecutionRow): ExecutionStorageRow {
|
|
108
|
+
return {
|
|
109
|
+
projectId: row.project_id,
|
|
110
|
+
id: row.id,
|
|
111
|
+
executorKind: row.executor_kind,
|
|
112
|
+
executorId: row.executor_id,
|
|
113
|
+
sourceKind: row.source_kind,
|
|
114
|
+
sourceId: row.source_id,
|
|
115
|
+
requestedByUserId: row.requested_by_user_id,
|
|
116
|
+
requestedByServiceAccountId: row.requested_by_service_account_id,
|
|
117
|
+
correlationId: row.correlation_id,
|
|
118
|
+
parentExecutionId: row.parent_execution_id,
|
|
119
|
+
authorityKind: row.authority_kind,
|
|
120
|
+
authorityUserId: row.authority_user_id,
|
|
121
|
+
authorityServiceAccountId: row.authority_service_account_id,
|
|
122
|
+
authoritySessionId: row.authority_session_id,
|
|
123
|
+
authorityAccessTokenId: row.authority_access_token_id,
|
|
124
|
+
authorityPrimitiveKind: row.authority_primitive_kind,
|
|
125
|
+
authorityPrimitiveId: row.authority_primitive_id,
|
|
126
|
+
authorityKernelOperation: row.authority_kernel_operation,
|
|
127
|
+
createdAt: new Date(row.created_at),
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function isDuplicateExecutionError(error: unknown): boolean {
|
|
132
|
+
return (
|
|
133
|
+
error instanceof Error &&
|
|
134
|
+
error.message.includes("UNIQUE constraint failed: executions.project_id, executions.id")
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
interface SqliteExecutionRow {
|
|
139
|
+
readonly project_id: string
|
|
140
|
+
readonly id: string
|
|
141
|
+
readonly executor_kind: ExecutionStorageRow["executorKind"]
|
|
142
|
+
readonly executor_id: string
|
|
143
|
+
readonly source_kind: ExecutionStorageRow["sourceKind"]
|
|
144
|
+
readonly source_id: string
|
|
145
|
+
readonly requested_by_user_id: string | null
|
|
146
|
+
readonly requested_by_service_account_id: string | null
|
|
147
|
+
readonly correlation_id: string
|
|
148
|
+
readonly parent_execution_id: string | null
|
|
149
|
+
readonly authority_kind: ExecutionStorageRow["authorityKind"]
|
|
150
|
+
readonly authority_user_id: string | null
|
|
151
|
+
readonly authority_service_account_id: string | null
|
|
152
|
+
readonly authority_session_id: string | null
|
|
153
|
+
readonly authority_access_token_id: string | null
|
|
154
|
+
readonly authority_primitive_kind: ExecutionStorageRow["authorityPrimitiveKind"]
|
|
155
|
+
readonly authority_primitive_id: string | null
|
|
156
|
+
readonly authority_kernel_operation: ExecutionStorageRow["authorityKernelOperation"]
|
|
157
|
+
readonly created_at: string
|
|
158
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -19,13 +19,19 @@ import {
|
|
|
19
19
|
createWorkflowRunOperationScope,
|
|
20
20
|
} from "@sixb/core/internal/storage-operation-scope"
|
|
21
21
|
import {
|
|
22
|
+
type AiCostStorage,
|
|
23
|
+
type AiUsageStorage,
|
|
22
24
|
createTransactionStorageProxy,
|
|
23
25
|
StorageTransactionError,
|
|
24
26
|
throwNestedStorageTransaction,
|
|
25
27
|
} from "@sixb/core/storage"
|
|
26
28
|
import { SqliteActionRunStorage } from "./action-run-storage"
|
|
27
29
|
import { SqliteAgentStorage } from "./agents"
|
|
30
|
+
import { SqliteAiCostStorage } from "./ai-cost-storage"
|
|
31
|
+
import { SqliteAiUsageStorage } from "./ai-usage-storage"
|
|
28
32
|
import { SqliteAuthStorage } from "./auth-storage"
|
|
33
|
+
import { SqliteConnectorConnectionStorage } from "./connector-connection-storage"
|
|
34
|
+
import { SqliteExecutionStorage } from "./execution-storage"
|
|
29
35
|
import {
|
|
30
36
|
createSqliteStorageMigrators,
|
|
31
37
|
installFreshSqliteSchema,
|
|
@@ -37,6 +43,7 @@ import { SqlitePipelineRunStorage } from "./pipeline-run-storage"
|
|
|
37
43
|
import { SqliteProjectionRunStorage } from "./projection-run-storage"
|
|
38
44
|
import { SqliteRulesStorage } from "./rules-storage"
|
|
39
45
|
import { SqliteSyncRunStorage } from "./sync-run-storage"
|
|
46
|
+
import { registerSqliteStorageTestingAdapter } from "./testing"
|
|
40
47
|
import { SqliteTimeseriesStorage } from "./timeseries-storage"
|
|
41
48
|
import {
|
|
42
49
|
closeSqliteStoreConnection,
|
|
@@ -44,7 +51,6 @@ import {
|
|
|
44
51
|
runImmediateTransactionAsync,
|
|
45
52
|
type SqliteStoreConnection,
|
|
46
53
|
} from "./transactions"
|
|
47
|
-
import { SqliteWebhookDeliveryStorage } from "./webhook-delivery-storage"
|
|
48
54
|
import { SqliteWebhookRunStorage } from "./webhook-run-storage"
|
|
49
55
|
import { SqliteWorkflowInterventionStorage } from "./workflow-intervention-storage"
|
|
50
56
|
import { SqliteWorkflowRunStorage } from "./workflow-run-storage"
|
|
@@ -57,8 +63,8 @@ export interface SqliteStorageOptions {
|
|
|
57
63
|
/**
|
|
58
64
|
* SQLite storage provider for Sixb.
|
|
59
65
|
*
|
|
60
|
-
* Bundles object, timeseries, auth,
|
|
61
|
-
* run,
|
|
66
|
+
* Bundles object, timeseries, auth, execution, AI accounting, sync run, pipeline run, projection
|
|
67
|
+
* run, workflow run, webhook run, and connector connection storage backed by SQLite.
|
|
62
68
|
*
|
|
63
69
|
* Usage:
|
|
64
70
|
* ```ts
|
|
@@ -74,7 +80,10 @@ export class SqliteStorage implements MigrationCapableStorage {
|
|
|
74
80
|
readonly objects: Storage["objects"]
|
|
75
81
|
readonly ontology: SqliteOntologyStorage
|
|
76
82
|
readonly auth: SqliteAuthStorage
|
|
83
|
+
readonly executions: SqliteExecutionStorage
|
|
77
84
|
readonly agents: SqliteAgentStorage
|
|
85
|
+
readonly aiUsage: AiUsageStorage
|
|
86
|
+
readonly aiCosts: AiCostStorage
|
|
78
87
|
readonly actionRuns: SqliteActionRunStorage
|
|
79
88
|
readonly pipelineRuns: SqlitePipelineRunStorage
|
|
80
89
|
readonly syncRuns: SqliteSyncRunStorage
|
|
@@ -82,18 +91,25 @@ export class SqliteStorage implements MigrationCapableStorage {
|
|
|
82
91
|
readonly workflowRuns: SqliteWorkflowRunStorage
|
|
83
92
|
readonly workflowInterventions: SqliteWorkflowInterventionStorage
|
|
84
93
|
readonly timeseries: Storage["timeseries"]
|
|
85
|
-
readonly webhookDeliveries: SqliteWebhookDeliveryStorage
|
|
86
94
|
readonly webhookRuns: SqliteWebhookRunStorage
|
|
87
95
|
readonly rules: SqliteRulesStorage
|
|
96
|
+
readonly connectorConnections: SqliteConnectorConnectionStorage
|
|
88
97
|
readonly migrators: readonly StorageMigrator[]
|
|
89
98
|
|
|
90
99
|
private readonly connection: SqliteStoreConnection
|
|
100
|
+
private readonly readConnection: SqliteStoreConnection
|
|
91
101
|
private readonly transactionScope = new AsyncLocalStorage<{ active: boolean }>()
|
|
92
102
|
private transactionTail: Promise<void> = Promise.resolve()
|
|
93
103
|
|
|
94
104
|
constructor(options: SqliteStorageOptions = {}) {
|
|
95
105
|
const path = options.path ? sqliteStoragePath(options.path) : undefined
|
|
96
106
|
this.connection = openSqliteStoreConnection({ path })
|
|
107
|
+
if (path) {
|
|
108
|
+
this.connection.db.run("PRAGMA journal_mode = WAL")
|
|
109
|
+
this.readConnection = openSqliteStoreConnection({ path, readonly: true })
|
|
110
|
+
} else {
|
|
111
|
+
this.readConnection = this.connection
|
|
112
|
+
}
|
|
97
113
|
|
|
98
114
|
if (this.connection.installFreshSchema) {
|
|
99
115
|
installFreshSqliteSchema(this.connection.db)
|
|
@@ -112,35 +128,57 @@ export class SqliteStorage implements MigrationCapableStorage {
|
|
|
112
128
|
(run) => this.runRootOntologyOperation(run),
|
|
113
129
|
assertRootOperationAvailable
|
|
114
130
|
)
|
|
115
|
-
|
|
131
|
+
const readScope = path
|
|
132
|
+
? createStorageOperationScope(async (run) => {
|
|
133
|
+
this.assertRootOperationAvailable()
|
|
134
|
+
return run()
|
|
135
|
+
}, assertRootOperationAvailable)
|
|
136
|
+
: scope
|
|
137
|
+
const readObjects = path
|
|
138
|
+
? new SqliteObjectStorage({ connection: this.readConnection })
|
|
139
|
+
: stores.objects
|
|
140
|
+
const readTimeseries = path
|
|
141
|
+
? new SqliteTimeseriesStorage({ connection: this.readConnection })
|
|
142
|
+
: stores.timeseries
|
|
143
|
+
this.objects = createOperationScopedFacade(readObjects, readScope)
|
|
116
144
|
this.ontology = createOntologyOperationScope(stores.ontology, ontologyScope)
|
|
117
145
|
this.auth = createAuthOperationScope(stores.auth, scope)
|
|
146
|
+
this.executions = createOperationScopedFacade(stores.executions, scope)
|
|
118
147
|
this.agents = createAgentOperationScope(stores.agents, scope)
|
|
148
|
+
this.aiUsage = createOperationScopedFacade(stores.aiUsage, scope)
|
|
149
|
+
this.aiCosts = createOperationScopedFacade(stores.aiCosts, scope)
|
|
119
150
|
this.actionRuns = createOperationScopedFacade(stores.actionRuns, scope)
|
|
120
151
|
this.pipelineRuns = createOperationScopedFacade(stores.pipelineRuns, scope)
|
|
121
|
-
this.timeseries = createOperationScopedFacade(
|
|
152
|
+
this.timeseries = createOperationScopedFacade(readTimeseries, readScope)
|
|
122
153
|
this.syncRuns = createOperationScopedFacade(stores.syncRuns, scope)
|
|
123
154
|
this.projectionRuns = createOperationScopedFacade(stores.projectionRuns, scope)
|
|
124
155
|
this.workflowRuns = createWorkflowRunOperationScope(stores.workflowRuns, scope)
|
|
125
156
|
this.workflowInterventions = createOperationScopedFacade(stores.workflowInterventions, scope)
|
|
126
|
-
this.webhookDeliveries = createOperationScopedFacade(stores.webhookDeliveries, scope)
|
|
127
157
|
this.webhookRuns = createOperationScopedFacade(stores.webhookRuns, scope)
|
|
128
158
|
this.rules = createOperationScopedFacade(stores.rules, scope)
|
|
159
|
+
this.connectorConnections = createOperationScopedFacade(stores.connectorConnections, scope)
|
|
129
160
|
this.migrators = options.path ? createSqliteStorageMigrators(options.path) : []
|
|
161
|
+
registerSqliteStorageTestingAdapter(this, (durationMs) =>
|
|
162
|
+
stores.connectorConnections.advanceTimeForTesting(durationMs)
|
|
163
|
+
)
|
|
130
164
|
}
|
|
131
165
|
|
|
132
166
|
async ping(): Promise<void> {
|
|
167
|
+
this.assertRootOperationAvailable()
|
|
168
|
+
if (this.readConnection !== this.connection) {
|
|
169
|
+
this.readConnection.db.query("SELECT 1").get()
|
|
170
|
+
return
|
|
171
|
+
}
|
|
133
172
|
await this.runRootStorageOperation(() => {
|
|
134
173
|
this.connection.db.query("SELECT 1").get()
|
|
135
174
|
})
|
|
136
175
|
}
|
|
137
176
|
|
|
138
177
|
/**
|
|
139
|
-
* The `isolation` option is intentionally ignored. SQLite runs every transaction through
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
* `isolation: "serializable"` translates to a real isolation level.
|
|
178
|
+
* The `isolation` option is intentionally ignored. SQLite runs every write transaction through
|
|
179
|
+
* one connection serialized by {@link withTransactionLock} and a `BEGIN IMMEDIATE`, so there is no
|
|
180
|
+
* concurrent writer to isolate against. File-backed object and timeseries reads use a separate WAL
|
|
181
|
+
* snapshot connection; Postgres is where `isolation: "serializable"` maps to a real isolation level.
|
|
144
182
|
*/
|
|
145
183
|
async transaction<T>(
|
|
146
184
|
run: (tx: Storage) => Promise<T> | T,
|
|
@@ -183,6 +221,7 @@ export class SqliteStorage implements MigrationCapableStorage {
|
|
|
183
221
|
}
|
|
184
222
|
|
|
185
223
|
close(): void {
|
|
224
|
+
if (this.readConnection !== this.connection) closeSqliteStoreConnection(this.readConnection)
|
|
186
225
|
closeSqliteStoreConnection(this.connection)
|
|
187
226
|
}
|
|
188
227
|
|
|
@@ -250,6 +289,8 @@ function createSqliteStores(
|
|
|
250
289
|
readonly transactionContext: SqliteOntologyTransactionContext | null
|
|
251
290
|
}
|
|
252
291
|
): SqliteStoreSet {
|
|
292
|
+
const auth = new SqliteAuthStorage({ connection })
|
|
293
|
+
const executions = new SqliteExecutionStorage(connection.db, auth)
|
|
253
294
|
return {
|
|
254
295
|
objects: new SqliteObjectStorage({ connection }),
|
|
255
296
|
ontology: new SqliteOntologyStorage({
|
|
@@ -257,18 +298,21 @@ function createSqliteStores(
|
|
|
257
298
|
runRootOperation: options.runOntologyOperation,
|
|
258
299
|
transactionContext: options.transactionContext,
|
|
259
300
|
}),
|
|
260
|
-
auth
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
301
|
+
auth,
|
|
302
|
+
executions,
|
|
303
|
+
agents: new SqliteAgentStorage({ connection, executions }),
|
|
304
|
+
aiUsage: new SqliteAiUsageStorage({ connection }),
|
|
305
|
+
aiCosts: new SqliteAiCostStorage(connection),
|
|
306
|
+
actionRuns: new SqliteActionRunStorage({ connection, executions }),
|
|
307
|
+
pipelineRuns: new SqlitePipelineRunStorage({ connection, executions }),
|
|
264
308
|
timeseries: new SqliteTimeseriesStorage({ connection }),
|
|
265
|
-
syncRuns: new SqliteSyncRunStorage({ connection }),
|
|
266
|
-
projectionRuns: new SqliteProjectionRunStorage({ connection }),
|
|
267
|
-
workflowRuns: new SqliteWorkflowRunStorage({ connection }),
|
|
309
|
+
syncRuns: new SqliteSyncRunStorage({ connection, executions }),
|
|
310
|
+
projectionRuns: new SqliteProjectionRunStorage({ connection, executions }),
|
|
311
|
+
workflowRuns: new SqliteWorkflowRunStorage({ connection, executions }),
|
|
268
312
|
workflowInterventions: new SqliteWorkflowInterventionStorage({ connection }),
|
|
269
|
-
|
|
270
|
-
webhookRuns: new SqliteWebhookRunStorage({ connection }),
|
|
313
|
+
webhookRuns: new SqliteWebhookRunStorage({ connection, executions }),
|
|
271
314
|
rules: new SqliteRulesStorage({ connection }),
|
|
315
|
+
connectorConnections: new SqliteConnectorConnectionStorage(connection),
|
|
272
316
|
}
|
|
273
317
|
}
|
|
274
318
|
|
|
@@ -276,7 +320,10 @@ interface SqliteStoreSet {
|
|
|
276
320
|
readonly objects: SqliteObjectStorage
|
|
277
321
|
readonly ontology: SqliteOntologyStorage
|
|
278
322
|
readonly auth: SqliteAuthStorage
|
|
323
|
+
readonly executions: SqliteExecutionStorage
|
|
279
324
|
readonly agents: SqliteAgentStorage
|
|
325
|
+
readonly aiUsage: SqliteAiUsageStorage
|
|
326
|
+
readonly aiCosts: SqliteAiCostStorage
|
|
280
327
|
readonly actionRuns: SqliteActionRunStorage
|
|
281
328
|
readonly pipelineRuns: SqlitePipelineRunStorage
|
|
282
329
|
readonly syncRuns: SqliteSyncRunStorage
|
|
@@ -284,9 +331,9 @@ interface SqliteStoreSet {
|
|
|
284
331
|
readonly workflowRuns: SqliteWorkflowRunStorage
|
|
285
332
|
readonly workflowInterventions: SqliteWorkflowInterventionStorage
|
|
286
333
|
readonly timeseries: SqliteTimeseriesStorage
|
|
287
|
-
readonly webhookDeliveries: SqliteWebhookDeliveryStorage
|
|
288
334
|
readonly webhookRuns: SqliteWebhookRunStorage
|
|
289
335
|
readonly rules: SqliteRulesStorage
|
|
336
|
+
readonly connectorConnections: SqliteConnectorConnectionStorage
|
|
290
337
|
}
|
|
291
338
|
|
|
292
339
|
export { migrateSqliteStorage } from "./migrations"
|
package/src/latest-run-query.ts
CHANGED
|
@@ -21,6 +21,12 @@ export function queryLatestRunsByOwnerId<TRow>(
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
const placeholders = ownerIds.map(() => "?").join(", ")
|
|
24
|
+
const orderColumn =
|
|
25
|
+
input.tableName === "sync_runs" ||
|
|
26
|
+
input.tableName === "pipeline_runs" ||
|
|
27
|
+
input.tableName === "projection_runs"
|
|
28
|
+
? "COALESCE(started_at, queued_at)"
|
|
29
|
+
: "started_at"
|
|
24
30
|
const rows = input.db
|
|
25
31
|
.query(
|
|
26
32
|
`
|
|
@@ -30,7 +36,7 @@ export function queryLatestRunsByOwnerId<TRow>(
|
|
|
30
36
|
*,
|
|
31
37
|
ROW_NUMBER() OVER (
|
|
32
38
|
PARTITION BY ${input.ownerColumn}
|
|
33
|
-
ORDER BY
|
|
39
|
+
ORDER BY ${orderColumn} DESC, id DESC
|
|
34
40
|
) AS sixb_latest_rank
|
|
35
41
|
FROM ${input.tableName}
|
|
36
42
|
WHERE project_id = ? AND ${input.ownerColumn} IN (${placeholders})
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
CREATE TABLE executions (
|
|
2
|
+
project_id TEXT NOT NULL CHECK (length(trim(project_id)) > 0),
|
|
3
|
+
id TEXT NOT NULL CHECK (length(trim(id)) > 0),
|
|
4
|
+
|
|
5
|
+
executor_kind TEXT NOT NULL CHECK (
|
|
6
|
+
executor_kind IN (
|
|
7
|
+
'request', 'action', 'pipeline', 'projection', 'rule', 'sync', 'webhook', 'workflow',
|
|
8
|
+
'agent', 'kernel'
|
|
9
|
+
)
|
|
10
|
+
),
|
|
11
|
+
executor_id TEXT NOT NULL CHECK (length(trim(executor_id)) > 0),
|
|
12
|
+
source_kind TEXT NOT NULL CHECK (
|
|
13
|
+
source_kind IN ('http', 'webhook', 'schedule', 'event', 'execution')
|
|
14
|
+
),
|
|
15
|
+
source_id TEXT NOT NULL CHECK (length(trim(source_id)) > 0),
|
|
16
|
+
|
|
17
|
+
requested_by_user_id TEXT,
|
|
18
|
+
requested_by_service_account_id TEXT,
|
|
19
|
+
correlation_id TEXT NOT NULL CHECK (length(trim(correlation_id)) > 0),
|
|
20
|
+
parent_execution_id TEXT,
|
|
21
|
+
|
|
22
|
+
authority_kind TEXT NOT NULL CHECK (
|
|
23
|
+
authority_kind IN ('principal', 'trustedPrimitive', 'kernel', 'disabled')
|
|
24
|
+
),
|
|
25
|
+
authority_user_id TEXT,
|
|
26
|
+
authority_service_account_id TEXT,
|
|
27
|
+
authority_session_id TEXT,
|
|
28
|
+
authority_access_token_id TEXT,
|
|
29
|
+
authority_primitive_kind TEXT CHECK (
|
|
30
|
+
authority_primitive_kind IS NULL
|
|
31
|
+
OR authority_primitive_kind IN (
|
|
32
|
+
'action', 'pipeline', 'projection', 'rule', 'sync', 'webhook', 'workflow'
|
|
33
|
+
)
|
|
34
|
+
),
|
|
35
|
+
authority_primitive_id TEXT,
|
|
36
|
+
authority_kernel_operation TEXT CHECK (
|
|
37
|
+
authority_kernel_operation IS NULL OR authority_kernel_operation = 'ontology.recover'
|
|
38
|
+
),
|
|
39
|
+
|
|
40
|
+
created_at TEXT NOT NULL,
|
|
41
|
+
|
|
42
|
+
PRIMARY KEY (project_id, id),
|
|
43
|
+
FOREIGN KEY (project_id, parent_execution_id)
|
|
44
|
+
REFERENCES executions (project_id, id),
|
|
45
|
+
FOREIGN KEY (project_id, requested_by_user_id)
|
|
46
|
+
REFERENCES auth_users (project_id, id),
|
|
47
|
+
FOREIGN KEY (project_id, requested_by_service_account_id)
|
|
48
|
+
REFERENCES auth_service_accounts (project_id, id),
|
|
49
|
+
FOREIGN KEY (project_id, authority_user_id)
|
|
50
|
+
REFERENCES auth_users (project_id, id),
|
|
51
|
+
FOREIGN KEY (project_id, authority_service_account_id)
|
|
52
|
+
REFERENCES auth_service_accounts (project_id, id),
|
|
53
|
+
FOREIGN KEY (project_id, authority_session_id)
|
|
54
|
+
REFERENCES auth_sessions (project_id, id),
|
|
55
|
+
FOREIGN KEY (project_id, authority_access_token_id)
|
|
56
|
+
REFERENCES auth_access_tokens (project_id, id),
|
|
57
|
+
|
|
58
|
+
CHECK (
|
|
59
|
+
(requested_by_user_id IS NOT NULL) + (requested_by_service_account_id IS NOT NULL) <= 1
|
|
60
|
+
),
|
|
61
|
+
CHECK (
|
|
62
|
+
(source_kind = 'execution' AND parent_execution_id = source_id)
|
|
63
|
+
OR (source_kind <> 'execution' AND parent_execution_id IS NULL)
|
|
64
|
+
),
|
|
65
|
+
CHECK (
|
|
66
|
+
(
|
|
67
|
+
authority_kind = 'principal'
|
|
68
|
+
AND (authority_user_id IS NOT NULL) + (authority_service_account_id IS NOT NULL) = 1
|
|
69
|
+
AND (authority_session_id IS NOT NULL) + (authority_access_token_id IS NOT NULL) <= 1
|
|
70
|
+
AND (authority_session_id IS NULL OR authority_user_id IS NOT NULL)
|
|
71
|
+
AND authority_primitive_kind IS NULL
|
|
72
|
+
AND authority_primitive_id IS NULL
|
|
73
|
+
AND authority_kernel_operation IS NULL
|
|
74
|
+
)
|
|
75
|
+
OR (
|
|
76
|
+
authority_kind = 'trustedPrimitive'
|
|
77
|
+
AND authority_user_id IS NULL
|
|
78
|
+
AND authority_service_account_id IS NULL
|
|
79
|
+
AND authority_session_id IS NULL
|
|
80
|
+
AND authority_access_token_id IS NULL
|
|
81
|
+
AND authority_primitive_kind IS NOT NULL
|
|
82
|
+
AND authority_primitive_id IS NOT NULL
|
|
83
|
+
AND length(trim(authority_primitive_id)) > 0
|
|
84
|
+
AND authority_kernel_operation IS NULL
|
|
85
|
+
)
|
|
86
|
+
OR (
|
|
87
|
+
authority_kind = 'kernel'
|
|
88
|
+
AND authority_user_id IS NULL
|
|
89
|
+
AND authority_service_account_id IS NULL
|
|
90
|
+
AND authority_session_id IS NULL
|
|
91
|
+
AND authority_access_token_id IS NULL
|
|
92
|
+
AND authority_primitive_kind IS NULL
|
|
93
|
+
AND authority_primitive_id IS NULL
|
|
94
|
+
AND authority_kernel_operation IS NOT NULL
|
|
95
|
+
)
|
|
96
|
+
OR (
|
|
97
|
+
authority_kind = 'disabled'
|
|
98
|
+
AND authority_user_id IS NULL
|
|
99
|
+
AND authority_service_account_id IS NULL
|
|
100
|
+
AND authority_session_id IS NULL
|
|
101
|
+
AND authority_access_token_id IS NULL
|
|
102
|
+
AND authority_primitive_kind IS NULL
|
|
103
|
+
AND authority_primitive_id IS NULL
|
|
104
|
+
AND authority_kernel_operation IS NULL
|
|
105
|
+
)
|
|
106
|
+
),
|
|
107
|
+
CHECK (
|
|
108
|
+
(
|
|
109
|
+
executor_kind = 'request'
|
|
110
|
+
AND source_kind = 'http'
|
|
111
|
+
AND executor_id = source_id
|
|
112
|
+
AND (
|
|
113
|
+
(
|
|
114
|
+
authority_kind = 'principal'
|
|
115
|
+
AND requested_by_user_id IS authority_user_id
|
|
116
|
+
AND requested_by_service_account_id IS authority_service_account_id
|
|
117
|
+
)
|
|
118
|
+
OR (
|
|
119
|
+
authority_kind = 'disabled'
|
|
120
|
+
AND requested_by_user_id IS NULL
|
|
121
|
+
AND requested_by_service_account_id IS NULL
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
)
|
|
125
|
+
OR (
|
|
126
|
+
executor_kind IN ('action', 'pipeline', 'projection', 'rule', 'sync', 'webhook', 'workflow')
|
|
127
|
+
AND authority_kind = 'trustedPrimitive'
|
|
128
|
+
AND executor_kind = authority_primitive_kind
|
|
129
|
+
)
|
|
130
|
+
OR (
|
|
131
|
+
executor_kind = 'agent'
|
|
132
|
+
AND authority_kind = 'principal'
|
|
133
|
+
AND authority_service_account_id IS NOT NULL
|
|
134
|
+
AND authority_session_id IS NULL
|
|
135
|
+
AND authority_access_token_id IS NULL
|
|
136
|
+
)
|
|
137
|
+
OR (
|
|
138
|
+
executor_kind = 'kernel'
|
|
139
|
+
AND authority_kind = 'kernel'
|
|
140
|
+
)
|
|
141
|
+
)
|
|
142
|
+
);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ALTER TABLE workflow_runs ADD COLUMN execution_id TEXT NOT NULL;
|
|
2
|
+
ALTER TABLE workflow_runs DROP COLUMN source;
|
|
3
|
+
ALTER TABLE workflow_runs DROP COLUMN requested_by_principal_type;
|
|
4
|
+
ALTER TABLE workflow_runs DROP COLUMN requested_by_principal_id;
|
|
5
|
+
|
|
6
|
+
CREATE UNIQUE INDEX idx_workflow_runs_project_execution
|
|
7
|
+
ON workflow_runs(project_id, execution_id);
|