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.
@@ -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
- error?.message === "APP_SERVING_ROUTE_COMMIT_PENDING";
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 platformFetchImpl(creds, `/platform/apps/${appId}/deploy-static`, {
387
- method: "POST",
388
- headers: {
389
- "Content-Type": "application/octet-stream",
390
- "X-Deploy-Local-Dir": cwd,
391
- "X-Gencow-Deploy-Claim": deployClaim.header,
392
- "X-Gencow-Deploy-Protocol": "1",
393
- "X-Gencow-CLI-Version": deployClaim.claim.generatedBy.version,
394
- ...(releaseAttemptId
395
- ? {
396
- "X-Gencow-Release-Attempt-Id": releaseAttemptId,
397
- "X-Gencow-Release-Environment": opts.envTarget || "dev",
398
- }
399
- : {}),
400
- },
401
- body: bundleBuffer,
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.221",
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",
@@ -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 = 6e4;
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))(input)
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" || now() >= deadlineMs) {
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
  }