@kici-dev/orchestrator 0.1.14 → 0.1.15
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 +13 -1
- package/dist/__test-helpers__/mock-db.d.ts +2 -0
- package/dist/agent/dispatcher.d.ts +110 -6
- package/dist/agent/registry.d.ts +14 -0
- package/dist/app.d.ts +11 -0
- package/dist/cache/agent-job-failed-error.d.ts +13 -0
- package/dist/cache/dispatch-cache-ref-tracker.d.ts +45 -0
- package/dist/cache/index.d.ts +2 -0
- package/dist/cache/user-cache.d.ts +116 -0
- package/dist/cancel/cancel-run.d.ts +56 -0
- package/dist/cli/commands/environment.d.ts +1 -0
- package/dist/cli.js +523 -111
- package/dist/cluster/peer-registry.d.ts +6 -0
- package/dist/config/schema.d.ts +4 -0
- package/dist/config.d.ts +13 -0
- package/dist/dashboard/handler.d.ts +92 -1
- package/dist/db/migrations/026_event_log_lockfile_corrupt.d.ts +11 -0
- package/dist/db/migrations/027_workflow_timeout.d.ts +20 -0
- package/dist/db/migrations/028_org_settings_user_cache.d.ts +4 -0
- package/dist/db/migrations/029_dispatch_queue_attempts.d.ts +16 -0
- package/dist/db/migrations/030_held_runs_env_set_null.d.ts +13 -0
- package/dist/db/migrations/031_dispatch_queue_ack_deadline.d.ts +19 -0
- package/dist/db/migrations/032_org_settings_dispatch_ack_timeout.d.ts +14 -0
- package/dist/db/types.d.ts +37 -2
- package/dist/environments/environment-store.d.ts +14 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +362 -40
- package/dist/lockfile-cache.d.ts +1 -1
- package/dist/metrics/prometheus.d.ts +8 -0
- package/dist/orchestrator-core.d.ts +4 -1
- package/dist/pipeline/dispatch-matched-workflow.d.ts +9 -0
- package/dist/pipeline/inline-eval.d.ts +17 -2
- package/dist/pipeline/process-webhook.d.ts +19 -0
- package/dist/pipeline/processor.d.ts +6 -1
- package/dist/pipeline/test-pipeline.d.ts +10 -0
- package/dist/providers/github/lock-file.d.ts +1 -1
- package/dist/providers/internal/lock-file-fetcher.d.ts +3 -2
- package/dist/queue/job-queue.d.ts +53 -1
- package/dist/reporting/execution-tracker.d.ts +3 -1
- package/dist/routes/admin-environments.d.ts +1 -0
- package/dist/scaler/bare-metal-backend.d.ts +1 -0
- package/dist/scaler/container-backend.d.ts +3 -2
- package/dist/scaler/firecracker-backend.d.ts +17 -0
- package/dist/scaler/manager.d.ts +2 -0
- package/dist/scaler/nftables.d.ts +25 -3
- package/dist/scaler/types.d.ts +26 -1
- package/dist/server.js +3981 -1421
- package/dist/stale-detector/workflow-deadline-detector.d.ts +49 -0
- package/dist/standalone.js +16819 -14768
- package/dist/storage/filesystem.d.ts +12 -3
- package/dist/storage/s3.d.ts +17 -4
- package/dist/storage/types.d.ts +25 -5
- package/dist/worker/in-memory-job-queue.d.ts +40 -7
- package/dist/ws/agent-handler.d.ts +13 -0
- package/dist/ws/dashboard-env-handler.d.ts +1 -0
- package/dist/ws/platform-client.d.ts +10 -1
- package/package.json +13 -10
- package/sbom.spdx.json +47 -47
|
@@ -21,6 +21,12 @@ export interface PeerAgentInfo {
|
|
|
21
21
|
* in the required label set.
|
|
22
22
|
*/
|
|
23
23
|
mandatoryLabels: string[];
|
|
24
|
+
/**
|
|
25
|
+
* Name of the scaler backend that spawned this agent, or null for static
|
|
26
|
+
* (stateful) agents not bound to any scaler. Surfaced in diagnostics so the
|
|
27
|
+
* dashboard can group a peer's agents under the correct scaler row.
|
|
28
|
+
*/
|
|
29
|
+
scalerName?: string | null;
|
|
24
30
|
}
|
|
25
31
|
export interface PeerInfo {
|
|
26
32
|
instanceId: string;
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -107,6 +107,8 @@ export declare const sharedConfigSchema: z.ZodObject<{
|
|
|
107
107
|
cacheTtlDays: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
108
108
|
cacheBuildTimeoutMs: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
109
109
|
cacheMaxTarballBytes: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
110
|
+
userCacheQuotaBytes: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
111
|
+
userCacheTtlMs: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
110
112
|
eventRouter: z.ZodOptional<z.ZodObject<{
|
|
111
113
|
maxChainDepth: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
112
114
|
rateLimitPerWorkflowPerMinute: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
@@ -189,6 +191,8 @@ export declare const appConfigSchema: z.ZodObject<{
|
|
|
189
191
|
cacheTtlDays: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
190
192
|
cacheBuildTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
191
193
|
cacheMaxTarballBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
194
|
+
userCacheQuotaBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
195
|
+
userCacheTtlMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
192
196
|
eventRouterMaxChainDepth: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
193
197
|
eventRouterRateLimitPerWorkflowPerMinute: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
194
198
|
eventRouterEventTtlSeconds: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
package/dist/config.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
36
36
|
queueBackpressureThreshold: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
37
37
|
workerConcurrency: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
38
38
|
concurrencyWaitTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
39
|
+
dispatchAckTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
39
40
|
cacheStorageType: z.ZodOptional<z.ZodEnum<{
|
|
40
41
|
s3: "s3";
|
|
41
42
|
filesystem: "filesystem";
|
|
@@ -46,6 +47,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
46
47
|
cacheStorageS3Region: z.ZodOptional<z.ZodString>;
|
|
47
48
|
cacheStorageS3Endpoint: z.ZodOptional<z.ZodString>;
|
|
48
49
|
cacheStorageS3ExternalEndpoint: z.ZodOptional<z.ZodString>;
|
|
50
|
+
cacheStorageS3UploadEndpoint: z.ZodOptional<z.ZodString>;
|
|
49
51
|
cacheStorageS3ForcePathStyle: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
|
|
50
52
|
true: "true";
|
|
51
53
|
false: "false";
|
|
@@ -56,6 +58,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
56
58
|
cacheTtlDays: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
57
59
|
cacheBuildTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
58
60
|
cacheMaxTarballBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
61
|
+
userCacheQuotaBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
62
|
+
userCacheTtlMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
59
63
|
webhookPayloadDir: z.ZodOptional<z.ZodString>;
|
|
60
64
|
dataDir: z.ZodOptional<z.ZodString>;
|
|
61
65
|
scalerConfigPath: z.ZodOptional<z.ZodString>;
|
|
@@ -149,12 +153,17 @@ export type AppConfig = z.infer<typeof configSchema> & {
|
|
|
149
153
|
region?: string;
|
|
150
154
|
endpoint?: string;
|
|
151
155
|
externalEndpoint?: string;
|
|
156
|
+
uploadEndpoint?: string;
|
|
152
157
|
forcePathStyle?: boolean;
|
|
153
158
|
logBucket?: string;
|
|
154
159
|
/** Filesystem backend: absolute base directory for cached blobs. */
|
|
155
160
|
fsBasePath?: string;
|
|
156
161
|
/** Filesystem backend: base URL the agent uses to reach this orchestrator. */
|
|
157
162
|
fsBaseUrl?: string;
|
|
163
|
+
/** Per-org byte quota for the user-facing cache (UserCache). */
|
|
164
|
+
userCacheQuotaBytes?: number;
|
|
165
|
+
/** Per-entry TTL (ms) for the user-facing cache (UserCache). */
|
|
166
|
+
userCacheTtlMs?: number;
|
|
158
167
|
};
|
|
159
168
|
};
|
|
160
169
|
/**
|
|
@@ -177,10 +186,13 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
|
|
|
177
186
|
queueBackpressureThreshold: number;
|
|
178
187
|
workerConcurrency: number;
|
|
179
188
|
concurrencyWaitTimeoutMs: number;
|
|
189
|
+
dispatchAckTimeoutMs: number;
|
|
180
190
|
cacheStorageS3Prefix: string;
|
|
181
191
|
cacheTtlDays: number;
|
|
182
192
|
cacheBuildTimeoutMs: number;
|
|
183
193
|
cacheMaxTarballBytes: number;
|
|
194
|
+
userCacheQuotaBytes: number;
|
|
195
|
+
userCacheTtlMs: number;
|
|
184
196
|
staleDetectorScanIntervalMs: number;
|
|
185
197
|
staleDetectorThresholdMultiplier: number;
|
|
186
198
|
jobHeartbeatIntervalMs: number;
|
|
@@ -234,6 +246,7 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
|
|
|
234
246
|
cacheStorageS3Region?: string | undefined;
|
|
235
247
|
cacheStorageS3Endpoint?: string | undefined;
|
|
236
248
|
cacheStorageS3ExternalEndpoint?: string | undefined;
|
|
249
|
+
cacheStorageS3UploadEndpoint?: string | undefined;
|
|
237
250
|
cacheStorageS3ForcePathStyle?: boolean | undefined;
|
|
238
251
|
cacheStorageFsPath?: string | undefined;
|
|
239
252
|
cacheStorageFsBaseUrl?: string | undefined;
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { type Kysely } from 'kysely';
|
|
15
15
|
import { type ColdStore } from '@kici-dev/shared';
|
|
16
|
-
import type { DashboardRunDetailRequest, DashboardStepLogsRequest, DashboardPayloadRequest, DashboardOrchLogsRequest, DashboardEventLogListRequest, DashboardEventLogDetailRequest, DashboardEventLogPayloadStreamRequest, DashboardAccessLogListRequest, DashboardEventDlqListRequest, DashboardEventDlqCountRequest, DashboardEventDlqRetryRequest, DashboardEventDlqDiscardRequest, RunRerunRequest, RunCancelRequest, ManualScheduleRequest } from '@kici-dev/engine';
|
|
16
|
+
import type { DashboardRunDetailRequest, DashboardRunsListRequest, DashboardRunsListResponse, DashboardRunsFiltersRequest, DashboardRunsFiltersResponse, DashboardSourcesListRequest, DashboardSourcesListResponse, DashboardStepLogsRequest, DashboardPayloadRequest, DashboardOrchLogsRequest, DashboardEventLogListRequest, DashboardEventLogDetailRequest, DashboardEventLogPayloadStreamRequest, DashboardAccessLogListRequest, DashboardEventDlqListRequest, DashboardEventDlqCountRequest, DashboardEventDlqRetryRequest, DashboardEventDlqDiscardRequest, RunRerunRequest, RunCancelRequest, ManualScheduleRequest } from '@kici-dev/engine';
|
|
17
17
|
import type { Database } from '../db/types.js';
|
|
18
18
|
import type { LogStorage } from '../reporting/log-storage.js';
|
|
19
19
|
import type { AccessLogWriter } from '../audit/access-log.js';
|
|
@@ -155,6 +155,97 @@ export declare class DashboardHandler {
|
|
|
155
155
|
* builds a nested job/step tree, and sends the response.
|
|
156
156
|
*/
|
|
157
157
|
handleRunDetail(msg: DashboardRunDetailRequest): Promise<void>;
|
|
158
|
+
/**
|
|
159
|
+
* Resolve every routing key owned by an org by unioning both source
|
|
160
|
+
* tables. The orchestrator is single-org but multi-routing-key: one org
|
|
161
|
+
* owns one GitHub-app source plus N generic sources, each with its own
|
|
162
|
+
* `routing_key`. `execution_runs` has no `org_id` column — org ownership
|
|
163
|
+
* is expressed purely through `routing_key → sources.customer_id` /
|
|
164
|
+
* `generic_webhook_sources.customer_id`, so scoping a run query to an org
|
|
165
|
+
* means scoping it to the union of that org's routing keys.
|
|
166
|
+
*
|
|
167
|
+
* Predicates mirror the org-context resolver in `server.ts` and
|
|
168
|
+
* `resolveOrgForRoutingKey` above:
|
|
169
|
+
* - `sources`: `customer_id = orgId` excluding the `__default__` sentinel.
|
|
170
|
+
* - `generic_webhook_sources`: `customer_id = orgId` and not soft-deleted
|
|
171
|
+
* (`deleted_at is null`).
|
|
172
|
+
*/
|
|
173
|
+
private resolveOrgRoutingKeys;
|
|
174
|
+
/**
|
|
175
|
+
* Resolve a per-routing-key source identity map for a set of routing keys,
|
|
176
|
+
* unioning both source tables. Uses the identical name/subtype/provider
|
|
177
|
+
* derivation as `handleSourcesList` so a run summary's `source` block
|
|
178
|
+
* matches what the sources page shows for the same routing key. Routing
|
|
179
|
+
* keys with no live source row are simply absent from the map (the caller
|
|
180
|
+
* falls back to the run's own provider).
|
|
181
|
+
*/
|
|
182
|
+
private resolveSourceIdentities;
|
|
183
|
+
/**
|
|
184
|
+
* Look up the page's jobs in one query to derive per-run `jobCount` plus the
|
|
185
|
+
* compile-job markers (`hadCompileJob` / `compileJobId`). The compile job is
|
|
186
|
+
* the synthetic `__build__*` job KiCI inserts for the compile phase — the
|
|
187
|
+
* same definition the Platform run-list route uses
|
|
188
|
+
* (`job_name LIKE '__build__%'`). Returns a per-run aggregate keyed by
|
|
189
|
+
* `run_id`; runs with no job rows are absent (the caller omits the fields).
|
|
190
|
+
*/
|
|
191
|
+
private resolveRunJobAggregates;
|
|
192
|
+
/**
|
|
193
|
+
* Handle a dashboard.runs.list request.
|
|
194
|
+
*
|
|
195
|
+
* Returns a page of run summaries from `execution_runs`, scoped to ALL
|
|
196
|
+
* routing keys owned by this orchestrator's bound org (`this.orgId`). The
|
|
197
|
+
* orchestrator is single-org but multi-routing-key, and the bound
|
|
198
|
+
* `this.routingKey` is just ONE of the org's keys (resolved
|
|
199
|
+
* non-deterministically at startup), so filtering on it alone would drop
|
|
200
|
+
* runs that arrived under a sibling routing key. We resolve the org's full
|
|
201
|
+
* routing-key set from `sources` + `generic_webhook_sources` and filter on
|
|
202
|
+
* the union. Attribution still uses the handler-bound `orgId` /
|
|
203
|
+
* `routingKey` directly — the same inline-ctx pattern as the org-scoped
|
|
204
|
+
* event-log / access-log handlers.
|
|
205
|
+
*
|
|
206
|
+
* Used by the operator console (`support-read` break-glass) and the
|
|
207
|
+
* dashboard's run-list view. The access_log row carries the wire actor
|
|
208
|
+
* (including the platform_operator reason) so the customer can audit any
|
|
209
|
+
* operator read.
|
|
210
|
+
*/
|
|
211
|
+
handleRunsList(msg: DashboardRunsListRequest): Promise<DashboardRunsListResponse>;
|
|
212
|
+
/**
|
|
213
|
+
* Handle a dashboard.runs.filters request.
|
|
214
|
+
*
|
|
215
|
+
* Returns the distinct filter-option values the customer runs page renders
|
|
216
|
+
* in its filter controls — statuses / workflows / branches / repositories /
|
|
217
|
+
* triggerTypes / sources — scoped to ALL routing keys owned by this
|
|
218
|
+
* orchestrator's bound org (same scoping as `handleRunsList`). Distinct
|
|
219
|
+
* values are derived in-memory from a single column projection over
|
|
220
|
+
* `execution_runs`; `sources` reuses `resolveSourceIdentities` so the list
|
|
221
|
+
* matches what the sources page shows for the same routing key.
|
|
222
|
+
*
|
|
223
|
+
* `triggerTypes` is populated from `execution_runs.provider` — the
|
|
224
|
+
* orchestrator has no dedicated trigger-event column, so `provider`
|
|
225
|
+
* (`github` / `generic` / `internal`) is the closest available
|
|
226
|
+
* discriminator the customer filter can offer.
|
|
227
|
+
*
|
|
228
|
+
* Attribution uses the handler-bound `orgId` / `routingKey` directly — the
|
|
229
|
+
* same inline-ctx pattern as `handleRunsList`. The access_log row carries
|
|
230
|
+
* the wire actor (including the platform_operator reason) so the customer
|
|
231
|
+
* can audit any operator read.
|
|
232
|
+
*/
|
|
233
|
+
handleRunsFilters(msg: DashboardRunsFiltersRequest): Promise<DashboardRunsFiltersResponse>;
|
|
234
|
+
/**
|
|
235
|
+
* Handle a dashboard.sources.list request.
|
|
236
|
+
*
|
|
237
|
+
* Returns the org's webhook source summaries by unioning both source
|
|
238
|
+
* tables (GitHub-app `sources` + live `generic_webhook_sources`), scoped
|
|
239
|
+
* to this orchestrator's bound org (`this.orgId`). Source counts are tiny
|
|
240
|
+
* so the page is returned unpaginated (`msg.limit` is ignored). Secret-
|
|
241
|
+
* bearing columns (`config`, `git_config`, `verification_config`) are
|
|
242
|
+
* never projected — `git_config` is read only to derive the subtype.
|
|
243
|
+
*
|
|
244
|
+
* Attribution uses the handler-bound `orgId` / `routingKey` directly —
|
|
245
|
+
* the same inline-ctx pattern as `handleRunsList`. The access_log row
|
|
246
|
+
* carries the wire actor so the customer can audit any operator read.
|
|
247
|
+
*/
|
|
248
|
+
handleSourcesList(msg: DashboardSourcesListRequest): Promise<DashboardSourcesListResponse>;
|
|
158
249
|
/**
|
|
159
250
|
* Handle a dashboard.step.logs request.
|
|
160
251
|
* Looks up the step's log_path and reads content from LogStorage.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* Extend the event_log.status CHECK constraint with 'lockfile_corrupt' so the
|
|
4
|
+
* orchestrator can log a delivery whose lock file was present but unparseable.
|
|
5
|
+
* Orchestrator-only: the Platform event_log uses a separate, narrower status set.
|
|
6
|
+
*
|
|
7
|
+
* Idempotent: the DROP ... IF EXISTS / re-ADD pair re-runs cleanly.
|
|
8
|
+
*/
|
|
9
|
+
export declare function up(db: Kysely<unknown>): Promise<void>;
|
|
10
|
+
export declare function down(db: Kysely<unknown>): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=026_event_log_lockfile_corrupt.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* Add `workflow_timeout_ms integer` to `execution_runs`.
|
|
4
|
+
*
|
|
5
|
+
* Persists the workflow-level wall-clock timeout (in milliseconds) read from
|
|
6
|
+
* the lock workflow at run creation. NULL means no workflow-level cap is
|
|
7
|
+
* configured. The WorkflowDeadlineDetector reads this column to find runs
|
|
8
|
+
* whose `started_at + workflow_timeout_ms` has passed and cancels them with
|
|
9
|
+
* the distinct workflow-timeout reason.
|
|
10
|
+
*
|
|
11
|
+
* Typed INTEGER to match the existing `*_ms` columns (`duration_ms`,
|
|
12
|
+
* `concurrency_timeout_ms`), which keeps the pg read representation a plain
|
|
13
|
+
* number rather than the BIGINT-as-string shape. INTEGER caps the timeout at
|
|
14
|
+
* ~24.8 days, far beyond any sane workflow wall-clock budget.
|
|
15
|
+
*
|
|
16
|
+
* Idempotent: re-running on a DB that already has the column is a no-op.
|
|
17
|
+
*/
|
|
18
|
+
export declare function up(db: Kysely<unknown>): Promise<void>;
|
|
19
|
+
export declare function down(db: Kysely<unknown>): Promise<void>;
|
|
20
|
+
//# sourceMappingURL=027_workflow_timeout.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* Add `dispatch_queue.dispatch_attempts INT NOT NULL DEFAULT 0`.
|
|
4
|
+
*
|
|
5
|
+
* Counts how many times a job has been returned to `pending` for
|
|
6
|
+
* re-dispatch after a failed delivery attempt (agent sent job.reject, or
|
|
7
|
+
* a scaler-managed agent disconnected before the job started). The
|
|
8
|
+
* dispatcher fails the job permanently once the counter reaches
|
|
9
|
+
* MAX_DISPATCH_ATTEMPTS, bounding requeue loops; `expires_at` remains the
|
|
10
|
+
* time-based backstop.
|
|
11
|
+
*
|
|
12
|
+
* Idempotent: re-running on a DB that already has the column is a no-op.
|
|
13
|
+
*/
|
|
14
|
+
export declare function up(db: Kysely<unknown>): Promise<void>;
|
|
15
|
+
export declare function down(db: Kysely<unknown>): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=029_dispatch_queue_attempts.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* held_runs.environment_id becomes nullable with ON DELETE SET NULL so
|
|
4
|
+
* terminal held-run history survives environment deletion (a null
|
|
5
|
+
* environment_id means the environment was since deleted). Pending held
|
|
6
|
+
* runs still block deletion — enforced in EnvironmentStore.delete.
|
|
7
|
+
*
|
|
8
|
+
* Idempotent: dropping the NOT NULL and the constraint are both no-ops on a
|
|
9
|
+
* re-run, and the constraint is re-created with the SET NULL action.
|
|
10
|
+
*/
|
|
11
|
+
export declare function up(db: Kysely<unknown>): Promise<void>;
|
|
12
|
+
export declare function down(db: Kysely<unknown>): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=030_held_runs_env_set_null.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* Add `dispatch_queue.ack_deadline TIMESTAMPTZ` and
|
|
4
|
+
* `dispatch_queue.ack_agent_id TEXT` persisting the per-dispatch
|
|
5
|
+
* acknowledgment deadline for HA-safe lost-dispatch detection.
|
|
6
|
+
*
|
|
7
|
+
* The dispatcher stamps both when a job.dispatch is sent and clears them
|
|
8
|
+
* when the agent answers (job.ack / job.reject / job.status running). A
|
|
9
|
+
* `dispatched` row past its deadline is requeued — by the owning coord's
|
|
10
|
+
* in-memory timer, or by the leader-gated sweep
|
|
11
|
+
* (`Dispatcher.sweepExpiredAckDeadlines`) when the owning coord crashed.
|
|
12
|
+
* On coord boot, `Dispatcher.recoverState()` re-arms timers from the
|
|
13
|
+
* persisted deadlines.
|
|
14
|
+
*
|
|
15
|
+
* Idempotent: re-running on a DB that already has either column is a no-op.
|
|
16
|
+
*/
|
|
17
|
+
export declare function up(db: Kysely<unknown>): Promise<void>;
|
|
18
|
+
export declare function down(db: Kysely<unknown>): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=031_dispatch_queue_ack_deadline.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* Add `org_settings.dispatch_ack_timeout_ms BIGINT` (nullable).
|
|
4
|
+
*
|
|
5
|
+
* Per-org override of the dispatch-acknowledgment deadline. NULL falls
|
|
6
|
+
* back to the cluster-wide default (`KICI_DISPATCH_ACK_TIMEOUT_MS`,
|
|
7
|
+
* default 10s). Operators raise it on high-latency networks via
|
|
8
|
+
* `kici-admin org-settings`.
|
|
9
|
+
*
|
|
10
|
+
* Idempotent: a re-run on a DB that already has the column is a no-op.
|
|
11
|
+
*/
|
|
12
|
+
export declare function up(db: Kysely<unknown>): Promise<void>;
|
|
13
|
+
export declare function down(db: Kysely<unknown>): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=032_org_settings_dispatch_ack_timeout.d.ts.map
|
package/dist/db/types.d.ts
CHANGED
|
@@ -158,6 +158,17 @@ export interface DispatchQueueTable {
|
|
|
158
158
|
* real provisioning cause; cleared on dispatch. NULL when none recorded.
|
|
159
159
|
*/
|
|
160
160
|
last_provisioning_error: ColumnType<string | null, string | null | undefined, string | null>;
|
|
161
|
+
/** Times this job was returned to pending for re-dispatch (job.reject / pre-start agent loss). */
|
|
162
|
+
dispatch_attempts: Generated<number>;
|
|
163
|
+
/**
|
|
164
|
+
* Deadline by which the dispatched job's agent must answer the
|
|
165
|
+
* job.dispatch (job.ack / job.reject / job.status running). Stamped when
|
|
166
|
+
* the dispatch is sent, cleared on any answer; `dispatched` rows past the
|
|
167
|
+
* deadline are requeued by the owning coord's timer or the leader sweep.
|
|
168
|
+
*/
|
|
169
|
+
ack_deadline: ColumnType<Date | null, Date | null | undefined, Date | null>;
|
|
170
|
+
/** Agent the dispatch was sent to (for ack-timeout disconnect + logging). */
|
|
171
|
+
ack_agent_id: ColumnType<string | null, string | null | undefined, string | null>;
|
|
161
172
|
}
|
|
162
173
|
/**
|
|
163
174
|
* Deduplication cache table
|
|
@@ -266,6 +277,12 @@ export interface ExecutionRunTable {
|
|
|
266
277
|
* provider context, agent spawn). NULL for normal runs.
|
|
267
278
|
*/
|
|
268
279
|
init_failure: ColumnType<InitFailure | null, unknown, unknown>;
|
|
280
|
+
/**
|
|
281
|
+
* Whole-run wall-clock timeout in ms from the workflow lock; null when
|
|
282
|
+
* unset. Read by the WorkflowDeadlineDetector. INTEGER in Postgres, matching
|
|
283
|
+
* the other `*_ms` columns, so pg returns a plain number.
|
|
284
|
+
*/
|
|
285
|
+
workflow_timeout_ms: ColumnType<number | null, number | null | undefined, number | null>;
|
|
269
286
|
/** When this record was created */
|
|
270
287
|
created_at: Generated<Date>;
|
|
271
288
|
/**
|
|
@@ -595,8 +612,8 @@ export interface HeldRunsTable {
|
|
|
595
612
|
run_id: string;
|
|
596
613
|
/** Job ID within the run */
|
|
597
614
|
job_id: string;
|
|
598
|
-
/** Environment ID (FK to environments.id) */
|
|
599
|
-
environment_id: string;
|
|
615
|
+
/** Environment ID (FK to environments.id); null once the environment is deleted */
|
|
616
|
+
environment_id: string | null;
|
|
600
617
|
/** Hold type: 'approval' | 'wait_timer' | 'concurrency' */
|
|
601
618
|
hold_type: string;
|
|
602
619
|
/** Hold status: 'pending' | 'approved' | 'rejected' | 'expired' | 'released' */
|
|
@@ -1157,6 +1174,24 @@ export interface OrgSettingsTable {
|
|
|
1157
1174
|
* treats missing keys as `true`.
|
|
1158
1175
|
*/
|
|
1159
1176
|
dashboard_write_policy: ColumnType<Record<string, boolean>, Record<string, boolean> | string | undefined, Record<string, boolean> | string>;
|
|
1177
|
+
/**
|
|
1178
|
+
* Per-org byte quota for the user-facing cache (UserCache). NULL = use the
|
|
1179
|
+
* cluster-wide default (`KICI_USER_CACHE_QUOTA_BYTES`, 5 GiB). Postgres
|
|
1180
|
+
* BIGINT — pg returns a string on select; accept a number on insert/update.
|
|
1181
|
+
*/
|
|
1182
|
+
user_cache_quota_bytes: ColumnType<string | null, number | null | undefined, number | null>;
|
|
1183
|
+
/**
|
|
1184
|
+
* Per-entry TTL (ms) for the user-facing cache (UserCache). NULL = use the
|
|
1185
|
+
* cluster-wide default (`KICI_USER_CACHE_TTL_MS`, 7 days). Postgres BIGINT —
|
|
1186
|
+
* pg returns a string on select; accept a number on insert/update.
|
|
1187
|
+
*/
|
|
1188
|
+
user_cache_ttl_ms: ColumnType<string | null, number | null | undefined, number | null>;
|
|
1189
|
+
/**
|
|
1190
|
+
* Per-org dispatch-acknowledgment deadline (ms); null = cluster default
|
|
1191
|
+
* (config.dispatchAckTimeoutMs / KICI_DISPATCH_ACK_TIMEOUT_MS). Postgres
|
|
1192
|
+
* BIGINT — pg returns a string on select; accept a number on insert/update.
|
|
1193
|
+
*/
|
|
1194
|
+
dispatch_ack_timeout_ms: ColumnType<string | null, number | null | undefined, number | null>;
|
|
1160
1195
|
/** When this setting was created */
|
|
1161
1196
|
created_at: Generated<Date>;
|
|
1162
1197
|
/** When this setting was last updated */
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { type Kysely } from 'kysely';
|
|
2
2
|
import type { Environment as EngineEnvironment } from '@kici-dev/engine';
|
|
3
3
|
import type { Database, Environment } from '../db/types.js';
|
|
4
|
+
/** Thrown by `delete` when pending held runs reference the environment. */
|
|
5
|
+
export declare class EnvironmentDeleteBlockedError extends Error {
|
|
6
|
+
readonly pendingCount: number;
|
|
7
|
+
constructor(pendingCount: number);
|
|
8
|
+
}
|
|
4
9
|
/**
|
|
5
10
|
* Map a DB environment row (snake_case) to the engine Environment type (camelCase).
|
|
6
11
|
*
|
|
@@ -60,7 +65,15 @@ export declare class EnvironmentStore {
|
|
|
60
65
|
create(orgId: string, data: EnvironmentCreateInput): Promise<Environment>;
|
|
61
66
|
/** Update an environment. Returns the updated row, or null if not found. */
|
|
62
67
|
update(orgId: string, id: string, updates: EnvironmentUpdateInput): Promise<Environment | null>;
|
|
63
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* Delete an environment.
|
|
70
|
+
*
|
|
71
|
+
* Bindings, variables, and source overrides cascade away via their FK.
|
|
72
|
+
* Terminal held-run history survives with a null `environment_id` (the FK
|
|
73
|
+
* uses ON DELETE SET NULL). Pending held runs still reference the
|
|
74
|
+
* environment, so deletion is blocked with `EnvironmentDeleteBlockedError`
|
|
75
|
+
* until they are approved or rejected.
|
|
76
|
+
*/
|
|
64
77
|
delete(orgId: string, id: string): Promise<boolean>;
|
|
65
78
|
/**
|
|
66
79
|
* Match an environment name against org environments.
|
package/dist/index.d.ts
CHANGED
|
@@ -3,5 +3,6 @@ export { S3CacheStorage, type S3CacheStorageOptions } from './storage/s3.js';
|
|
|
3
3
|
export { createCacheStorage } from './storage/index.js';
|
|
4
4
|
export { SourceCache } from './cache/source-cache.js';
|
|
5
5
|
export { DepCache } from './cache/dep-cache.js';
|
|
6
|
+
export { UserCache, DEFAULT_USER_CACHE_QUOTA_BYTES, DEFAULT_USER_CACHE_TTL_MS, type UserCacheRef, type UserCacheRestoreResult, type UserCacheBeginSaveResult, } from './cache/user-cache.js';
|
|
6
7
|
export { PeerCredentialStore, createPeerCredentialStoreFromUrl, type PeerCredential, } from './cluster/peer-credentials.js';
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|