@stacksjs/ts-cloud 0.7.68 → 0.7.70
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-349k40rw.js → chunk-1c1vwq1p.js} +52 -10
- package/dist/deploy/index.js +1 -1
- package/dist/index.js +1 -1
- package/dist/queue/queue.d.ts +7 -0
- package/dist/queue/worker.d.ts +2 -0
- package/dist/ui/account/automation.html +4 -4
- 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/security.html +2 -2
- 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 +4 -4
- 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/security.html +2 -2
- package/dist/ui/server/services.html +2 -2
- package/dist/ui/server/sites.html +4 -4
- package/dist/ui/server/ssh-keys.html +4 -4
- 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 +3 -3
- package/dist/ui/serverless/logs.html +4 -4
- 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
|
@@ -3381,6 +3381,24 @@ var DEFAULT_LIMITS = { project: 2, environment: 1, provider: 2, builds: 1 };
|
|
|
3381
3381
|
var DEFAULT_RETENTION_DAYS = 30;
|
|
3382
3382
|
var MAX_LOG_BYTES = 16 * 1024;
|
|
3383
3383
|
var TERMINAL_STATES2 = ["succeeded", "failed", "cancelled", "timed_out"];
|
|
3384
|
+
var fileAvailabilityListeners = new Map;
|
|
3385
|
+
var memoryAvailabilityListeners = new WeakMap;
|
|
3386
|
+
function availabilityListeners(store) {
|
|
3387
|
+
if (store.path === ":memory:") {
|
|
3388
|
+
const existing2 = memoryAvailabilityListeners.get(store);
|
|
3389
|
+
if (existing2)
|
|
3390
|
+
return existing2;
|
|
3391
|
+
const created2 = new Set;
|
|
3392
|
+
memoryAvailabilityListeners.set(store, created2);
|
|
3393
|
+
return created2;
|
|
3394
|
+
}
|
|
3395
|
+
const existing = fileAvailabilityListeners.get(store.path);
|
|
3396
|
+
if (existing)
|
|
3397
|
+
return existing;
|
|
3398
|
+
const created = new Set;
|
|
3399
|
+
fileAvailabilityListeners.set(store.path, created);
|
|
3400
|
+
return created;
|
|
3401
|
+
}
|
|
3384
3402
|
function optional(value) {
|
|
3385
3403
|
return typeof value === "string" && value ? value : undefined;
|
|
3386
3404
|
}
|
|
@@ -3484,7 +3502,22 @@ class DurableOperationQueue {
|
|
|
3484
3502
|
now
|
|
3485
3503
|
]);
|
|
3486
3504
|
this.appendLog(operation.id, "Queued for durable execution.", { stream: "system" });
|
|
3487
|
-
|
|
3505
|
+
const view = this.view(operation.id);
|
|
3506
|
+
this.notifyAvailable();
|
|
3507
|
+
return view;
|
|
3508
|
+
}
|
|
3509
|
+
onAvailable(listener) {
|
|
3510
|
+
const listeners = availabilityListeners(this.controlPlane);
|
|
3511
|
+
listeners.add(listener);
|
|
3512
|
+
return () => {
|
|
3513
|
+
listeners.delete(listener);
|
|
3514
|
+
if (listeners.size === 0 && this.controlPlane.path !== ":memory:")
|
|
3515
|
+
fileAvailabilityListeners.delete(this.controlPlane.path);
|
|
3516
|
+
};
|
|
3517
|
+
}
|
|
3518
|
+
notifyAvailable() {
|
|
3519
|
+
for (const listener of availabilityListeners(this.controlPlane))
|
|
3520
|
+
listener();
|
|
3488
3521
|
}
|
|
3489
3522
|
getJob(operationId) {
|
|
3490
3523
|
const row = this.controlPlane.database.query("SELECT * FROM operation_jobs WHERE operation_id=?").get(operationId);
|
|
@@ -3497,7 +3530,7 @@ class DurableOperationQueue {
|
|
|
3497
3530
|
return;
|
|
3498
3531
|
let approximatePosition;
|
|
3499
3532
|
if (operation.state === "queued") {
|
|
3500
|
-
const ahead = Number(this.controlPlane.database.query(
|
|
3533
|
+
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
3534
|
approximatePosition = { ahead, precision: "bounded" };
|
|
3502
3535
|
}
|
|
3503
3536
|
return { operation, job: metadata, approximatePosition };
|
|
@@ -3532,17 +3565,17 @@ class DurableOperationQueue {
|
|
|
3532
3565
|
if (lock)
|
|
3533
3566
|
return `resource_lock:${metadata.lockKey}`;
|
|
3534
3567
|
}
|
|
3535
|
-
if (operation.projectId && this.runningCount(
|
|
3568
|
+
if (operation.projectId && this.runningCount(`SELECT COUNT(*) AS count FROM operations WHERE state='running' AND project_id=?`, [
|
|
3536
3569
|
operation.projectId
|
|
3537
3570
|
]) >= this.limits.project)
|
|
3538
3571
|
return "project_concurrency";
|
|
3539
|
-
if (operation.environmentId && this.runningCount(
|
|
3572
|
+
if (operation.environmentId && this.runningCount(`SELECT COUNT(*) AS count FROM operations WHERE state='running' AND environment_id=?`, [
|
|
3540
3573
|
operation.environmentId
|
|
3541
3574
|
]) >= this.limits.environment)
|
|
3542
3575
|
return "environment_concurrency";
|
|
3543
|
-
if (metadata.providerKey && this.runningCount(
|
|
3576
|
+
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
3577
|
return "provider_concurrency";
|
|
3545
|
-
if (metadata.buildSlot && this.runningCount(
|
|
3578
|
+
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
3579
|
return "build_concurrency";
|
|
3547
3580
|
return;
|
|
3548
3581
|
}
|
|
@@ -3597,7 +3630,7 @@ class DurableOperationQueue {
|
|
|
3597
3630
|
const now = this.now();
|
|
3598
3631
|
const expiry = this.leaseExpiry();
|
|
3599
3632
|
const metadata = this.getJob(operationId);
|
|
3600
|
-
const changed = this.controlPlane.database.run(
|
|
3633
|
+
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
3634
|
if (changed !== 1)
|
|
3602
3635
|
throw new Error("Operation lease changed before heartbeat");
|
|
3603
3636
|
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 +3724,9 @@ class DurableOperationQueue {
|
|
|
3691
3724
|
payload: { errorClass, availableAt: available, nextAttempt: operation.attempt + 1 }
|
|
3692
3725
|
});
|
|
3693
3726
|
this.appendLog(operationId, `Retry queued for error class ${errorClass}.`, { stream: "system" });
|
|
3694
|
-
|
|
3727
|
+
const operationView = this.controlPlane.getOperation(queued.id);
|
|
3728
|
+
this.notifyAvailable();
|
|
3729
|
+
return operationView;
|
|
3695
3730
|
}
|
|
3696
3731
|
release(operationId) {
|
|
3697
3732
|
this.controlPlane.database.run("DELETE FROM operation_locks WHERE operation_id=?", [operationId]);
|
|
@@ -3832,7 +3867,7 @@ class DurableOperationQueue {
|
|
|
3832
3867
|
expectedVersion: operation.version,
|
|
3833
3868
|
error: "Worker lease expired; safely requeued from the last checkpoint."
|
|
3834
3869
|
});
|
|
3835
|
-
this.controlPlane.database.run(
|
|
3870
|
+
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
3871
|
this.appendLog(operation.id, "Worker lease expired; operation requeued from its persisted checkpoint.", {
|
|
3837
3872
|
stream: "system"
|
|
3838
3873
|
});
|
|
@@ -3885,11 +3920,12 @@ class DurableQueueWorker {
|
|
|
3885
3920
|
waits = new Map;
|
|
3886
3921
|
lanes = [];
|
|
3887
3922
|
running = false;
|
|
3923
|
+
unsubscribeAvailability;
|
|
3888
3924
|
constructor(queue, handlers, options = {}) {
|
|
3889
3925
|
this.queue = queue;
|
|
3890
3926
|
this.handlers = handlers;
|
|
3891
3927
|
this.parallelism = bounded(options.parallelism, 4, 100);
|
|
3892
|
-
this.pollIntervalMs = bounded(options.pollIntervalMs,
|
|
3928
|
+
this.pollIntervalMs = bounded(options.pollIntervalMs, 5000, 60000);
|
|
3893
3929
|
this.onResult = options.onResult;
|
|
3894
3930
|
this.onError = options.onError;
|
|
3895
3931
|
}
|
|
@@ -3900,11 +3936,17 @@ class DurableQueueWorker {
|
|
|
3900
3936
|
if (this.running)
|
|
3901
3937
|
return this;
|
|
3902
3938
|
this.running = true;
|
|
3939
|
+
this.unsubscribeAvailability = this.queue.onAvailable(() => this.wake());
|
|
3903
3940
|
this.lanes = Array.from({ length: this.parallelism }, () => this.runLane());
|
|
3904
3941
|
return this;
|
|
3905
3942
|
}
|
|
3906
3943
|
stop() {
|
|
3907
3944
|
this.running = false;
|
|
3945
|
+
this.unsubscribeAvailability?.();
|
|
3946
|
+
this.unsubscribeAvailability = undefined;
|
|
3947
|
+
this.wake();
|
|
3948
|
+
}
|
|
3949
|
+
wake() {
|
|
3908
3950
|
for (const [timer, resolve] of this.waits) {
|
|
3909
3951
|
clearTimeout(timer);
|
|
3910
3952
|
resolve();
|
package/dist/deploy/index.js
CHANGED
package/dist/index.js
CHANGED
package/dist/queue/queue.d.ts
CHANGED
|
@@ -17,6 +17,13 @@ export declare class DurableOperationQueue {
|
|
|
17
17
|
private now;
|
|
18
18
|
private leaseExpiry;
|
|
19
19
|
enqueue(input: EnqueueOperationInput): QueueOperationView;
|
|
20
|
+
/**
|
|
21
|
+
* Wake in-process workers as soon as work becomes available. Durable workers
|
|
22
|
+
* still poll as a cross-process/recovery fallback, but dashboard API actions
|
|
23
|
+
* no longer need an aggressive idle database polling interval.
|
|
24
|
+
*/
|
|
25
|
+
onAvailable(listener: () => void): () => void;
|
|
26
|
+
private notifyAvailable;
|
|
20
27
|
getJob(operationId: string): OperationJob | undefined;
|
|
21
28
|
view(operationId: string): QueueOperationView | undefined;
|
|
22
29
|
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[]>;
|