gencow 0.1.221 → 0.1.222
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/lib/static-deploy-command.mjs +55 -18
- package/package.json +3 -3
- package/runtime/server.mjs +34 -29
- package/server/index.js.map +0 -7
|
@@ -21,8 +21,38 @@ import { pollAcceptedDeploymentOperation } from "./deployment-operation-poll.mjs
|
|
|
21
21
|
import { writeProjectMetadata } from "./deploy-project-metadata.mjs";
|
|
22
22
|
|
|
23
23
|
function shouldPreserveFinalizeAttempt(error) {
|
|
24
|
-
return error?.retryable === true ||
|
|
25
|
-
|
|
24
|
+
return error?.retryable === true || error?.message === "APP_SERVING_ROUTE_COMMIT_PENDING";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const TRANSIENT_STATIC_DEPLOY_PROXY_STATUSES = new Set([502, 503, 504]);
|
|
28
|
+
|
|
29
|
+
async function isBodylessTransientStaticDeployResponse(response) {
|
|
30
|
+
if (
|
|
31
|
+
!TRANSIENT_STATIC_DEPLOY_PROXY_STATUSES.has(response?.status) ||
|
|
32
|
+
typeof response?.clone !== "function"
|
|
33
|
+
) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
return (await readJsonObjectResponse(response.clone())) === null;
|
|
38
|
+
} catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function postStaticDeployWithTransientProxyRetry({
|
|
44
|
+
send,
|
|
45
|
+
retryDelaysMs = [250, 500, 1_000],
|
|
46
|
+
delayImpl = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
47
|
+
}) {
|
|
48
|
+
let response;
|
|
49
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
50
|
+
response = await send();
|
|
51
|
+
if (!(await isBodylessTransientStaticDeployResponse(response)) || attempt >= retryDelaysMs.length) {
|
|
52
|
+
return response;
|
|
53
|
+
}
|
|
54
|
+
await delayImpl(retryDelaysMs[attempt]);
|
|
55
|
+
}
|
|
26
56
|
}
|
|
27
57
|
|
|
28
58
|
export function resolveStaticDeployDir({
|
|
@@ -178,6 +208,8 @@ export function createStaticDeployRuntime({
|
|
|
178
208
|
resolvePathImpl = resolve,
|
|
179
209
|
setTimeoutImpl = setTimeout,
|
|
180
210
|
statSyncImpl = statSync,
|
|
211
|
+
staticDeployRetryDelayImpl = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
212
|
+
staticDeployRetryDelaysMs,
|
|
181
213
|
successImpl = success,
|
|
182
214
|
tarCreateImpl,
|
|
183
215
|
unlinkSyncImpl = unlinkSync,
|
|
@@ -383,22 +415,27 @@ export function createStaticDeployRuntime({
|
|
|
383
415
|
infoImpl("Deploying static files...");
|
|
384
416
|
let deployRes;
|
|
385
417
|
try {
|
|
386
|
-
deployRes = await
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
418
|
+
deployRes = await postStaticDeployWithTransientProxyRetry({
|
|
419
|
+
send: () =>
|
|
420
|
+
platformFetchImpl(creds, `/platform/apps/${appId}/deploy-static`, {
|
|
421
|
+
method: "POST",
|
|
422
|
+
headers: {
|
|
423
|
+
"Content-Type": "application/octet-stream",
|
|
424
|
+
"X-Deploy-Local-Dir": cwd,
|
|
425
|
+
"X-Gencow-Deploy-Claim": deployClaim.header,
|
|
426
|
+
"X-Gencow-Deploy-Protocol": "1",
|
|
427
|
+
"X-Gencow-CLI-Version": deployClaim.claim.generatedBy.version,
|
|
428
|
+
...(releaseAttemptId
|
|
429
|
+
? {
|
|
430
|
+
"X-Gencow-Release-Attempt-Id": releaseAttemptId,
|
|
431
|
+
"X-Gencow-Release-Environment": opts.envTarget || "dev",
|
|
432
|
+
}
|
|
433
|
+
: {}),
|
|
434
|
+
},
|
|
435
|
+
body: bundleBuffer,
|
|
436
|
+
}),
|
|
437
|
+
retryDelaysMs: staticDeployRetryDelaysMs,
|
|
438
|
+
delayImpl: staticDeployRetryDelayImpl,
|
|
402
439
|
});
|
|
403
440
|
if (deployRes.status === 202) {
|
|
404
441
|
deployRes = await pollAcceptedDeploymentOperation({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gencow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.222",
|
|
4
4
|
"description": "Gencow — AI Backend Engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/node": "^25.9.5",
|
|
35
35
|
"better-auth": "^1.6.23",
|
|
36
|
-
"@gencow/core": "0.1.43",
|
|
37
36
|
"@gencow/client": "0.2.7",
|
|
38
|
-
"@gencow/react": "0.2.7"
|
|
37
|
+
"@gencow/react": "0.2.7",
|
|
38
|
+
"@gencow/core": "0.1.43"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"prebuild": "pnpm --filter @gencow/migration-contract run build && pnpm --filter @gencow/server run build",
|
package/runtime/server.mjs
CHANGED
|
@@ -164575,6 +164575,7 @@ async function registerPlatformCronScheduler(params) {
|
|
|
164575
164575
|
rawSql: params.rawSql,
|
|
164576
164576
|
provisioner,
|
|
164577
164577
|
fetchImpl: params.fetchImpl,
|
|
164578
|
+
cronExecTimeoutMs: CRON_EXEC_TIMEOUT,
|
|
164578
164579
|
log: log3,
|
|
164579
164580
|
admitRuntimeWorkload: params.admitRuntimeWorkload,
|
|
164580
164581
|
requestRuntimeWake
|
|
@@ -164599,9 +164600,10 @@ var init_server_platform_cron_scheduler = __esm({
|
|
|
164599
164600
|
init_platform_active_slot();
|
|
164600
164601
|
init_postgres_temporal();
|
|
164601
164602
|
init_server_platform_cron_ledger();
|
|
164603
|
+
init_server_execution();
|
|
164602
164604
|
CRON_POLL_INTERVAL = 6e4;
|
|
164603
164605
|
CRON_CONCURRENCY = 5;
|
|
164604
|
-
CRON_EXEC_TIMEOUT =
|
|
164606
|
+
CRON_EXEC_TIMEOUT = FUNCTION_TIMEOUTS.cron;
|
|
164605
164607
|
CRON_MAX_JOBS_PER_POLL = 50;
|
|
164606
164608
|
CRON_MAX_WAKE_PER_POLL = 3;
|
|
164607
164609
|
CRON_DUE_PER_APP_PER_POLL = 10;
|
|
@@ -187570,7 +187572,9 @@ async function admitDeploymentExecutorRequestAfterActiveOperation(input, options
|
|
|
187570
187572
|
pollMs: options.pollMs,
|
|
187571
187573
|
sleep: options.sleep,
|
|
187572
187574
|
now: options.now,
|
|
187573
|
-
onBusy: async () => (options.joinActiveSameSource ?? (options.admit ? async () => null : joinActiveSameSourceDeployment))(
|
|
187575
|
+
onBusy: async () => (options.joinActiveSameSource ?? (options.admit ? async () => null : joinActiveSameSourceDeployment))(
|
|
187576
|
+
input
|
|
187577
|
+
)
|
|
187574
187578
|
}
|
|
187575
187579
|
);
|
|
187576
187580
|
}
|
|
@@ -187587,11 +187591,12 @@ async function retryDeploymentExecutorAdmission(admit, options = {}) {
|
|
|
187587
187591
|
try {
|
|
187588
187592
|
return await admit();
|
|
187589
187593
|
} catch (error51) {
|
|
187590
|
-
if (!(error51 instanceof DeploymentExecutorAdmissionError) || error51.code !== "DEPLOYMENT_EXECUTOR_APP_BUSY"
|
|
187594
|
+
if (!(error51 instanceof DeploymentExecutorAdmissionError) || error51.code !== "DEPLOYMENT_EXECUTOR_APP_BUSY") {
|
|
187591
187595
|
throw error51;
|
|
187592
187596
|
}
|
|
187593
187597
|
const joined = await options.onBusy?.();
|
|
187594
187598
|
if (joined) return joined;
|
|
187599
|
+
if (now() >= deadlineMs) return await admit();
|
|
187595
187600
|
await sleep6(Math.min(pollMs, Math.max(1, deadlineMs - now())));
|
|
187596
187601
|
}
|
|
187597
187602
|
}
|
|
@@ -426367,30 +426372,30 @@ async function failExplicitRuntimeStop(input) {
|
|
|
426367
426372
|
if (intent?.dispatchStartedAt || intent?.consumedAt) return false;
|
|
426368
426373
|
if (intent) {
|
|
426369
426374
|
await tx.update(runtimeStopIntents).set({ cancelledAt: now, cancelReason: failureCode }).where(and60(eq65(runtimeStopIntents.id, intent.id), isNull26(runtimeStopIntents.cancelledAt)));
|
|
426370
|
-
await Promise.all([
|
|
426371
|
-
tx.update(appRuntimeDesiredState).set({ desiredRuntimeState: "serving", updatedAt: now }).where(
|
|
426372
|
-
and60(
|
|
426373
|
-
eq65(appRuntimeDesiredState.appId, input.plan.appId),
|
|
426374
|
-
eq65(appRuntimeDesiredState.desiredActivationId, input.plan.activationId),
|
|
426375
|
-
eq65(appRuntimeDesiredState.desiredRuntimeState, "draining")
|
|
426376
|
-
)
|
|
426377
|
-
),
|
|
426378
|
-
tx.update(appDeploymentActivations).set({ state: "serving", updatedAt: now }).where(
|
|
426379
|
-
and60(
|
|
426380
|
-
eq65(appDeploymentActivations.id, input.plan.activationId),
|
|
426381
|
-
eq65(appDeploymentActivations.appId, input.plan.appId),
|
|
426382
|
-
eq65(appDeploymentActivations.state, "draining")
|
|
426383
|
-
)
|
|
426384
|
-
),
|
|
426385
|
-
tx.update(appRuntimeInstances).set({ state: "serving", updatedAt: now }).where(
|
|
426386
|
-
and60(
|
|
426387
|
-
eq65(appRuntimeInstances.instanceId, input.plan.instanceId),
|
|
426388
|
-
eq65(appRuntimeInstances.appId, input.plan.appId),
|
|
426389
|
-
eq65(appRuntimeInstances.state, "draining")
|
|
426390
|
-
)
|
|
426391
|
-
)
|
|
426392
|
-
]);
|
|
426393
426375
|
}
|
|
426376
|
+
await Promise.all([
|
|
426377
|
+
tx.update(appRuntimeDesiredState).set({ desiredRuntimeState: "serving", updatedAt: now }).where(
|
|
426378
|
+
and60(
|
|
426379
|
+
eq65(appRuntimeDesiredState.appId, input.plan.appId),
|
|
426380
|
+
eq65(appRuntimeDesiredState.desiredActivationId, input.plan.activationId),
|
|
426381
|
+
eq65(appRuntimeDesiredState.desiredRuntimeState, "draining")
|
|
426382
|
+
)
|
|
426383
|
+
),
|
|
426384
|
+
tx.update(appDeploymentActivations).set({ state: "serving", updatedAt: now }).where(
|
|
426385
|
+
and60(
|
|
426386
|
+
eq65(appDeploymentActivations.id, input.plan.activationId),
|
|
426387
|
+
eq65(appDeploymentActivations.appId, input.plan.appId),
|
|
426388
|
+
eq65(appDeploymentActivations.state, "draining")
|
|
426389
|
+
)
|
|
426390
|
+
),
|
|
426391
|
+
tx.update(appRuntimeInstances).set({ state: "serving", updatedAt: now }).where(
|
|
426392
|
+
and60(
|
|
426393
|
+
eq65(appRuntimeInstances.instanceId, input.plan.instanceId),
|
|
426394
|
+
eq65(appRuntimeInstances.appId, input.plan.appId),
|
|
426395
|
+
eq65(appRuntimeInstances.state, "draining")
|
|
426396
|
+
)
|
|
426397
|
+
)
|
|
426398
|
+
]);
|
|
426394
426399
|
await tx.update(runtimeDrainRequests).set({ state: "cancelled", cancelReason: failureCode, updatedAt: now }).where(
|
|
426395
426400
|
and60(
|
|
426396
426401
|
eq65(runtimeDrainRequests.id, input.plan.drainId),
|
|
@@ -434212,7 +434217,7 @@ async function createDatabase(options = {}) {
|
|
|
434212
434217
|
const databaseUrl = options.databaseUrl ?? process.env.DATABASE_URL;
|
|
434213
434218
|
if (databaseUrl) {
|
|
434214
434219
|
const platformMigrationRuntime = options.platformMigrationRuntime ?? process.env.IS_PLATFORM === "true";
|
|
434215
|
-
return initPostgres(databaseUrl, platformMigrationRuntime);
|
|
434220
|
+
return initPostgres(databaseUrl, platformMigrationRuntime, options.platformMigrationJournalReadOnly ?? false);
|
|
434216
434221
|
}
|
|
434217
434222
|
const dataDir = process.env.GENCOW_DB_URL || "./data";
|
|
434218
434223
|
return initPGlite(dataDir);
|
|
@@ -434326,7 +434331,7 @@ async function initPGlite(dataDir) {
|
|
|
434326
434331
|
}
|
|
434327
434332
|
};
|
|
434328
434333
|
}
|
|
434329
|
-
async function initPostgres(url2, platformMigrationRuntime) {
|
|
434334
|
+
async function initPostgres(url2, platformMigrationRuntime, platformMigrationJournalReadOnly) {
|
|
434330
434335
|
const { SQL: SQL2 } = await import("bun");
|
|
434331
434336
|
const { drizzle: drizzle2 } = await import("drizzle-orm/bun-sql");
|
|
434332
434337
|
const poolConfig = resolvePostgresPoolConfig();
|
|
@@ -434457,7 +434462,7 @@ async function initPostgres(url2, platformMigrationRuntime) {
|
|
|
434457
434462
|
preserveMilliseconds: !platformMigrationRuntime
|
|
434458
434463
|
});
|
|
434459
434464
|
try {
|
|
434460
|
-
const repairPlan = platformMigrationRuntime ? await repairLegacyDrizzleMigrationTableForPlatformRuntime(rawSql, prepared.path) : null;
|
|
434465
|
+
const repairPlan = platformMigrationRuntime && !platformMigrationJournalReadOnly ? await repairLegacyDrizzleMigrationTableForPlatformRuntime(rawSql, prepared.path) : null;
|
|
434461
434466
|
if (repairPlan) {
|
|
434462
434467
|
console.warn(`[db] drizzle migration table reconciled for runtime compatibility (matched=${repairPlan.matchedCount}, inferred=${repairPlan.inferredCount}, dbRows=${repairPlan.dbCount}, local=${repairPlan.localCount})`);
|
|
434463
434468
|
}
|