@stacksjs/ts-cloud 0.7.67 → 0.7.69
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/bin/cli.js +1126 -1126
- package/dist/{chunk-n59was4s.js → chunk-j6zaxywt.js} +31 -11
- package/dist/deploy/index.js +2 -2
- package/dist/drivers/hetzner/host-optimization.d.ts +19 -0
- package/dist/drivers/index.js +1 -1
- package/dist/index.js +2 -2
- package/dist/queue/queue.d.ts +8 -0
- package/dist/queue/worker.d.ts +2 -0
- package/dist/ui/account/automation.html +3 -3
- package/dist/ui/account/security.html +2 -2
- package/dist/ui/applications/compose.html +4 -4
- package/dist/ui/applications/new.html +2 -2
- package/dist/ui/data/backups.html +4 -4
- package/dist/ui/data/services.html +4 -4
- package/dist/ui/data/volumes.html +4 -4
- package/dist/ui/index.html +4 -4
- package/dist/ui/integrations.html +2 -2
- package/dist/ui/operations/alerts.html +4 -4
- package/dist/ui/operations/configuration.html +4 -4
- package/dist/ui/operations/jobs.html +4 -4
- package/dist/ui/operations/maintenance.html +4 -4
- package/dist/ui/operations/observability.html +4 -4
- package/dist/ui/operations/previews.html +4 -4
- package/dist/ui/operations/queue.html +4 -4
- package/dist/ui/operations/regions.html +4 -4
- package/dist/ui/operations/releases.html +4 -4
- package/dist/ui/operations/workloads.html +4 -4
- package/dist/ui/server/actions.html +4 -4
- package/dist/ui/server/activity.html +2 -2
- package/dist/ui/server/capacity.html +4 -4
- package/dist/ui/server/database.html +4 -4
- package/dist/ui/server/deployments.html +4 -4
- package/dist/ui/server/diagnostics.html +2 -2
- package/dist/ui/server/firewall.html +3 -3
- package/dist/ui/server/fleet.html +4 -4
- package/dist/ui/server/logs.html +4 -4
- package/dist/ui/server/metrics.html +4 -4
- package/dist/ui/server/services.html +2 -2
- package/dist/ui/server/sites.html +4 -4
- package/dist/ui/server/ssh-keys.html +3 -3
- package/dist/ui/server/team.html +4 -4
- package/dist/ui/server/terminal.html +2 -2
- package/dist/ui/serverless/alarms.html +4 -4
- package/dist/ui/serverless/assets.html +2 -2
- package/dist/ui/serverless/cost.html +2 -2
- package/dist/ui/serverless/data.html +4 -4
- package/dist/ui/serverless/firewall.html +2 -2
- package/dist/ui/serverless/functions.html +4 -4
- package/dist/ui/serverless/logs.html +4 -4
- package/dist/ui/serverless/metrics.html +2 -2
- package/dist/ui/serverless/queues.html +4 -4
- package/dist/ui/serverless/secrets.html +4 -4
- package/dist/ui/serverless/traces.html +4 -4
- package/dist/ui/serverless.html +4 -4
- package/package.json +3 -3
- /package/dist/{chunk-xawdhj7z.js → chunk-1p8jah5z.js} +0 -0
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
resolveSiteKind,
|
|
46
46
|
resolveUiSource,
|
|
47
47
|
siteInstallBase
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-1p8jah5z.js";
|
|
49
49
|
import {
|
|
50
50
|
artifactKey,
|
|
51
51
|
buildCloudFormationTemplate,
|
|
@@ -3435,6 +3435,7 @@ class DurableOperationQueue {
|
|
|
3435
3435
|
idFn;
|
|
3436
3436
|
workerId;
|
|
3437
3437
|
leaseMs;
|
|
3438
|
+
availabilityListeners = new Set;
|
|
3438
3439
|
limits;
|
|
3439
3440
|
constructor(controlPlane, options = {}) {
|
|
3440
3441
|
this.controlPlane = controlPlane;
|
|
@@ -3484,7 +3485,17 @@ class DurableOperationQueue {
|
|
|
3484
3485
|
now
|
|
3485
3486
|
]);
|
|
3486
3487
|
this.appendLog(operation.id, "Queued for durable execution.", { stream: "system" });
|
|
3487
|
-
|
|
3488
|
+
const view = this.view(operation.id);
|
|
3489
|
+
this.notifyAvailable();
|
|
3490
|
+
return view;
|
|
3491
|
+
}
|
|
3492
|
+
onAvailable(listener) {
|
|
3493
|
+
this.availabilityListeners.add(listener);
|
|
3494
|
+
return () => this.availabilityListeners.delete(listener);
|
|
3495
|
+
}
|
|
3496
|
+
notifyAvailable() {
|
|
3497
|
+
for (const listener of this.availabilityListeners)
|
|
3498
|
+
listener();
|
|
3488
3499
|
}
|
|
3489
3500
|
getJob(operationId) {
|
|
3490
3501
|
const row = this.controlPlane.database.query("SELECT * FROM operation_jobs WHERE operation_id=?").get(operationId);
|
|
@@ -3497,7 +3508,7 @@ class DurableOperationQueue {
|
|
|
3497
3508
|
return;
|
|
3498
3509
|
let approximatePosition;
|
|
3499
3510
|
if (operation.state === "queued") {
|
|
3500
|
-
const ahead = Number(this.controlPlane.database.query(
|
|
3511
|
+
const ahead = Number(this.controlPlane.database.query(`SELECT COUNT(*) AS count FROM operations o JOIN operation_jobs j ON j.operation_id=o.id WHERE o.state='queued' AND j.available_at<=? AND (o.priority>? OR (o.priority=? AND o.created_at<?))`).get(this.now(), operation.priority, operation.priority, operation.createdAt)?.count ?? 0);
|
|
3501
3512
|
approximatePosition = { ahead, precision: "bounded" };
|
|
3502
3513
|
}
|
|
3503
3514
|
return { operation, job: metadata, approximatePosition };
|
|
@@ -3532,17 +3543,17 @@ class DurableOperationQueue {
|
|
|
3532
3543
|
if (lock)
|
|
3533
3544
|
return `resource_lock:${metadata.lockKey}`;
|
|
3534
3545
|
}
|
|
3535
|
-
if (operation.projectId && this.runningCount(
|
|
3546
|
+
if (operation.projectId && this.runningCount(`SELECT COUNT(*) AS count FROM operations WHERE state='running' AND project_id=?`, [
|
|
3536
3547
|
operation.projectId
|
|
3537
3548
|
]) >= this.limits.project)
|
|
3538
3549
|
return "project_concurrency";
|
|
3539
|
-
if (operation.environmentId && this.runningCount(
|
|
3550
|
+
if (operation.environmentId && this.runningCount(`SELECT COUNT(*) AS count FROM operations WHERE state='running' AND environment_id=?`, [
|
|
3540
3551
|
operation.environmentId
|
|
3541
3552
|
]) >= this.limits.environment)
|
|
3542
3553
|
return "environment_concurrency";
|
|
3543
|
-
if (metadata.providerKey && this.runningCount(
|
|
3554
|
+
if (metadata.providerKey && this.runningCount(`SELECT COUNT(*) AS count FROM operations o JOIN operation_jobs j ON j.operation_id=o.id WHERE o.state='running' AND j.provider_key=?`, [metadata.providerKey]) >= this.limits.provider)
|
|
3544
3555
|
return "provider_concurrency";
|
|
3545
|
-
if (metadata.buildSlot && this.runningCount(
|
|
3556
|
+
if (metadata.buildSlot && this.runningCount(`SELECT COUNT(*) AS count FROM operations o JOIN operation_jobs j ON j.operation_id=o.id WHERE o.state='running' AND j.build_slot=1`, []) >= this.limits.builds)
|
|
3546
3557
|
return "build_concurrency";
|
|
3547
3558
|
return;
|
|
3548
3559
|
}
|
|
@@ -3597,7 +3608,7 @@ class DurableOperationQueue {
|
|
|
3597
3608
|
const now = this.now();
|
|
3598
3609
|
const expiry = this.leaseExpiry();
|
|
3599
3610
|
const metadata = this.getJob(operationId);
|
|
3600
|
-
const changed = this.controlPlane.database.run(
|
|
3611
|
+
const changed = this.controlPlane.database.run(`UPDATE operations SET lease_expires_at=?, updated_at=?, version=version+1 WHERE id=? AND state='running' AND lease_owner=? AND version=?`, [expiry, now, operationId, this.workerId, operation.version]).changes;
|
|
3601
3612
|
if (changed !== 1)
|
|
3602
3613
|
throw new Error("Operation lease changed before heartbeat");
|
|
3603
3614
|
this.controlPlane.database.run("UPDATE operation_jobs SET heartbeat_at=?, current_step=COALESCE(?, current_step), updated_at=? WHERE operation_id=?", [now, step2 ?? null, now, operationId]);
|
|
@@ -3691,7 +3702,9 @@ class DurableOperationQueue {
|
|
|
3691
3702
|
payload: { errorClass, availableAt: available, nextAttempt: operation.attempt + 1 }
|
|
3692
3703
|
});
|
|
3693
3704
|
this.appendLog(operationId, `Retry queued for error class ${errorClass}.`, { stream: "system" });
|
|
3694
|
-
|
|
3705
|
+
const operationView = this.controlPlane.getOperation(queued.id);
|
|
3706
|
+
this.notifyAvailable();
|
|
3707
|
+
return operationView;
|
|
3695
3708
|
}
|
|
3696
3709
|
release(operationId) {
|
|
3697
3710
|
this.controlPlane.database.run("DELETE FROM operation_locks WHERE operation_id=?", [operationId]);
|
|
@@ -3832,7 +3845,7 @@ class DurableOperationQueue {
|
|
|
3832
3845
|
expectedVersion: operation.version,
|
|
3833
3846
|
error: "Worker lease expired; safely requeued from the last checkpoint."
|
|
3834
3847
|
});
|
|
3835
|
-
this.controlPlane.database.run(
|
|
3848
|
+
this.controlPlane.database.run(`UPDATE operation_jobs SET available_at=?, blocked_reason='worker_restart', updated_at=? WHERE operation_id=?`, [this.now(), this.now(), operation.id]);
|
|
3836
3849
|
this.appendLog(operation.id, "Worker lease expired; operation requeued from its persisted checkpoint.", {
|
|
3837
3850
|
stream: "system"
|
|
3838
3851
|
});
|
|
@@ -3885,11 +3898,12 @@ class DurableQueueWorker {
|
|
|
3885
3898
|
waits = new Map;
|
|
3886
3899
|
lanes = [];
|
|
3887
3900
|
running = false;
|
|
3901
|
+
unsubscribeAvailability;
|
|
3888
3902
|
constructor(queue, handlers, options = {}) {
|
|
3889
3903
|
this.queue = queue;
|
|
3890
3904
|
this.handlers = handlers;
|
|
3891
3905
|
this.parallelism = bounded(options.parallelism, 4, 100);
|
|
3892
|
-
this.pollIntervalMs = bounded(options.pollIntervalMs,
|
|
3906
|
+
this.pollIntervalMs = bounded(options.pollIntervalMs, 5000, 60000);
|
|
3893
3907
|
this.onResult = options.onResult;
|
|
3894
3908
|
this.onError = options.onError;
|
|
3895
3909
|
}
|
|
@@ -3900,11 +3914,17 @@ class DurableQueueWorker {
|
|
|
3900
3914
|
if (this.running)
|
|
3901
3915
|
return this;
|
|
3902
3916
|
this.running = true;
|
|
3917
|
+
this.unsubscribeAvailability = this.queue.onAvailable(() => this.wake());
|
|
3903
3918
|
this.lanes = Array.from({ length: this.parallelism }, () => this.runLane());
|
|
3904
3919
|
return this;
|
|
3905
3920
|
}
|
|
3906
3921
|
stop() {
|
|
3907
3922
|
this.running = false;
|
|
3923
|
+
this.unsubscribeAvailability?.();
|
|
3924
|
+
this.unsubscribeAvailability = undefined;
|
|
3925
|
+
this.wake();
|
|
3926
|
+
}
|
|
3927
|
+
wake() {
|
|
3908
3928
|
for (const [timer, resolve] of this.waits) {
|
|
3909
3929
|
clearTimeout(timer);
|
|
3910
3930
|
resolve();
|
package/dist/deploy/index.js
CHANGED
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
synchronizeDashboardUsers,
|
|
33
33
|
trackDashboardOperation,
|
|
34
34
|
verifyStaticApiOrigin
|
|
35
|
-
} from "../chunk-
|
|
35
|
+
} from "../chunk-j6zaxywt.js";
|
|
36
36
|
import {
|
|
37
37
|
deleteStaticSite,
|
|
38
38
|
deployStaticSite,
|
|
@@ -65,7 +65,7 @@ import {
|
|
|
65
65
|
shipsARelease,
|
|
66
66
|
siteInstallBase,
|
|
67
67
|
validateDeploymentConfig
|
|
68
|
-
} from "../chunk-
|
|
68
|
+
} from "../chunk-1p8jah5z.js";
|
|
69
69
|
import"../chunk-ecsyc3p0.js";
|
|
70
70
|
import"../chunk-703nkybg.js";
|
|
71
71
|
import"../chunk-4cjrg98a.js";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CloudConfig } from '@ts-cloud/core';
|
|
2
2
|
import type { RemoteExecOptions } from '../shared/remote-exec';
|
|
3
|
+
import type { HetznerResizeManifest } from './resize-remote';
|
|
3
4
|
export interface HetznerHostOptimizationPlan {
|
|
4
5
|
firewallPorts: number[];
|
|
5
6
|
monitoring: boolean;
|
|
@@ -26,6 +27,24 @@ export interface HetznerHostOptimizationReport {
|
|
|
26
27
|
export interface HetznerHostOptimizationOptions extends RemoteExecOptions {
|
|
27
28
|
host: string;
|
|
28
29
|
}
|
|
30
|
+
export interface HetznerHostContinuityFailures {
|
|
31
|
+
stoppedServices: string[];
|
|
32
|
+
changedRouteFragments: string[];
|
|
33
|
+
missingRouteIds: string[];
|
|
34
|
+
changedReleaseLinks: string[];
|
|
35
|
+
missingData: string[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Compare workload identities rather than immutable release values.
|
|
39
|
+
*
|
|
40
|
+
* Host optimization does not stop application services, but a normal deploy
|
|
41
|
+
* may finish while its package installs and system services are being
|
|
42
|
+
* reconciled. In that case `api@old.service` becoming `api@new.service`, a
|
|
43
|
+
* `current` link advancing, or a route fragment being atomically rewritten is
|
|
44
|
+
* healthy continuity, not loss. Exact route IDs and data catalog entries still
|
|
45
|
+
* have to survive, and a workload with no replacement still fails closed.
|
|
46
|
+
*/
|
|
47
|
+
export declare function verifyHetznerHostContinuity(before: HetznerResizeManifest, after: HetznerResizeManifest): HetznerHostContinuityFailures;
|
|
29
48
|
export declare function resolveHetznerHostOptimizationPlan(config: CloudConfig): HetznerHostOptimizationPlan;
|
|
30
49
|
export declare function buildHetznerHostOptimizationScript(config: CloudConfig): string[];
|
|
31
50
|
export declare function applyHetznerHostOptimization(config: CloudConfig, options: HetznerHostOptimizationOptions): Promise<void>;
|
package/dist/drivers/index.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -285,7 +285,7 @@ import {
|
|
|
285
285
|
volumeCapabilities,
|
|
286
286
|
webhookEndpoint,
|
|
287
287
|
zeroCapacity
|
|
288
|
-
} from "./chunk-
|
|
288
|
+
} from "./chunk-j6zaxywt.js";
|
|
289
289
|
import {
|
|
290
290
|
deleteStaticSite,
|
|
291
291
|
deployStaticSite,
|
|
@@ -398,7 +398,7 @@ import {
|
|
|
398
398
|
waitForCloudInit,
|
|
399
399
|
waitForSsh,
|
|
400
400
|
wrapCloudInitUserData
|
|
401
|
-
} from "./chunk-
|
|
401
|
+
} from "./chunk-1p8jah5z.js";
|
|
402
402
|
import {
|
|
403
403
|
ABTestManager,
|
|
404
404
|
AI,
|
package/dist/queue/queue.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export declare class DurableOperationQueue {
|
|
|
6
6
|
private readonly idFn;
|
|
7
7
|
private readonly workerId;
|
|
8
8
|
private readonly leaseMs;
|
|
9
|
+
private readonly availabilityListeners;
|
|
9
10
|
readonly limits: QueueConcurrencyLimits;
|
|
10
11
|
constructor(controlPlane: ControlPlaneStore, options?: {
|
|
11
12
|
workerId?: string;
|
|
@@ -17,6 +18,13 @@ export declare class DurableOperationQueue {
|
|
|
17
18
|
private now;
|
|
18
19
|
private leaseExpiry;
|
|
19
20
|
enqueue(input: EnqueueOperationInput): QueueOperationView;
|
|
21
|
+
/**
|
|
22
|
+
* Wake in-process workers as soon as work becomes available. Durable workers
|
|
23
|
+
* still poll as a cross-process/recovery fallback, but dashboard API actions
|
|
24
|
+
* no longer need an aggressive idle database polling interval.
|
|
25
|
+
*/
|
|
26
|
+
onAvailable(listener: () => void): () => void;
|
|
27
|
+
private notifyAvailable;
|
|
20
28
|
getJob(operationId: string): OperationJob | undefined;
|
|
21
29
|
view(operationId: string): QueueOperationView | undefined;
|
|
22
30
|
list(input?: {
|
package/dist/queue/worker.d.ts
CHANGED
|
@@ -20,10 +20,12 @@ export declare class DurableQueueWorker {
|
|
|
20
20
|
private readonly waits;
|
|
21
21
|
private lanes;
|
|
22
22
|
private running;
|
|
23
|
+
private unsubscribeAvailability?;
|
|
23
24
|
constructor(queue: DurableOperationQueue, handlers: Record<string, QueueOperationHandler>, options?: DurableQueueWorkerOptions);
|
|
24
25
|
get active(): boolean;
|
|
25
26
|
start(): this;
|
|
26
27
|
stop(): void;
|
|
28
|
+
private wake;
|
|
27
29
|
settled(): Promise<void>;
|
|
28
30
|
/** Execute all currently claimable work, using the configured lane bound. */
|
|
29
31
|
drain(): Promise<QueueRunResult[]>;
|