@kici-dev/orchestrator 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__test-helpers__/fake-scaler-state-store.d.ts +24 -0
- package/dist/__test-helpers__/mock-db-query.d.ts +130 -0
- package/dist/__test-helpers__/mock-db.d.ts +27 -0
- package/dist/agent/agent-version.d.ts +34 -0
- package/dist/agent/dispatcher.d.ts +151 -13
- package/dist/agent/host-roster.d.ts +37 -5
- package/dist/agent/registry.d.ts +2 -0
- package/dist/app.d.ts +56 -7
- package/dist/approvals/apply-decision.d.ts +67 -19
- package/dist/approvals/held-run-release-wiring.d.ts +45 -0
- package/dist/approvals/independent-wiring.d.ts +55 -0
- package/dist/approvals/resume-router.d.ts +9 -0
- package/dist/approvals/triggerer-subject.d.ts +37 -0
- package/dist/cache/dep-cache.d.ts +54 -10
- package/dist/cache/global-eval-round-cache.d.ts +95 -0
- package/dist/cache/index.d.ts +3 -0
- package/dist/cache/pending-global-evals.d.ts +42 -0
- package/dist/cache/pending-inits.d.ts +10 -0
- package/dist/cli/api-client.d.ts +18 -0
- package/dist/cli/commands/cluster-settings.d.ts +52 -3
- package/dist/cli/commands/diagnose.d.ts +6 -0
- package/dist/cli/commands/held-run.d.ts +58 -0
- package/dist/cli/commands/runs.d.ts +1 -0
- package/dist/cli/commands/trust-policy.d.ts +117 -12
- package/dist/cli/kici-admin.d.ts +10 -0
- package/dist/cli.js +2770 -938
- package/dist/cluster/cluster-identity.d.ts +3 -3
- package/dist/cluster/cluster-settings-reader.d.ts +59 -1
- package/dist/cluster/coordinator.d.ts +44 -0
- package/dist/cluster/index.d.ts +4 -0
- package/dist/cluster/peer-handler.d.ts +19 -0
- package/dist/cluster/peer-registry.d.ts +17 -0
- package/dist/cluster/plan-headroom-store.d.ts +26 -0
- package/dist/cluster/worker-eviction.d.ts +69 -0
- package/dist/cold-store/load-event-log-range.d.ts +10 -3
- package/dist/cold-store/load-secret-audit-log-range.d.ts +4 -3
- package/dist/cold-store/tables/secret-audit-log.d.ts +4 -3
- package/dist/config.d.ts +48 -21
- package/dist/content-requirements-cache.d.ts +55 -0
- package/dist/contexts/held-runs.d.ts +123 -16
- package/dist/contexts/protection/aggregate.d.ts +3 -2
- package/dist/contexts/protection/branch-gate.d.ts +15 -0
- package/dist/contexts/protection/concurrency-gate.d.ts +8 -2
- package/dist/contexts/protection/pipeline.d.ts +18 -0
- package/dist/contexts/release-queued-holds.d.ts +35 -0
- package/dist/dashboard/attestation-filters.d.ts +8 -0
- package/dist/dashboard/handler.d.ts +6 -24
- package/dist/db/migrations/109_cluster_settings_cache_knobs.d.ts +4 -0
- package/dist/db/migrations/110_cluster_settings_global_eval_knobs.d.ts +4 -0
- package/dist/db/migrations/111_cluster_settings_global_eval_wait.d.ts +4 -0
- package/dist/db/migrations/112_execution_runs_workflow_repo.d.ts +4 -0
- package/dist/db/migrations/113_execution_runs_workflow_repo_index.d.ts +30 -0
- package/dist/db/migrations/114_ingest_queue_claim.d.ts +4 -0
- package/dist/db/migrations/115_global_workflows_cluster_switch.d.ts +9 -0
- package/dist/db/migrations/116_org_plan_headroom.d.ts +4 -0
- package/dist/db/migrations/117_invoke_gate_proxy_jobs.d.ts +4 -0
- package/dist/db/migrations/118_invoke_gate_scheduling.d.ts +4 -0
- package/dist/db/migrations/119_scaler_ha_ownership.d.ts +4 -0
- package/dist/db/migrations/120_cluster_settings_scaler_reaper.d.ts +4 -0
- package/dist/db/migrations/121_org_settings_allow_untrusted_dockerfile_builds.d.ts +19 -0
- package/dist/db/migrations/122_host_roster_scaler_managed.d.ts +25 -0
- package/dist/db/migrations/123_workflow_registrations_default_branch.d.ts +24 -0
- package/dist/db/migrations/124_cluster_settings_provision_backoff.d.ts +4 -0
- package/dist/db/migrations/125_org_trust_directory.d.ts +30 -0
- package/dist/db/migrations/126_held_runs_posted_pending_check.d.ts +28 -0
- package/dist/db/migrations/127_org_trust_policy_approval_expiry_seconds.d.ts +26 -0
- package/dist/db/migrations/128_execution_runs_global_eval_round.d.ts +23 -0
- package/dist/db/migrations/129_execution_runs_dispatch_routing_key.d.ts +24 -0
- package/dist/db/migrations/130_scaler_provision_outcomes.d.ts +32 -0
- package/dist/db/types.d.ts +428 -12
- package/dist/entry-helpers.d.ts +28 -0
- package/dist/events/event-emitter.d.ts +22 -0
- package/dist/events/event-router.d.ts +87 -1
- package/dist/events/types.d.ts +2 -23
- package/dist/git/credential-broker.d.ts +94 -0
- package/dist/git/inherited-secret.d.ts +24 -0
- package/dist/git/installation-token.d.ts +38 -0
- package/dist/git/job-context.d.ts +13 -0
- package/dist/index.js +324 -84
- package/dist/metrics/agent-metrics-aggregator.d.ts +4 -4
- package/dist/metrics/prometheus.d.ts +170 -3
- package/dist/oidc/oidc-mint-registration.d.ts +7 -3
- package/dist/orchestrator-core.d.ts +91 -24
- package/dist/pipeline/content-filter.d.ts +71 -0
- package/dist/pipeline/direct-ingress-deps.d.ts +100 -0
- package/dist/pipeline/dispatch-matched-workflow.d.ts +521 -11
- package/dist/pipeline/global-eval-round.d.ts +307 -0
- package/dist/pipeline/internal-event-pipeline.d.ts +140 -0
- package/dist/pipeline/invoke-gate.d.ts +164 -0
- package/dist/pipeline/job-contexts.d.ts +16 -17
- package/dist/pipeline/needs-scheduler.d.ts +13 -0
- package/dist/pipeline/process-webhook.d.ts +126 -31
- package/dist/pipeline/processor.d.ts +282 -23
- package/dist/pipeline/rerun.d.ts +21 -0
- package/dist/pipeline/resume-workflow.d.ts +40 -7
- package/dist/pipeline/route-or-dispatch-jobs.d.ts +15 -0
- package/dist/pipeline/security-hold-check.d.ts +217 -0
- package/dist/pipeline/test-pipeline.d.ts +12 -0
- package/dist/pipeline/undispatched-hold-checks.d.ts +23 -0
- package/dist/pipeline/webhook-payload-store.d.ts +20 -0
- package/dist/policy/dashboard-write-policy-listener.d.ts +62 -0
- package/dist/policy/dashboard-write-policy.d.ts +14 -0
- package/dist/provenance/backfill-run.d.ts +10 -1
- package/dist/provider-registry.d.ts +47 -4
- package/dist/providers/github/check-status-poster.d.ts +33 -3
- package/dist/providers/github/commit-message.d.ts +20 -0
- package/dist/providers/github/file-contents.d.ts +40 -0
- package/dist/providers/github/index.d.ts +2 -2
- package/dist/providers/github/normalizer.d.ts +3 -2
- package/dist/providers/local/normalizer.d.ts +3 -5
- package/dist/providers/universal-git/config.d.ts +2 -0
- package/dist/providers/universal-git/index.d.ts +11 -2
- package/dist/providers/universal-git/normalizer.d.ts +10 -0
- package/dist/queue/cleanup.d.ts +7 -1
- package/dist/queue/job-queue.d.ts +112 -7
- package/dist/queue/terminalize-unroutable.d.ts +13 -0
- package/dist/registration/extractor.d.ts +3 -3
- package/dist/registration/registration-index.d.ts +7 -0
- package/dist/registration/registration-run-match.d.ts +47 -0
- package/dist/registration/registration-store.d.ts +22 -0
- package/dist/reporting/check-run-reporter.d.ts +146 -2
- package/dist/reporting/check-run-summary.d.ts +25 -1
- package/dist/reporting/execution-tracker.d.ts +324 -9
- package/dist/reporting/log-chunk-sink.d.ts +8 -5
- package/dist/reporting/run-aggregator.d.ts +4 -14
- package/dist/reporting/step-display-order.d.ts +43 -0
- package/dist/routes/admin-held-runs.d.ts +142 -0
- package/dist/routes/admin-org-settings.d.ts +5 -0
- package/dist/routes/admin-trust-policy.d.ts +34 -6
- package/dist/routes/admin.d.ts +15 -0
- package/dist/scaler/backend-factory.d.ts +55 -0
- package/dist/scaler/bare-metal-backend.d.ts +43 -5
- package/dist/scaler/claim-store.d.ts +119 -0
- package/dist/scaler/config.d.ts +4 -0
- package/dist/scaler/container-backend.d.ts +18 -4
- package/dist/scaler/container-routing.d.ts +23 -0
- package/dist/scaler/container-spawn.d.ts +28 -0
- package/dist/scaler/event-backend.d.ts +124 -0
- package/dist/scaler/event-provision-reaper.d.ts +350 -0
- package/dist/scaler/failure-tracker.d.ts +1 -1
- package/dist/scaler/firecracker-backend.d.ts +33 -6
- package/dist/scaler/index.d.ts +11 -1
- package/dist/scaler/label-matcher.d.ts +4 -3
- package/dist/scaler/manager.d.ts +905 -76
- package/dist/scaler/resolve-container-auth.d.ts +45 -0
- package/dist/scaler/scaler-events.d.ts +11 -0
- package/dist/scaler/scaler-state-store.d.ts +294 -10
- package/dist/scaler/types.d.ts +131 -13
- package/dist/scaler/warm-pool.d.ts +132 -29
- package/dist/security/comment-handler.d.ts +50 -11
- package/dist/security/global-workflow-policy.d.ts +52 -12
- package/dist/security/identity-link.d.ts +60 -0
- package/dist/security/lock-source.d.ts +11 -13
- package/dist/security/reduced-privilege-note.d.ts +59 -0
- package/dist/security/trust-directory-store.d.ts +233 -0
- package/dist/security/trust-policy-gate.d.ts +94 -59
- package/dist/security/trust-policy-store.d.ts +3 -0
- package/dist/security/trust-resolver.d.ts +14 -98
- package/dist/server.d.ts +11 -1
- package/dist/server.js +56329 -42234
- package/dist/stale-detector/gate-deadline-detector.d.ts +52 -0
- package/dist/stale-detector/stale-run-detector.d.ts +61 -3
- package/dist/standalone.js +37619 -23570
- package/dist/webhook/ingest-accept.d.ts +70 -0
- package/dist/webhook/ingest-overflow-buffer.d.ts +35 -4
- package/dist/webhook/ingest-overflow-replayer.d.ts +50 -6
- package/dist/worker/in-memory-job-queue.d.ts +1 -1
- package/dist/ws/agent-handler.d.ts +31 -4
- package/dist/ws/dashboard-context-handler.d.ts +28 -4
- package/dist/ws/dashboard-global-workflows-handler.d.ts +36 -9
- package/dist/ws/execution-status-frame.d.ts +32 -0
- package/dist/ws/failure-messages.d.ts +2 -0
- package/dist/ws/git-credential-relay.d.ts +39 -0
- package/dist/ws/oidc-token-relay.d.ts +6 -11
- package/dist/ws/platform-client.d.ts +68 -9
- package/dist/ws/test-relay-handlers.d.ts +35 -10
- package/installer-image-digests.json +3 -3
- package/package.json +24 -19
- package/sbom.spdx.json +868 -821
- package/dist/approvals/team-membership-lookup.d.ts +0 -13
- package/dist/pipeline/inline-eval.d.ts +0 -44
- package/dist/providers/github/contributor-resolver.d.ts +0 -30
- package/dist/security/contributor-cache.d.ts +0 -83
|
@@ -23,9 +23,9 @@ export interface ClusterIdentityDeps {
|
|
|
23
23
|
*/
|
|
24
24
|
storagePrefix?: string;
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
* returns early.
|
|
28
|
-
*
|
|
26
|
+
* Test-only escape hatch — when true, validateS3Sentinel logs a warning and
|
|
27
|
+
* returns early. Supplied only by the build-time test double's injected
|
|
28
|
+
* fault-injection policy; the shipped orchestrator always validates.
|
|
29
29
|
*/
|
|
30
30
|
skipSentinelValidation?: boolean;
|
|
31
31
|
}
|
|
@@ -1,9 +1,52 @@
|
|
|
1
1
|
import type { Kysely } from 'kysely';
|
|
2
2
|
import type { Database } from '../db/types.js';
|
|
3
3
|
/** Numeric columns on cluster_settings readable via {@link ClusterSettingsReader}. */
|
|
4
|
-
export type ClusterNumberColumn = 'max_github_payload_bytes' | 'event_log_max_payload_bytes' | 'lock_file_max_bytes' | 'webhook_dedup_ttl_ms'
|
|
4
|
+
export type ClusterNumberColumn = 'max_github_payload_bytes' | 'event_log_max_payload_bytes' | 'lock_file_max_bytes' | 'webhook_dedup_ttl_ms'
|
|
5
|
+
/** @deprecated Readable, but no call site reads it. Removed at v1.0.0. */
|
|
6
|
+
| 'contributor_cache_ttl_ms' | 'event_router_event_ttl_seconds' | 'event_router_max_dispatch_attempts' | 'queue_max_depth' | 'reroute_flap_grace_ms' | 'max_fanout_hosts' | 'event_router_rate_limit_per_workflow_per_minute' | 'cache_max_tarball_bytes' | 'cache_ttl_days' | 'lockfile_cache_max' | 'lockfile_cache_max_bytes' | 'lockfile_cache_ttl_ms' | 'content_cache_max' | 'content_cache_max_bytes' | 'content_cache_ttl_ms' | 'global_eval_round_timeout_ms' | 'global_eval_candidate_timeout_ms' | 'global_eval_cache_max' | 'global_eval_wait_timeout_ms' | 'check_run_tracking_ttl_days' | 'concurrency_wait_timeout_ms' | 'agent_token_ttl_ms' | 'ownership_db_check_timeout_ms' | 'unroutable_grace_ms' | 'ingest_overflow_claim_timeout_ms' | 'scaler_reap_interval_ms' | 'scaler_reap_stranded_timeout_ms' | 'scaler_reap_reattempt_interval_ms' | 'scaler_claim_retention_ms' | 'scaler_provision_backoff_base_ms' | 'scaler_provision_backoff_max_ms' | 'scaler_provision_max_consecutive_failures';
|
|
5
7
|
/** Text columns on cluster_settings readable via {@link ClusterSettingsReader}. */
|
|
6
8
|
export type ClusterStringColumn = 'dashboard_verified_issuer';
|
|
9
|
+
/** Boolean columns on cluster_settings readable via {@link ClusterSettingsReader}. */
|
|
10
|
+
export type ClusterBooleanColumn = 'global_workflows_enabled';
|
|
11
|
+
/**
|
|
12
|
+
* Ceiling for the three LRU entry-count knobs — `lockfile_cache_max`,
|
|
13
|
+
* `content_cache_max`, and `global_eval_cache_max`.
|
|
14
|
+
*
|
|
15
|
+
* This is a boot-safety bound, not a policy preference. The underlying LRU
|
|
16
|
+
* allocates its index arrays eagerly from `max` — several typed arrays plus the
|
|
17
|
+
* TTL and size arrays the caches ask for — so the cost is paid at construction
|
|
18
|
+
* with zero entries cached. Measured on the shipped version: an empty cache at
|
|
19
|
+
* `max` 5,000,000 costs ~191 MB, and at 5,000,000,000 the constructor throws
|
|
20
|
+
* `RangeError: Invalid array length`.
|
|
21
|
+
*
|
|
22
|
+
* That throw is what makes an unbounded knob dangerous rather than merely
|
|
23
|
+
* wasteful. All three caches are built inside `bootstrapOrchestrator`, so a bad
|
|
24
|
+
* stored value crashes the orchestrator before its admin API is listening —
|
|
25
|
+
* and the admin API is the only way `kici-admin cluster-settings` can reach the
|
|
26
|
+
* stored value. The knob would brick the very tool needed to un-brick it.
|
|
27
|
+
*
|
|
28
|
+
* 100,000 is 200x the shipped default of 500 and costs ~4 MB per empty cache,
|
|
29
|
+
* so it is far above any plausible operator setting while keeping boot bounded.
|
|
30
|
+
*/
|
|
31
|
+
export declare const CACHE_MAX_ENTRIES_CEILING = 100000;
|
|
32
|
+
/**
|
|
33
|
+
* Bound a stored entry-count knob to something the LRU constructor survives.
|
|
34
|
+
*
|
|
35
|
+
* Applied at the read site rather than only at the write site, because the
|
|
36
|
+
* write-side validation cannot reach a value that is already in the database —
|
|
37
|
+
* set before the ceiling shipped, or written by any path other than the admin
|
|
38
|
+
* route. Clamping here is what actually guarantees a stored value cannot
|
|
39
|
+
* prevent boot.
|
|
40
|
+
*
|
|
41
|
+
* A value that is not a usable positive count (NaN, non-finite, below 1) falls
|
|
42
|
+
* back to the configured default rather than clamping to 1: a 1-entry cache
|
|
43
|
+
* thrashes silently, which is harder to diagnose than simply ignoring garbage.
|
|
44
|
+
* The fallback is floored and bounded by the ceiling on the same path as the
|
|
45
|
+
* stored value, so neither a fractional nor an above-ceiling configured default
|
|
46
|
+
* can reach the LRU constructor as a non-integer or unclamped max — the
|
|
47
|
+
* constructor rejects both, and either would prevent boot.
|
|
48
|
+
*/
|
|
49
|
+
export declare function clampCacheMaxEntries(value: number, fallback: number): number;
|
|
7
50
|
/**
|
|
8
51
|
* A knob read that keeps "the operator never set this" separate from "we could
|
|
9
52
|
* not read it".
|
|
@@ -64,6 +107,21 @@ export declare class ClusterSettingsReader {
|
|
|
64
107
|
* An empty stored string is unset, matching {@link getString}.
|
|
65
108
|
*/
|
|
66
109
|
tryGetString(column: ClusterStringColumn): Promise<ClusterSettingRead<string>>;
|
|
110
|
+
/**
|
|
111
|
+
* Resolve a fleet-wide boolean knob without collapsing a read failure into a
|
|
112
|
+
* default.
|
|
113
|
+
*
|
|
114
|
+
* There is deliberately no `getBoolean(column, fallback)` companion. The
|
|
115
|
+
* security gate that consumes this must tell the reader's outcomes apart
|
|
116
|
+
* itself: a stored `false` and a NULL both deny today, but they deny for
|
|
117
|
+
* different reasons, and `{ ok: false }` must deny regardless of what the
|
|
118
|
+
* configured default happens to be. A convenience wrapper that folded the
|
|
119
|
+
* failure into the default would be safe only for as long as that default
|
|
120
|
+
* stayed `false`. A caller that only needs a display value (the dashboard
|
|
121
|
+
* status badge) folds `{ ok: false }` into the default explicitly at its own
|
|
122
|
+
* site, where getting it wrong misreports a badge rather than opening a gate.
|
|
123
|
+
*/
|
|
124
|
+
tryGetBoolean(column: ClusterBooleanColumn): Promise<ClusterSettingRead<boolean>>;
|
|
67
125
|
/**
|
|
68
126
|
* The cluster_settings row version last seen in the cache (0 if never loaded).
|
|
69
127
|
*
|
|
@@ -90,6 +90,8 @@ export interface RunCoordinatorDeps {
|
|
|
90
90
|
sendAndWaitAckViaHandler?: (targetInstanceId: string, msg: JobReroute, timeoutMs: number) => Promise<boolean>;
|
|
91
91
|
/** Fallback: send a message via server-side (incoming) peer connection (fire-and-forget). */
|
|
92
92
|
sendToPeerViaHandler?: (targetInstanceId: string, msg: PeerToPeerMessage) => boolean;
|
|
93
|
+
/** Close a peer's incoming socket by instanceId (used by worker eviction). */
|
|
94
|
+
closePeerViaHandler?: (targetInstanceId: string, code: number, reason: string) => void;
|
|
93
95
|
ackTimeoutMs?: number;
|
|
94
96
|
/** Stale peer timeout in ms. Default: 60000 (60s). */
|
|
95
97
|
staleTimeoutMs?: number;
|
|
@@ -137,7 +139,23 @@ export declare class RunCoordinator {
|
|
|
137
139
|
private readonly nakTracker;
|
|
138
140
|
/** Stale eviction timer handle. */
|
|
139
141
|
private staleEvictionTimer;
|
|
142
|
+
/** Plan-ceiling worker eviction (drain-then-disconnect). */
|
|
143
|
+
private readonly workerEviction;
|
|
144
|
+
/** Per-peer "no in-flight rerouted jobs" callbacks, fired by worker drain. */
|
|
145
|
+
private readonly evictionIdleCallbacks;
|
|
146
|
+
private readonly closePeerViaHandler?;
|
|
140
147
|
constructor(deps: RunCoordinatorDeps);
|
|
148
|
+
/** In-flight rerouted jobs currently attributed to a peer. */
|
|
149
|
+
private runningJobCountForPeer;
|
|
150
|
+
/** Fire a registered drain idle-callback once the peer has no in-flight jobs. */
|
|
151
|
+
private fireIdleIfDrained;
|
|
152
|
+
/**
|
|
153
|
+
* Reconcile this coordinator's workers against the pushed ceiling. Invoked on
|
|
154
|
+
* every `plan.headroom` frame: when `evictExcess` is set, the newest workers
|
|
155
|
+
* past `ceiling` are drained; otherwise any in-flight drain is cancelled and
|
|
156
|
+
* the worker restored, so a raised ceiling rescues it.
|
|
157
|
+
*/
|
|
158
|
+
reconcileWorkerEviction(ceiling: number, evictExcess: boolean): void;
|
|
141
159
|
/**
|
|
142
160
|
* Route jobs for a webhook run. Claims jobs that local agents can handle,
|
|
143
161
|
* reroutes the rest to peers with matching capacity.
|
|
@@ -268,6 +286,32 @@ export declare class RunCoordinator {
|
|
|
268
286
|
* its worker is connected.
|
|
269
287
|
*/
|
|
270
288
|
private trackReroutedJob;
|
|
289
|
+
/** Arm a spawn-window / reap timer that fires {@link handleRerouteSpawnTimeout}. */
|
|
290
|
+
private armRerouteWindow;
|
|
291
|
+
/**
|
|
292
|
+
* Whether the reroute target has actually started the job, read from the
|
|
293
|
+
* shared `execution_jobs` row.
|
|
294
|
+
*
|
|
295
|
+
* A read failure answers "not running" so a transient database fault cannot
|
|
296
|
+
* silently disable the backstop — the re-dispatch it then performs is the
|
|
297
|
+
* behavior that shipped before this check existed, and it is idempotent.
|
|
298
|
+
* Only the FIRST observation goes through this path: once `peerStarted`
|
|
299
|
+
* latches, a read fault can no longer bounce a running job.
|
|
300
|
+
*/
|
|
301
|
+
private rerouteTargetIsRunning;
|
|
302
|
+
/**
|
|
303
|
+
* The peer owns the job, so the backstop must not re-dispatch it. Release the
|
|
304
|
+
* tracking entry once the shared row is terminal, otherwise re-arm the window
|
|
305
|
+
* as a reap poll.
|
|
306
|
+
*
|
|
307
|
+
* The entry cannot simply be dropped here: cancel propagation still needs it
|
|
308
|
+
* while the job runs. It also cannot simply be kept, because a peer
|
|
309
|
+
* COORDINATOR relays no terminal `job.progress` — the shared row IS its
|
|
310
|
+
* report — so nothing else would ever release it and `reroutedJobs` would
|
|
311
|
+
* grow for the lifetime of the process. A read fault re-arms (never releases),
|
|
312
|
+
* so a transient fault costs one more poll rather than tracking.
|
|
313
|
+
*/
|
|
314
|
+
private reapOrDeferRerouteTracking;
|
|
271
315
|
/**
|
|
272
316
|
* Post-ACK spawn-window backstop. Fires when a rerouted job's peer accepted
|
|
273
317
|
* but produced no progress within the window (Layer A), or immediately when a
|
package/dist/cluster/index.d.ts
CHANGED
|
@@ -21,6 +21,10 @@ export type { RaftPersistentState } from './raft-state.js';
|
|
|
21
21
|
export { OrphanRecovery } from './orphan-recovery.js';
|
|
22
22
|
export { RunCoordinator } from './coordinator.js';
|
|
23
23
|
export type { RunContext, JobToRoute, RouteResult } from './coordinator.js';
|
|
24
|
+
export { PlanHeadroomStore } from './plan-headroom-store.js';
|
|
25
|
+
export type { StoredPlanHeadroom } from './plan-headroom-store.js';
|
|
26
|
+
export { WorkerEviction, selectEvictionTargets, WORKER_DRAIN_TIMEOUT_MS, } from './worker-eviction.js';
|
|
27
|
+
export type { EvictionHooks } from './worker-eviction.js';
|
|
24
28
|
export { createClusterHealthRoutes } from './health-api.js';
|
|
25
29
|
export type { ClusterHealthRoutesDeps } from './health-api.js';
|
|
26
30
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -33,6 +33,14 @@ export interface PeerHandlerDeps {
|
|
|
33
33
|
peerRegistry: PeerRegistry;
|
|
34
34
|
/** Callback to get this orchestrator's local agent inventory for heartbeats. */
|
|
35
35
|
getLocalInventory: () => Omit<PeerHeartbeat, 'type'>;
|
|
36
|
+
/**
|
|
37
|
+
* The Platform-pushed worker ceiling this coordinator enforces, or `null`
|
|
38
|
+
* when none was ever received (admit worker joins freely). Read at each
|
|
39
|
+
* worker-peer admission. Served from the persisted PlanHeadroomStore, so it
|
|
40
|
+
* survives a Platform disconnect — the coordinator keeps enforcing the last
|
|
41
|
+
* known ceiling rather than resetting to unlimited.
|
|
42
|
+
*/
|
|
43
|
+
getWorkerCeiling?: () => Promise<number | null>;
|
|
36
44
|
/** Heartbeat interval in ms. Default: 30000 (30s). */
|
|
37
45
|
heartbeatIntervalMs?: number;
|
|
38
46
|
/** Auth timeout in ms. Default: 15000 (15s). */
|
|
@@ -103,9 +111,20 @@ export interface PeerHandlerDeps {
|
|
|
103
111
|
* Returns `handleConnection(ws, remoteIp?)` which should be called when a new
|
|
104
112
|
* WebSocket connection is upgraded on the peer endpoint.
|
|
105
113
|
*/
|
|
114
|
+
/**
|
|
115
|
+
* Whether a joining peer may be admitted against the plan ceiling.
|
|
116
|
+
*
|
|
117
|
+
* Only workers are gated: a coordinator peer holds its own Platform connection
|
|
118
|
+
* and is counted there, and a peer advertising no role registers as a
|
|
119
|
+
* coordinator (see PeerRegistry.addPeer), so neither is gated here. A `null`
|
|
120
|
+
* ceiling — none ever received — admits freely. The ceiling is ABSOLUTE, so the
|
|
121
|
+
* join is admitted only while the currently-connected worker count is below it.
|
|
122
|
+
*/
|
|
123
|
+
export declare function shouldAdmitWorker(role: string | undefined, ceiling: number | null, connectedWorkerCount: number): boolean;
|
|
106
124
|
export declare function createPeerHandler(deps: PeerHandlerDeps): {
|
|
107
125
|
handleConnection: (ws: PeerWsLike, remoteIp?: string) => void;
|
|
108
126
|
sendToPeer: (targetInstanceId: string, msg: PeerToPeerMessage) => boolean;
|
|
127
|
+
closePeer: (targetInstanceId: string, code: number, reason: string) => void;
|
|
109
128
|
sendAndWaitAck: (targetInstanceId: string, msg: JobReroute, timeoutMs?: number) => Promise<boolean>;
|
|
110
129
|
sendConfigReloadAndWait: (targetInstanceId: string, msg: PeerConfigReload, timeoutMs?: number) => Promise<PeerConfigReloadResponse | null>;
|
|
111
130
|
sendLogsCollectAndWait: (targetInstanceId: string, msg: PeerLogsCollectRequest, timeoutMs: number) => Promise<Buffer>;
|
|
@@ -35,6 +35,8 @@ export interface PeerInfo {
|
|
|
35
35
|
routingKeys: string[];
|
|
36
36
|
connected: boolean;
|
|
37
37
|
lastHeartbeatAt: number;
|
|
38
|
+
/** When this peer first connected. Distinct from `lastHeartbeatAt`, which moves; this does not. */
|
|
39
|
+
connectedAt: number;
|
|
38
40
|
agents: PeerAgentInfo[];
|
|
39
41
|
draining: boolean;
|
|
40
42
|
capabilities: PeerCapabilities;
|
|
@@ -71,6 +73,12 @@ export interface PeerRegistryOptions {
|
|
|
71
73
|
onClusterSettingsVersionBehind?: (peerVersion: number) => void;
|
|
72
74
|
/** Called when a peer transitions to disconnected state. */
|
|
73
75
|
onPeerDisconnected?: (instanceId: string) => void;
|
|
76
|
+
/**
|
|
77
|
+
* Called when the connected-peer set changes (a fresh add or a
|
|
78
|
+
* markDisconnected), so a coordinator can re-report its `cluster.membership`
|
|
79
|
+
* snapshot to the Platform without waiting for the periodic interval.
|
|
80
|
+
*/
|
|
81
|
+
onMembershipChange?: () => void;
|
|
74
82
|
}
|
|
75
83
|
export declare class PeerRegistry {
|
|
76
84
|
private readonly peers;
|
|
@@ -81,6 +89,7 @@ export declare class PeerRegistry {
|
|
|
81
89
|
private readonly onRegistryVersionBehind?;
|
|
82
90
|
private readonly onClusterSettingsVersionBehind?;
|
|
83
91
|
private readonly onPeerDisconnected?;
|
|
92
|
+
private readonly onMembershipChange?;
|
|
84
93
|
constructor(options?: PeerRegistryOptions);
|
|
85
94
|
/**
|
|
86
95
|
* Update the local config version for comparison with peer heartbeats.
|
|
@@ -196,6 +205,14 @@ export declare class PeerRegistry {
|
|
|
196
205
|
* Get all peers with role=worker.
|
|
197
206
|
*/
|
|
198
207
|
getWorkerPeers(): PeerInfo[];
|
|
208
|
+
/**
|
|
209
|
+
* Currently-connected worker peers.
|
|
210
|
+
*
|
|
211
|
+
* A peer that advertises no role registers as a coordinator (see `addPeer`),
|
|
212
|
+
* so a worker predating the role field is not counted here. That under-counts,
|
|
213
|
+
* which errs permissive, and it self-heals as workers upgrade.
|
|
214
|
+
*/
|
|
215
|
+
getConnectedWorkerPeers(): PeerInfo[];
|
|
199
216
|
/**
|
|
200
217
|
* Get all peers with role=coordinator.
|
|
201
218
|
*/
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import type { PlanHeadroom } from '@kici-dev/engine';
|
|
3
|
+
import type { Database } from '../db/types.js';
|
|
4
|
+
/** The ceiling as last pushed by the Platform. */
|
|
5
|
+
export interface StoredPlanHeadroom {
|
|
6
|
+
maxWorkerPeers: number;
|
|
7
|
+
orgLimit: number;
|
|
8
|
+
orgTotal: number;
|
|
9
|
+
evictExcess: boolean;
|
|
10
|
+
updatedAt: Date;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The orchestrator's cache of the Platform-owned worker ceiling.
|
|
14
|
+
*
|
|
15
|
+
* Persisted so a coordinator restarting during a Platform outage keeps
|
|
16
|
+
* enforcing the last known ceiling instead of resetting to unlimited. Same
|
|
17
|
+
* ownership shape as `org_trust_policy`: the Platform writes it, the
|
|
18
|
+
* orchestrator only reads it back.
|
|
19
|
+
*/
|
|
20
|
+
export declare class PlanHeadroomStore {
|
|
21
|
+
private readonly db;
|
|
22
|
+
constructor(db: Kysely<Database>);
|
|
23
|
+
read(): Promise<StoredPlanHeadroom | null>;
|
|
24
|
+
write(headroom: PlanHeadroom): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=plan-headroom-store.d.ts.map
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { PeerInfo, PeerRegistry } from './peer-registry.js';
|
|
2
|
+
/** How long a draining worker may hold in-flight jobs before it is disconnected anyway. */
|
|
3
|
+
export declare const WORKER_DRAIN_TIMEOUT_MS: number;
|
|
4
|
+
/**
|
|
5
|
+
* The coordinator-side operations eviction needs.
|
|
6
|
+
*
|
|
7
|
+
* Declared here rather than reached for on the coordinator directly: the
|
|
8
|
+
* coordinator owns dispatch and job attribution, but exposes no ineligibility
|
|
9
|
+
* or idle-notification surface, and widening its public API for one caller
|
|
10
|
+
* would couple eviction to it. A fake implementation makes this class unit
|
|
11
|
+
* testable without a running cluster.
|
|
12
|
+
*/
|
|
13
|
+
export interface EvictionHooks {
|
|
14
|
+
/** Stop rerouting new jobs to this peer. */
|
|
15
|
+
markIneligible(instanceId: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* Restore this peer to dispatch eligibility and drop any idle-notification
|
|
18
|
+
* registration. Called when a drain is cancelled (the ceiling rose so the
|
|
19
|
+
* peer is no longer excess) and after a drained peer is disconnected, so a
|
|
20
|
+
* later re-admission of the same instance starts dispatch-eligible.
|
|
21
|
+
*/
|
|
22
|
+
clearIneligible(instanceId: string): void;
|
|
23
|
+
/** In-flight rerouted jobs currently attributed to this peer. */
|
|
24
|
+
runningJobCount(instanceId: string): number;
|
|
25
|
+
/** Invoke the callback once this peer has no in-flight rerouted jobs. */
|
|
26
|
+
onPeerIdle(instanceId: string, callback: () => void): void;
|
|
27
|
+
/** Close this peer's connection with the given code and reason. */
|
|
28
|
+
closePeer(instanceId: string, code: number, reason: string): void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The workers to drain to bring this coordinator down to its ceiling.
|
|
32
|
+
*
|
|
33
|
+
* Newest-first by connect time: the joins that crossed the line are the ones
|
|
34
|
+
* that go, so long-running capacity is not shuffled arbitrarily.
|
|
35
|
+
*/
|
|
36
|
+
export declare function selectEvictionTargets(workers: readonly PeerInfo[], ceiling: number): PeerInfo[];
|
|
37
|
+
/**
|
|
38
|
+
* Drain-then-disconnect this coordinator's excess workers.
|
|
39
|
+
*
|
|
40
|
+
* A target is first marked ineligible for new dispatch, then closed once its
|
|
41
|
+
* in-flight rerouted jobs reach terminal status — which the worker's durable
|
|
42
|
+
* outbox and `job.progress.ack` already guarantee — or after
|
|
43
|
+
* `WORKER_DRAIN_TIMEOUT_MS`, after which the coordinator's existing
|
|
44
|
+
* orphan-recovery guard handles whatever remains.
|
|
45
|
+
*/
|
|
46
|
+
export declare class WorkerEviction {
|
|
47
|
+
private readonly peerRegistry;
|
|
48
|
+
private readonly hooks;
|
|
49
|
+
private readonly logger;
|
|
50
|
+
private readonly draining;
|
|
51
|
+
constructor(peerRegistry: PeerRegistry, hooks: EvictionHooks, logger: {
|
|
52
|
+
warn: (msg: string, meta?: unknown) => void;
|
|
53
|
+
});
|
|
54
|
+
/**
|
|
55
|
+
* Reconcile the connected worker set against the ceiling.
|
|
56
|
+
*
|
|
57
|
+
* When `evictExcess` is true, drain the newest workers past `ceiling`;
|
|
58
|
+
* otherwise the target set is empty. Any drain in flight for a worker that is
|
|
59
|
+
* no longer a target is CANCELLED — its timer cleared and its dispatch
|
|
60
|
+
* eligibility restored — so a raised ceiling (or the Platform clearing
|
|
61
|
+
* `evictExcess` once the org drops back under) rescues a worker instead of
|
|
62
|
+
* disconnecting it at the drain timeout.
|
|
63
|
+
*/
|
|
64
|
+
reconcile(ceiling: number, evictExcess: boolean): void;
|
|
65
|
+
/** Stop an in-flight drain and restore the worker to dispatch eligibility. */
|
|
66
|
+
private cancelDrain;
|
|
67
|
+
private startDrain;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=worker-eviction.d.ts.map
|
|
@@ -13,10 +13,17 @@
|
|
|
13
13
|
* dashboard's payload-detail view continues to resolve archived
|
|
14
14
|
* deliveries identically to hot ones.
|
|
15
15
|
*/
|
|
16
|
-
import { type Kysely
|
|
16
|
+
import { type Kysely } from 'kysely';
|
|
17
17
|
import { type ColdStore } from '@kici-dev/shared';
|
|
18
|
-
import type { Database
|
|
19
|
-
|
|
18
|
+
import type { Database } from '../db/types.js';
|
|
19
|
+
import type { EventLogColdStoreRow } from './tables/event-log.js';
|
|
20
|
+
/**
|
|
21
|
+
* Re-exported, not re-declared: the alias is defined beside the cold-store
|
|
22
|
+
* adapter that owns the table, and a second identical declaration here is what
|
|
23
|
+
* a homonym sweep flags. Kept as an export so this module's public surface is
|
|
24
|
+
* unchanged for its consumers.
|
|
25
|
+
*/
|
|
26
|
+
export type { EventLogColdStoreRow };
|
|
20
27
|
export interface LoadOrchEventLogRangeArgs {
|
|
21
28
|
db: Kysely<Database>;
|
|
22
29
|
coldStore: ColdStore | undefined;
|
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
* rows after streaming. This is correct because cold chunks are
|
|
16
16
|
* partitioned by `(routing_key, day)`, not by the secondary filters.
|
|
17
17
|
*/
|
|
18
|
-
import { type Kysely
|
|
18
|
+
import { type Kysely } from 'kysely';
|
|
19
19
|
import { type ColdStore } from '@kici-dev/shared';
|
|
20
|
-
import type { Database,
|
|
21
|
-
|
|
20
|
+
import type { Database, SecretAuditLogRow } from '../db/types.js';
|
|
21
|
+
/** Re-exported rather than re-declared — see the note in `load-event-log-range`. */
|
|
22
|
+
export type { SecretAuditLogRow };
|
|
22
23
|
export interface LoadSecretAuditLogRangeArgs {
|
|
23
24
|
db: Kysely<Database>;
|
|
24
25
|
coldStore: ColdStore | undefined;
|
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
* synthetic prefix `__orchestrator__`. Mirrors the same pattern already
|
|
14
14
|
* used for `event_log` payload keys when the routing key is missing.
|
|
15
15
|
*/
|
|
16
|
-
import { type Kysely
|
|
16
|
+
import { type Kysely } from 'kysely';
|
|
17
17
|
import { type ChunkCommitMetadata, type ColdRetention, type ColdStoreTableConfig, type EligiblePartition, type TableAdapter } from '@kici-dev/shared';
|
|
18
|
-
import type { Database,
|
|
19
|
-
|
|
18
|
+
import type { Database, SecretAuditLogRow } from '../../db/types.js';
|
|
19
|
+
/** Re-exported rather than re-declared — see the note in `load-event-log-range`. */
|
|
20
|
+
export type { SecretAuditLogRow };
|
|
20
21
|
export interface SecretAuditLogAdapterOptions {
|
|
21
22
|
overrides?: Partial<ColdStoreTableConfig>;
|
|
22
23
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -56,9 +56,17 @@ declare const configSchema: z.ZodObject<{
|
|
|
56
56
|
lockfileCacheMax: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
57
57
|
lockfileCacheTtlMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
58
58
|
lockfileCacheMaxBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
59
|
+
contentCacheMax: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
60
|
+
contentCacheTtlMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
61
|
+
contentCacheMaxBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
62
|
+
globalEvalRoundTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
63
|
+
globalEvalCandidateTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
64
|
+
globalEvalCacheMax: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
65
|
+
globalEvalWaitTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
59
66
|
queueMaxDepth: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
60
67
|
queueTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
61
68
|
unroutableGraceMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
69
|
+
globalWorkflowsEnabled: z.ZodPipe<z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>, z.ZodTransform<boolean, string | boolean>>;
|
|
62
70
|
queueBackpressureThreshold: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
63
71
|
workerConcurrency: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
64
72
|
concurrencyWaitTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
@@ -81,6 +89,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
81
89
|
ingestOverflowReplayIntervalMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
82
90
|
ingestOverflowReplayBatch: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
83
91
|
ingestOverflowMaxAttempts: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
92
|
+
ingestOverflowClaimTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
84
93
|
rerouteSpawnWindowMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
85
94
|
rerouteAckTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
86
95
|
rerouteMaxHops: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
@@ -88,6 +97,13 @@ declare const configSchema: z.ZodObject<{
|
|
|
88
97
|
scalerSpawnTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
89
98
|
backupStalenessWarnHours: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
90
99
|
scalerPendingSweepIntervalMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
100
|
+
scalerReapIntervalMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
101
|
+
scalerReapStrandedTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
102
|
+
scalerReapReattemptIntervalMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
103
|
+
scalerClaimRetentionMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
104
|
+
scalerProvisionBackoffBaseMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
105
|
+
scalerProvisionBackoffMaxMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
106
|
+
scalerProvisionMaxConsecutiveFailures: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
91
107
|
cacheStorageType: z.ZodOptional<z.ZodEnum<{
|
|
92
108
|
filesystem: "filesystem";
|
|
93
109
|
s3: "s3";
|
|
@@ -168,12 +184,6 @@ declare const configSchema: z.ZodObject<{
|
|
|
168
184
|
eventRouterRetryBaseBackoffMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
169
185
|
eventRouterRetryMaxBackoffMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
170
186
|
eventRouterRetryScanIntervalMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
171
|
-
testMode: z.ZodPipe<z.ZodDefault<z.ZodString>, z.ZodTransform<boolean, string>>;
|
|
172
|
-
testEventFailFirstN: z.ZodOptional<z.ZodString>;
|
|
173
|
-
testMintDeferAudience: z.ZodOptional<z.ZodString>;
|
|
174
|
-
testMintRejectAudience: z.ZodOptional<z.ZodString>;
|
|
175
|
-
testRerunDelayMs: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
176
|
-
testOmitDashboardRequestTypes: z.ZodOptional<z.ZodString>;
|
|
177
187
|
eventLogMaxPayloadBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
178
188
|
maxGithubPayloadBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
179
189
|
lockFileMaxBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
@@ -193,7 +203,6 @@ declare const configSchema: z.ZodObject<{
|
|
|
193
203
|
}>>;
|
|
194
204
|
autoMigrate: z.ZodPipe<z.ZodDefault<z.ZodString>, z.ZodTransform<boolean, string>>;
|
|
195
205
|
agentMaxReconnectDelayMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
196
|
-
skipS3SentinelValidation: z.ZodPipe<z.ZodDefault<z.ZodString>, z.ZodTransform<boolean, string>>;
|
|
197
206
|
otelExporterOtlpEndpoint: z.ZodOptional<z.ZodString>;
|
|
198
207
|
clusterName: z.ZodOptional<z.ZodString>;
|
|
199
208
|
cluster: z.ZodPrefault<z.ZodObject<{
|
|
@@ -250,9 +259,17 @@ export declare const packagingConfigSchema: z.ZodObject<{
|
|
|
250
259
|
lockfileCacheMax: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
251
260
|
lockfileCacheTtlMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
252
261
|
lockfileCacheMaxBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
262
|
+
contentCacheMax: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
263
|
+
contentCacheTtlMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
264
|
+
contentCacheMaxBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
265
|
+
globalEvalRoundTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
266
|
+
globalEvalCandidateTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
267
|
+
globalEvalCacheMax: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
268
|
+
globalEvalWaitTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
253
269
|
queueMaxDepth: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
254
270
|
queueTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
255
271
|
unroutableGraceMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
272
|
+
globalWorkflowsEnabled: z.ZodPipe<z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>, z.ZodTransform<boolean, string | boolean>>;
|
|
256
273
|
queueBackpressureThreshold: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
257
274
|
workerConcurrency: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
258
275
|
concurrencyWaitTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
@@ -275,6 +292,7 @@ export declare const packagingConfigSchema: z.ZodObject<{
|
|
|
275
292
|
ingestOverflowReplayIntervalMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
276
293
|
ingestOverflowReplayBatch: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
277
294
|
ingestOverflowMaxAttempts: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
295
|
+
ingestOverflowClaimTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
278
296
|
rerouteSpawnWindowMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
279
297
|
rerouteAckTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
280
298
|
rerouteMaxHops: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
@@ -282,6 +300,13 @@ export declare const packagingConfigSchema: z.ZodObject<{
|
|
|
282
300
|
scalerSpawnTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
283
301
|
backupStalenessWarnHours: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
284
302
|
scalerPendingSweepIntervalMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
303
|
+
scalerReapIntervalMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
304
|
+
scalerReapStrandedTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
305
|
+
scalerReapReattemptIntervalMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
306
|
+
scalerClaimRetentionMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
307
|
+
scalerProvisionBackoffBaseMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
308
|
+
scalerProvisionBackoffMaxMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
309
|
+
scalerProvisionMaxConsecutiveFailures: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
285
310
|
cacheStorageType: z.ZodOptional<z.ZodEnum<{
|
|
286
311
|
filesystem: "filesystem";
|
|
287
312
|
s3: "s3";
|
|
@@ -362,12 +387,6 @@ export declare const packagingConfigSchema: z.ZodObject<{
|
|
|
362
387
|
eventRouterRetryBaseBackoffMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
363
388
|
eventRouterRetryMaxBackoffMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
364
389
|
eventRouterRetryScanIntervalMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
365
|
-
testMode: z.ZodPipe<z.ZodDefault<z.ZodString>, z.ZodTransform<boolean, string>>;
|
|
366
|
-
testEventFailFirstN: z.ZodOptional<z.ZodString>;
|
|
367
|
-
testMintDeferAudience: z.ZodOptional<z.ZodString>;
|
|
368
|
-
testMintRejectAudience: z.ZodOptional<z.ZodString>;
|
|
369
|
-
testRerunDelayMs: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
370
|
-
testOmitDashboardRequestTypes: z.ZodOptional<z.ZodString>;
|
|
371
390
|
eventLogMaxPayloadBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
372
391
|
maxGithubPayloadBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
373
392
|
lockFileMaxBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
@@ -387,7 +406,6 @@ export declare const packagingConfigSchema: z.ZodObject<{
|
|
|
387
406
|
}>>;
|
|
388
407
|
autoMigrate: z.ZodPipe<z.ZodDefault<z.ZodString>, z.ZodTransform<boolean, string>>;
|
|
389
408
|
agentMaxReconnectDelayMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
390
|
-
skipS3SentinelValidation: z.ZodPipe<z.ZodDefault<z.ZodString>, z.ZodTransform<boolean, string>>;
|
|
391
409
|
otelExporterOtlpEndpoint: z.ZodOptional<z.ZodString>;
|
|
392
410
|
clusterName: z.ZodOptional<z.ZodString>;
|
|
393
411
|
cluster: z.ZodPrefault<z.ZodObject<{
|
|
@@ -477,9 +495,17 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
|
|
|
477
495
|
lockfileCacheMax: number;
|
|
478
496
|
lockfileCacheTtlMs: number;
|
|
479
497
|
lockfileCacheMaxBytes: number;
|
|
498
|
+
contentCacheMax: number;
|
|
499
|
+
contentCacheTtlMs: number;
|
|
500
|
+
contentCacheMaxBytes: number;
|
|
501
|
+
globalEvalRoundTimeoutMs: number;
|
|
502
|
+
globalEvalCandidateTimeoutMs: number;
|
|
503
|
+
globalEvalCacheMax: number;
|
|
504
|
+
globalEvalWaitTimeoutMs: number;
|
|
480
505
|
queueMaxDepth: number;
|
|
481
506
|
queueTimeoutMs: number;
|
|
482
507
|
unroutableGraceMs: number;
|
|
508
|
+
globalWorkflowsEnabled: boolean;
|
|
483
509
|
queueBackpressureThreshold: number;
|
|
484
510
|
workerConcurrency: number;
|
|
485
511
|
concurrencyWaitTimeoutMs: number;
|
|
@@ -499,6 +525,7 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
|
|
|
499
525
|
ingestOverflowReplayIntervalMs: number;
|
|
500
526
|
ingestOverflowReplayBatch: number;
|
|
501
527
|
ingestOverflowMaxAttempts: number;
|
|
528
|
+
ingestOverflowClaimTimeoutMs: number;
|
|
502
529
|
rerouteSpawnWindowMs: number;
|
|
503
530
|
rerouteAckTimeoutMs: number;
|
|
504
531
|
rerouteMaxHops: number;
|
|
@@ -506,6 +533,13 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
|
|
|
506
533
|
scalerSpawnTimeoutMs: number;
|
|
507
534
|
backupStalenessWarnHours: number;
|
|
508
535
|
scalerPendingSweepIntervalMs: number;
|
|
536
|
+
scalerReapIntervalMs: number;
|
|
537
|
+
scalerReapStrandedTimeoutMs: number;
|
|
538
|
+
scalerReapReattemptIntervalMs: number;
|
|
539
|
+
scalerClaimRetentionMs: number;
|
|
540
|
+
scalerProvisionBackoffBaseMs: number;
|
|
541
|
+
scalerProvisionBackoffMaxMs: number;
|
|
542
|
+
scalerProvisionMaxConsecutiveFailures: number;
|
|
509
543
|
cacheStorageType?: "filesystem" | "s3" | undefined;
|
|
510
544
|
cacheStoragePath?: string | undefined;
|
|
511
545
|
cacheStorageS3Bucket?: string | undefined;
|
|
@@ -568,12 +602,6 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
|
|
|
568
602
|
eventRouterRetryBaseBackoffMs: number;
|
|
569
603
|
eventRouterRetryMaxBackoffMs: number;
|
|
570
604
|
eventRouterRetryScanIntervalMs: number;
|
|
571
|
-
testMode: boolean;
|
|
572
|
-
testEventFailFirstN?: string | undefined;
|
|
573
|
-
testMintDeferAudience?: string | undefined;
|
|
574
|
-
testMintRejectAudience?: string | undefined;
|
|
575
|
-
testRerunDelayMs?: number | undefined;
|
|
576
|
-
testOmitDashboardRequestTypes?: string | undefined;
|
|
577
605
|
eventLogMaxPayloadBytes: number;
|
|
578
606
|
maxGithubPayloadBytes: number;
|
|
579
607
|
lockFileMaxBytes: number;
|
|
@@ -584,7 +612,6 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
|
|
|
584
612
|
nodeEnv: "development" | "production" | "test";
|
|
585
613
|
autoMigrate: boolean;
|
|
586
614
|
agentMaxReconnectDelayMs: number;
|
|
587
|
-
skipS3SentinelValidation: boolean;
|
|
588
615
|
otelExporterOtlpEndpoint?: string | undefined;
|
|
589
616
|
clusterName?: string | undefined;
|
|
590
617
|
cluster: {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider-agnostic LRU cache for source-file contents fetched at a ref.
|
|
3
|
+
*
|
|
4
|
+
* Wraps any {@link FileContentsFetcher} with an in-memory LRU cache keyed by
|
|
5
|
+
* `(provider, repo, sha, path)`. The key is content-addressable by
|
|
6
|
+
* construction: a commit SHA pins immutable bytes, so a cached entry for a
|
|
7
|
+
* `(repo, sha, path)` triple can never go stale within the SHA. When the caller
|
|
8
|
+
* passes a mutable ref (a branch name) instead of a SHA, staleness is bounded by
|
|
9
|
+
* the TTL, exactly as the lock-file cache handles the same case.
|
|
10
|
+
*
|
|
11
|
+
* Mirrors {@link ../lockfile-cache.ts LockFileCache}: same LRU + in-flight
|
|
12
|
+
* coalescing shape so N concurrent misses for one key run a single fetch.
|
|
13
|
+
*/
|
|
14
|
+
import type { FileContentsFetcher } from '@kici-dev/engine';
|
|
15
|
+
/**
|
|
16
|
+
* One fetched file's presence + bytes. `present: true` with `bytes: undefined`
|
|
17
|
+
* is the size-limit case (the file exists but the provider returned no inline
|
|
18
|
+
* content, e.g. a GitHub file over 1 MiB) — callers MUST treat it as
|
|
19
|
+
* "content unavailable for matching", never as an absent or empty file.
|
|
20
|
+
*/
|
|
21
|
+
export interface FileContentEntry {
|
|
22
|
+
readonly present: boolean;
|
|
23
|
+
readonly bytes?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare class ContentRequirementsCache {
|
|
26
|
+
private readonly cache;
|
|
27
|
+
private readonly inFlight;
|
|
28
|
+
private hits;
|
|
29
|
+
private misses;
|
|
30
|
+
constructor(options: {
|
|
31
|
+
max: number;
|
|
32
|
+
ttl: number;
|
|
33
|
+
maxBytes?: number;
|
|
34
|
+
});
|
|
35
|
+
/**
|
|
36
|
+
* Fetch a file's contents at a ref, using the provided fetcher and LRU
|
|
37
|
+
* caching. Each distinct `(provider, repo, sha, path)` is fetched at most
|
|
38
|
+
* once; concurrent misses coalesce onto one fetch.
|
|
39
|
+
*
|
|
40
|
+
* @param fetcher - Provider-specific file-contents fetcher.
|
|
41
|
+
* @param repo - Provider repo identifier ("owner/repo").
|
|
42
|
+
* @param sha - Git ref (commit SHA, or a branch/tag name).
|
|
43
|
+
* @param path - Repo-relative file path.
|
|
44
|
+
*/
|
|
45
|
+
get(fetcher: FileContentsFetcher, repo: string, sha: string, path: string): Promise<FileContentEntry>;
|
|
46
|
+
private fetchAndCache;
|
|
47
|
+
/** Cache statistics for metrics/monitoring. */
|
|
48
|
+
getStats(): {
|
|
49
|
+
hits: number;
|
|
50
|
+
misses: number;
|
|
51
|
+
size: number;
|
|
52
|
+
calculatedSize: number;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=content-requirements-cache.d.ts.map
|