gencow 0.1.214 → 0.1.216
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.
|
@@ -16,7 +16,14 @@ const APP_DELETE_ACTIVE_STATES = new Set([
|
|
|
16
16
|
"failed_tenant_db_cleanup",
|
|
17
17
|
"failed_catalog_cleanup",
|
|
18
18
|
]);
|
|
19
|
-
const APP_DELETE_TERMINAL_FAILURE_STATES = new Set([
|
|
19
|
+
const APP_DELETE_TERMINAL_FAILURE_STATES = new Set([
|
|
20
|
+
"blocked_catalog_outcome_unknown",
|
|
21
|
+
"failed_delete_recovery_required",
|
|
22
|
+
]);
|
|
23
|
+
const APP_DELETE_RESPONSE_STATES = new Set([
|
|
24
|
+
...APP_DELETE_ACTIVE_STATES,
|
|
25
|
+
...APP_DELETE_TERMINAL_FAILURE_STATES,
|
|
26
|
+
]);
|
|
20
27
|
const CORRELATION_ID_PATTERN = /^[A-Za-z0-9_-]{8,128}$/u;
|
|
21
28
|
const DIAGNOSTIC_CODE_PATTERN = /^[A-Za-z][A-Za-z0-9_]{2,127}$/u;
|
|
22
29
|
const APP_ID_PATTERN = /^(?=.{3,63}$)[a-z][a-z0-9]*(?:-[a-z0-9]+){2,7}$/u;
|
|
@@ -44,7 +51,7 @@ export function parseAppDeleteOperationEnvelope(value, expectedAppId) {
|
|
|
44
51
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
45
52
|
if (value.success !== undefined && value.success !== false) return null;
|
|
46
53
|
if (!APP_DELETE_OPERATION_PATTERN.test(value.operationId ?? "")) return null;
|
|
47
|
-
if (!
|
|
54
|
+
if (!APP_DELETE_RESPONSE_STATES.has(value.state)) return null;
|
|
48
55
|
if (
|
|
49
56
|
!CORRELATION_ID_PATTERN.test(value.correlationId ?? "") ||
|
|
50
57
|
(value.deleted !== undefined && value.deleted !== expectedAppId) ||
|
|
@@ -164,6 +164,19 @@ export async function deployBackendPackage({
|
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
if (!deployed) return null;
|
|
167
|
+
// Persist the production target before finalize. Finalize is a separate durable
|
|
168
|
+
// release effect; if it fails, the next customer retry must reuse this exact
|
|
169
|
+
// app instead of creating a second production child.
|
|
170
|
+
if (envTarget === "prod") {
|
|
171
|
+
writeProjectMetadata({
|
|
172
|
+
appId: deployed.appId,
|
|
173
|
+
displayName,
|
|
174
|
+
envTarget,
|
|
175
|
+
platformUrl: creds.platformUrl,
|
|
176
|
+
gencowJsonPath,
|
|
177
|
+
writeFileSyncImpl,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
167
180
|
if (releaseAttempt && finalizeReleaseAttempt) {
|
|
168
181
|
try {
|
|
169
182
|
await finalizeReleaseAttempt({ appId: deployed.appId, attemptId: releaseAttempt.attemptId });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gencow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.216",
|
|
4
4
|
"description": "Gencow — AI Backend Engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/node": "^25.9.5",
|
|
35
35
|
"better-auth": "^1.6.23",
|
|
36
|
-
"@gencow/client": "0.2.7",
|
|
37
36
|
"@gencow/core": "0.1.43",
|
|
37
|
+
"@gencow/client": "0.2.7",
|
|
38
38
|
"@gencow/react": "0.2.7"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
package/runtime/server.mjs
CHANGED
|
@@ -110824,9 +110824,14 @@ function registerPlatformSlotPromotionRoute(params) {
|
|
|
110824
110824
|
}
|
|
110825
110825
|
state2 = "promoting";
|
|
110826
110826
|
const approval = routeProjectionDegradedApprovalFromRequest(c);
|
|
110827
|
-
|
|
110828
|
-
if (!currentEvidence || currentEvidence.bindingCount !== preparedEvidence.bindingCount || currentEvidence.evidenceDigest !== preparedEvidence.evidenceDigest)
|
|
110829
|
-
|
|
110827
|
+
let currentEvidence = await params.assertTenantRouteParity?.(approval);
|
|
110828
|
+
if (!currentEvidence || currentEvidence.bindingCount !== preparedEvidence.bindingCount || currentEvidence.evidenceDigest !== preparedEvidence.evidenceDigest) {
|
|
110829
|
+
await params.autoRecoveryRuntime.promote();
|
|
110830
|
+
currentEvidence = await params.assertTenantRouteParity?.(approval);
|
|
110831
|
+
if (!currentEvidence || currentEvidence.bindingCount !== preparedEvidence.bindingCount || currentEvidence.evidenceDigest !== preparedEvidence.evidenceDigest) {
|
|
110832
|
+
throw new Error("PLATFORM_TENANT_ROUTE_PARITY_EVIDENCE_CHANGED");
|
|
110833
|
+
}
|
|
110834
|
+
}
|
|
110830
110835
|
params.setCandidateMode(false);
|
|
110831
110836
|
state2 = "active";
|
|
110832
110837
|
logger3.log("[platform] standby candidate promoted to active runtime mode");
|
|
@@ -149200,6 +149205,7 @@ async function bootstrapRuntimeRouteProjectionForPlatform(input) {
|
|
|
149200
149205
|
return {
|
|
149201
149206
|
convergeServingFleet: runtime.convergeServingFleet,
|
|
149202
149207
|
isAppProjectionBlocked: runtime.isAppProjectionBlocked,
|
|
149208
|
+
resolveExistingOnlyRoute: runtime.resolveExistingOnlyRoute,
|
|
149203
149209
|
setAbsentRouteConverger: runtime.setAbsentRouteConverger,
|
|
149204
149210
|
startAfter,
|
|
149205
149211
|
startAfterRecovery
|
|
@@ -152045,13 +152051,55 @@ function rejectNodeMismatch(c, enabled, currentNodeId, homeNodeId) {
|
|
|
152045
152051
|
code: "APP_RUNTIME_EXISTING_ROUTE_NODE_MISMATCH"
|
|
152046
152052
|
}, 409);
|
|
152047
152053
|
}
|
|
152048
|
-
function
|
|
152054
|
+
function routeResolutionUnavailable(c, result2) {
|
|
152049
152055
|
return c.json({
|
|
152050
|
-
error: "Exact serving runtime is not
|
|
152051
|
-
code:
|
|
152052
|
-
status:
|
|
152056
|
+
error: "Exact serving runtime is not available on this platform slot",
|
|
152057
|
+
code: result2.code,
|
|
152058
|
+
status: result2.status
|
|
152053
152059
|
}, 503);
|
|
152054
152060
|
}
|
|
152061
|
+
async function proxyResolvedExistingOnlyRoute(input) {
|
|
152062
|
+
const route = await input.resolveRoute?.(input.appId);
|
|
152063
|
+
if (!route || route.kind !== "ready") {
|
|
152064
|
+
return routeResolutionUnavailable(input.c, route ?? { code: "APP_RUNTIME_EXISTING_ROUTE_UNAVAILABLE", status: "unavailable" });
|
|
152065
|
+
}
|
|
152066
|
+
try {
|
|
152067
|
+
return await input.proxyRequest({
|
|
152068
|
+
c: input.c,
|
|
152069
|
+
host: input.host,
|
|
152070
|
+
appName: input.appName,
|
|
152071
|
+
port: route.port,
|
|
152072
|
+
url: input.url,
|
|
152073
|
+
requestBody: input.requestBody,
|
|
152074
|
+
addProxyMetric: input.addProxyMetric
|
|
152075
|
+
});
|
|
152076
|
+
} catch {
|
|
152077
|
+
return routeResolutionUnavailable(input.c, {
|
|
152078
|
+
code: "APP_RUNTIME_EXISTING_ROUTE_UNAVAILABLE",
|
|
152079
|
+
status: "unavailable"
|
|
152080
|
+
});
|
|
152081
|
+
}
|
|
152082
|
+
}
|
|
152083
|
+
async function resolveExistingOnlyRoutePort(input) {
|
|
152084
|
+
const route = await input.resolveRoute?.(input.appId);
|
|
152085
|
+
if (!route || route.kind !== "ready") {
|
|
152086
|
+
return routeResolutionUnavailable(input.c, route ?? { code: "APP_RUNTIME_EXISTING_ROUTE_UNAVAILABLE", status: "unavailable" });
|
|
152087
|
+
}
|
|
152088
|
+
return route.port;
|
|
152089
|
+
}
|
|
152090
|
+
async function resolveWebsocketPort(input) {
|
|
152091
|
+
if (input.existingOnly) {
|
|
152092
|
+
return resolveExistingOnlyRoutePort({
|
|
152093
|
+
c: input.c,
|
|
152094
|
+
appId: input.appRow.id,
|
|
152095
|
+
resolveRoute: input.resolveRoute
|
|
152096
|
+
});
|
|
152097
|
+
}
|
|
152098
|
+
const runtime = await input.recover();
|
|
152099
|
+
if (runtime.kind === "unavailable")
|
|
152100
|
+
return input.c.json(runtime, runtime.httpStatus);
|
|
152101
|
+
return runtime.port;
|
|
152102
|
+
}
|
|
152055
152103
|
async function acquireRuntimeActivity(params) {
|
|
152056
152104
|
if (params.existingOnlyRuntimeProbe)
|
|
152057
152105
|
return void 0;
|
|
@@ -153315,12 +153363,12 @@ var init_server_serving_plane_dependency_metrics = __esm({
|
|
|
153315
153363
|
}
|
|
153316
153364
|
});
|
|
153317
153365
|
|
|
153318
|
-
// ../server/dist/server-platform-app-proxy.js
|
|
153366
|
+
// ../server/dist/server-platform-app-proxy-routing.js
|
|
153319
153367
|
function isPublicAppBackendRoute(pathname) {
|
|
153320
153368
|
return /^\/(api|platform|internal|ws)\b/.test(pathname);
|
|
153321
153369
|
}
|
|
153322
153370
|
function isDeniedPublicAppSystemPath(pathname) {
|
|
153323
|
-
return /^\/(_admin|_dashboard)\b/.test(pathname);
|
|
153371
|
+
return /^\/(?:_admin|_dashboard)\b/.test(pathname);
|
|
153324
153372
|
}
|
|
153325
153373
|
function classifyServingPlaneRequest(pathname, upgradeHeader) {
|
|
153326
153374
|
if (pathname.startsWith("/_gencow/analytics"))
|
|
@@ -153334,6 +153382,13 @@ function classifyServingPlaneRequest(pathname, upgradeHeader) {
|
|
|
153334
153382
|
return "backend_http";
|
|
153335
153383
|
return "static_candidate";
|
|
153336
153384
|
}
|
|
153385
|
+
var init_server_platform_app_proxy_routing = __esm({
|
|
153386
|
+
"../server/dist/server-platform-app-proxy-routing.js"() {
|
|
153387
|
+
"use strict";
|
|
153388
|
+
}
|
|
153389
|
+
});
|
|
153390
|
+
|
|
153391
|
+
// ../server/dist/server-platform-app-proxy.js
|
|
153337
153392
|
async function proxyToBackendWithRecoveryInternal(params) {
|
|
153338
153393
|
if (params.appRow.status === "memory_exceeded") {
|
|
153339
153394
|
const unavailable2 = params.buildAppRuntimeUnavailableResult(params.appRow.name, params.appRow.status, params.appRow.statusReason);
|
|
@@ -153364,7 +153419,17 @@ async function proxyToBackendWithRecoveryInternal(params) {
|
|
|
153364
153419
|
}
|
|
153365
153420
|
}
|
|
153366
153421
|
if (params.existingOnlyRuntimeProbe)
|
|
153367
|
-
return
|
|
153422
|
+
return proxyResolvedExistingOnlyRoute({
|
|
153423
|
+
c: params.c,
|
|
153424
|
+
host: params.host,
|
|
153425
|
+
appName: params.appRow.name,
|
|
153426
|
+
appId: params.appRow.id,
|
|
153427
|
+
url: params.url,
|
|
153428
|
+
requestBody: replayPlan.initialBody,
|
|
153429
|
+
addProxyMetric: params.addProxyMetric,
|
|
153430
|
+
proxyRequest,
|
|
153431
|
+
resolveRoute: params.resolveExistingOnlyRoute
|
|
153432
|
+
});
|
|
153368
153433
|
let runtime;
|
|
153369
153434
|
try {
|
|
153370
153435
|
runtime = await params.ensureAppRuntimeReady(params.appRow, buildPlatformRuntimeRecoveryDeps({
|
|
@@ -153374,6 +153439,7 @@ async function proxyToBackendWithRecoveryInternal(params) {
|
|
|
153374
153439
|
} catch (error51) {
|
|
153375
153440
|
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
153376
153441
|
params.logger.error(`[platform] ${params.appRow.name}: runtime recovery failed: ${message}`);
|
|
153442
|
+
params.c.header("Retry-After", "2");
|
|
153377
153443
|
return params.c.json(buildTransientProxyFailureBody(), 503);
|
|
153378
153444
|
}
|
|
153379
153445
|
if (runtime.kind === "unavailable") {
|
|
@@ -153400,6 +153466,7 @@ async function proxyToBackendWithRecoveryInternal(params) {
|
|
|
153400
153466
|
} catch (error51) {
|
|
153401
153467
|
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
153402
153468
|
params.logger.error(`[platform] ${params.appRow.name}: retry proxy failed on :${runtime.port} ${requestLabel}: ${message}`);
|
|
153469
|
+
params.c.header("Retry-After", "2");
|
|
153403
153470
|
return params.c.json(buildTransientProxyFailureBody(), 502);
|
|
153404
153471
|
}
|
|
153405
153472
|
}
|
|
@@ -153622,18 +153689,23 @@ function registerPlatformAppProxy(params) {
|
|
|
153622
153689
|
});
|
|
153623
153690
|
let websocketPort = params.getLivePort(appName) || appRow.port;
|
|
153624
153691
|
if (appRow.runtimeAuthorityMode === "enforce") {
|
|
153625
|
-
const
|
|
153626
|
-
|
|
153627
|
-
|
|
153628
|
-
|
|
153629
|
-
|
|
153630
|
-
|
|
153631
|
-
|
|
153692
|
+
const resolvedPort = await resolveWebsocketPort({
|
|
153693
|
+
c,
|
|
153694
|
+
appRow,
|
|
153695
|
+
existingOnly: existingOnlyRuntimeProbe,
|
|
153696
|
+
resolveRoute: params.resolveExistingOnlyRoute,
|
|
153697
|
+
recover: async () => params.ensureAppRuntimeReady(appRow, buildPlatformRuntimeRecoveryDeps({
|
|
153698
|
+
...params,
|
|
153699
|
+
logger: logger3,
|
|
153700
|
+
probePort: async (_appName, port) => probeAppPort(port)
|
|
153701
|
+
}), {
|
|
153702
|
+
stalePort: params.getLivePort(appName) ?? null,
|
|
153703
|
+
currentNodeId: params.currentNodeId
|
|
153704
|
+
})
|
|
153632
153705
|
});
|
|
153633
|
-
if (
|
|
153634
|
-
return
|
|
153635
|
-
|
|
153636
|
-
websocketPort = runtime.port;
|
|
153706
|
+
if (resolvedPort instanceof Response)
|
|
153707
|
+
return resolvedPort;
|
|
153708
|
+
websocketPort = resolvedPort;
|
|
153637
153709
|
}
|
|
153638
153710
|
let runtimeActivityLease;
|
|
153639
153711
|
try {
|
|
@@ -153720,6 +153792,7 @@ function registerPlatformAppProxy(params) {
|
|
|
153720
153792
|
addProxyMetric: params.addProxyMetric,
|
|
153721
153793
|
beginRuntimeActivity: params.beginRuntimeActivity,
|
|
153722
153794
|
admitRuntimeActivity: params.admitRuntimeActivity,
|
|
153795
|
+
resolveExistingOnlyRoute: params.resolveExistingOnlyRoute,
|
|
153723
153796
|
existingOnlyRuntimeProbe
|
|
153724
153797
|
});
|
|
153725
153798
|
}
|
|
@@ -153761,6 +153834,7 @@ function registerPlatformAppProxy(params) {
|
|
|
153761
153834
|
addProxyMetric: params.addProxyMetric,
|
|
153762
153835
|
beginRuntimeActivity: params.beginRuntimeActivity,
|
|
153763
153836
|
admitRuntimeActivity: params.admitRuntimeActivity,
|
|
153837
|
+
resolveExistingOnlyRoute: params.resolveExistingOnlyRoute,
|
|
153764
153838
|
existingOnlyRuntimeProbe
|
|
153765
153839
|
});
|
|
153766
153840
|
}
|
|
@@ -153797,6 +153871,8 @@ var init_server_platform_app_proxy = __esm({
|
|
|
153797
153871
|
init_server_platform_app_proxy_responses();
|
|
153798
153872
|
init_server_platform_hosted_analytics();
|
|
153799
153873
|
init_server_serving_plane_dependency_metrics();
|
|
153874
|
+
init_server_platform_app_proxy_routing();
|
|
153875
|
+
init_server_platform_app_proxy_routing();
|
|
153800
153876
|
init_static_file_routing();
|
|
153801
153877
|
init_server_platform_app_proxy_domain();
|
|
153802
153878
|
init_server_realtime_connection_limit();
|
|
@@ -170732,7 +170808,8 @@ var init_schema_app_lifecycle_operation = __esm({
|
|
|
170732
170808
|
'accepted', 'stopping_children', 'draining_runtime', 'stop_dispatched',
|
|
170733
170809
|
'runtime_absent', 'tenant_db_drop_pending', 'catalog_delete_pending', 'completed',
|
|
170734
170810
|
'blocked_ownership_ambiguous', 'blocked_active_work', 'blocked_runtime_outcome_unknown',
|
|
170735
|
-
'blocked_catalog_outcome_unknown', 'failed_tenant_db_cleanup', 'failed_catalog_cleanup'
|
|
170811
|
+
'blocked_catalog_outcome_unknown', 'failed_tenant_db_cleanup', 'failed_catalog_cleanup',
|
|
170812
|
+
'failed_delete_recovery_required'
|
|
170736
170813
|
)`
|
|
170737
170814
|
)
|
|
170738
170815
|
]
|
|
@@ -184114,6 +184191,12 @@ function clearCandidateCleanupFailureCode(error51) {
|
|
|
184114
184191
|
} catch {
|
|
184115
184192
|
}
|
|
184116
184193
|
}
|
|
184194
|
+
function getDeploymentFailureCause(error51) {
|
|
184195
|
+
if (!error51 || typeof error51 !== "object" && typeof error51 !== "function") return null;
|
|
184196
|
+
const direct = error51.deploymentFailureCause;
|
|
184197
|
+
if (typeof direct === "string" && DEPLOYMENT_FAILURE_CAUSE_PATTERN.test(direct)) return direct;
|
|
184198
|
+
return DEPLOYMENT_FAILURE_CAUSE_BY_ERROR.get(error51) ?? null;
|
|
184199
|
+
}
|
|
184117
184200
|
function attachDeploymentFailureStage(error51, stage) {
|
|
184118
184201
|
if (!error51 || typeof error51 !== "object" && typeof error51 !== "function") return error51;
|
|
184119
184202
|
const existing = error51.deploymentFailureStage;
|
|
@@ -184199,7 +184282,8 @@ function retry(code, message) {
|
|
|
184199
184282
|
}
|
|
184200
184283
|
function resolveGenericDeploymentFailurePolicy(input) {
|
|
184201
184284
|
const explicitCode = getStableDeploymentFailureCode(input.error);
|
|
184202
|
-
const
|
|
184285
|
+
const typedArtifactCause = getDeploymentFailureCause(input.error)?.startsWith("DEPLOY_ARTIFACT_");
|
|
184286
|
+
const code = (typedArtifactCause ? "DEPLOY_ARTIFACT_MATERIALIZE_FAILED" : explicitCode) ?? (input.stage === "candidate" ? classifyCandidateFailure(input.error, input.crashLogs) : defaultFailureCode(input.stage));
|
|
184203
184287
|
if (getCandidateCleanupFailureCode(input.error)) {
|
|
184204
184288
|
return {
|
|
184205
184289
|
status: 503,
|
|
@@ -184281,7 +184365,7 @@ function resolveStoredDeploymentFailurePolicy(stage, code) {
|
|
|
184281
184365
|
error: Object.assign(new Error(code), { code })
|
|
184282
184366
|
});
|
|
184283
184367
|
}
|
|
184284
|
-
var DEPLOYMENT_FAILURE_STAGE_FIELD, STABLE_CONTROL_PLANE_CODE, DEPLOYMENT_FAILURE_STAGE_SET, DEPLOYMENT_FAILURE_STAGE_BY_ERROR, CANDIDATE_CLEANUP_FAILURES, RETRYABLE_CODES, PLATFORM_OWNED_CODES, PLATFORM_OWNED_PREFIXES;
|
|
184368
|
+
var DEPLOYMENT_FAILURE_STAGE_FIELD, STABLE_CONTROL_PLANE_CODE, DEPLOYMENT_FAILURE_STAGE_SET, DEPLOYMENT_FAILURE_STAGE_BY_ERROR, CANDIDATE_CLEANUP_FAILURES, DEPLOYMENT_FAILURE_CAUSE_BY_ERROR, DEPLOYMENT_FAILURE_CAUSE_PATTERN, RETRYABLE_CODES, PLATFORM_OWNED_CODES, PLATFORM_OWNED_PREFIXES;
|
|
184285
184369
|
var init_deployment_failure_contract = __esm({
|
|
184286
184370
|
"../platform/src/deployment-failure-contract.ts"() {
|
|
184287
184371
|
"use strict";
|
|
@@ -184292,6 +184376,8 @@ var init_deployment_failure_contract = __esm({
|
|
|
184292
184376
|
DEPLOYMENT_FAILURE_STAGE_SET = new Set(DEPLOYMENT_FAILURE_STAGES);
|
|
184293
184377
|
DEPLOYMENT_FAILURE_STAGE_BY_ERROR = /* @__PURE__ */ new WeakMap();
|
|
184294
184378
|
CANDIDATE_CLEANUP_FAILURES = /* @__PURE__ */ new WeakSet();
|
|
184379
|
+
DEPLOYMENT_FAILURE_CAUSE_BY_ERROR = /* @__PURE__ */ new WeakMap();
|
|
184380
|
+
DEPLOYMENT_FAILURE_CAUSE_PATTERN = /^[A-Z][A-Z0-9_]{2,99}$/u;
|
|
184295
184381
|
RETRYABLE_CODES = /* @__PURE__ */ new Set([
|
|
184296
184382
|
"APP_DEPENDENCY_INSTALL_FAILED",
|
|
184297
184383
|
"ACTIVATION_EPOCH_CAS_FAILED",
|
|
@@ -184756,6 +184842,9 @@ function getDeploymentAttemptFailureCode(error51, stage, crashLogs) {
|
|
|
184756
184842
|
if (guardrailCode) return guardrailCode;
|
|
184757
184843
|
if (isMigrationDeployError(error51)) return String(error51.code);
|
|
184758
184844
|
if (isDeployDependencyVersionError(error51) || isCronManifestDeployError(error51)) return error51.code;
|
|
184845
|
+
if (getDeploymentFailureCause(error51)?.startsWith("DEPLOY_ARTIFACT_")) {
|
|
184846
|
+
return "DEPLOY_ARTIFACT_MATERIALIZE_FAILED";
|
|
184847
|
+
}
|
|
184759
184848
|
const stableCode = getStableDeploymentFailureCode(error51);
|
|
184760
184849
|
if (stableCode) return stableCode;
|
|
184761
184850
|
if (stage === "admission") return "DEPLOY_CONTRACT_INVALID";
|
|
@@ -185369,7 +185458,8 @@ function fleetSelection() {
|
|
|
185369
185458
|
...bindingSelection(),
|
|
185370
185459
|
authorityMode: appRuntimeDesiredState.authorityMode,
|
|
185371
185460
|
desiredRuntimeState: appRuntimeDesiredState.desiredRuntimeState,
|
|
185372
|
-
hasBackend: apps.hasBackend
|
|
185461
|
+
hasBackend: apps.hasBackend,
|
|
185462
|
+
appStatus: apps.status
|
|
185373
185463
|
};
|
|
185374
185464
|
}
|
|
185375
185465
|
function queryBindingRows(db) {
|
|
@@ -185488,6 +185578,10 @@ async function loadCanonicalTenantRouteFleetSnapshot(input) {
|
|
|
185488
185578
|
const desired = appRows[0];
|
|
185489
185579
|
if (desired.hasBackend && desired.desiredRuntimeState === "serving" && desired.desiredNodeId === input.nodeId) {
|
|
185490
185580
|
const joinedRows = appRows.filter((row) => row.instanceId !== null);
|
|
185581
|
+
if (joinedRows.length === 0 && desired.appStatus === "stopped") {
|
|
185582
|
+
removalTargets.push({ appId: desired.appId, appName: desired.appName });
|
|
185583
|
+
continue;
|
|
185584
|
+
}
|
|
185491
185585
|
try {
|
|
185492
185586
|
bindings.push(bindingFromRows(joinedRows));
|
|
185493
185587
|
} catch (error51) {
|
|
@@ -186001,6 +186095,16 @@ function appDeleteOperationResult(operation, options = {}) {
|
|
|
186001
186095
|
recoveryActivityEpoch: options.recovery.activityEpoch
|
|
186002
186096
|
} : {};
|
|
186003
186097
|
const blockedWithoutRecovery = operation.state === "blocked_active_work" && !options.recovery;
|
|
186098
|
+
const terminalRecoveryRequired = operation.state === "failed_delete_recovery_required";
|
|
186099
|
+
const recoveryDeadlineAnchor = operation.createdAt instanceof Date ? operation.createdAt : /* @__PURE__ */ new Date();
|
|
186100
|
+
const recoveryReconcileAnchor = operation.updatedAt instanceof Date ? operation.updatedAt : recoveryDeadlineAnchor;
|
|
186101
|
+
const recoveryEvidence = !isAppDeleteTerminalState(operation.state) ? {
|
|
186102
|
+
recoveryOwnerId: operation.ownerId,
|
|
186103
|
+
recoveryDeadlineAt: new Date(recoveryDeadlineAnchor.getTime() + RECOVERY_DEADLINE_MS).toISOString(),
|
|
186104
|
+
nextReconcileAt: new Date(
|
|
186105
|
+
recoveryReconcileAnchor.getTime() + RECOVERY_RECONCILE_INTERVAL_MS
|
|
186106
|
+
).toISOString()
|
|
186107
|
+
} : {};
|
|
186004
186108
|
return {
|
|
186005
186109
|
success: false,
|
|
186006
186110
|
deleted: operation.appName,
|
|
@@ -186013,6 +186117,13 @@ function appDeleteOperationResult(operation, options = {}) {
|
|
|
186013
186117
|
...operation.state === "completed" ? { success: true } : {},
|
|
186014
186118
|
...options.executorAvailable === void 0 ? {} : { executorAvailable: options.executorAvailable },
|
|
186015
186119
|
...operation.lastErrorCode ? { code: operation.lastErrorCode } : executorUnavailable ? { code: "PLATFORM_LIFECYCLE_EXECUTOR_UNAVAILABLE" } : {},
|
|
186120
|
+
...terminalRecoveryRequired ? {
|
|
186121
|
+
code: "APP_DELETE_RECOVERY_REQUIRED",
|
|
186122
|
+
failureClass: "PLATFORM_ACTION_REQUIRED",
|
|
186123
|
+
action: "CONTACT_SUPPORT",
|
|
186124
|
+
recoveryCauseCode: operation.lastErrorCode
|
|
186125
|
+
} : {},
|
|
186126
|
+
...recoveryEvidence,
|
|
186016
186127
|
...blockedRecovery,
|
|
186017
186128
|
...blockedWithoutRecovery ? {
|
|
186018
186129
|
code: "PLATFORM_ACTION_REQUIRED",
|
|
@@ -186021,7 +186132,7 @@ function appDeleteOperationResult(operation, options = {}) {
|
|
|
186021
186132
|
} : {}
|
|
186022
186133
|
};
|
|
186023
186134
|
}
|
|
186024
|
-
var APP_DELETE_ACTIVE_STATES2, APP_DELETE_TERMINAL_FAILURE_STATES2, APP_DELETE_TERMINAL_STATES, APP_DELETE_ADMISSION_BLOCKING_STATES, RETENTION_MS;
|
|
186135
|
+
var APP_DELETE_ACTIVE_STATES2, APP_DELETE_TERMINAL_FAILURE_STATES2, APP_DELETE_TERMINAL_STATES, APP_DELETE_ADMISSION_BLOCKING_STATES, RETENTION_MS, RECOVERY_DEADLINE_MS, RECOVERY_RECONCILE_INTERVAL_MS;
|
|
186025
186136
|
var init_app_delete_operation_store = __esm({
|
|
186026
186137
|
"../platform/src/app-delete-operation-store.ts"() {
|
|
186027
186138
|
"use strict";
|
|
@@ -186040,13 +186151,18 @@ var init_app_delete_operation_store = __esm({
|
|
|
186040
186151
|
"failed_tenant_db_cleanup",
|
|
186041
186152
|
"failed_catalog_cleanup"
|
|
186042
186153
|
];
|
|
186043
|
-
APP_DELETE_TERMINAL_FAILURE_STATES2 = [
|
|
186154
|
+
APP_DELETE_TERMINAL_FAILURE_STATES2 = [
|
|
186155
|
+
"blocked_catalog_outcome_unknown",
|
|
186156
|
+
"failed_delete_recovery_required"
|
|
186157
|
+
];
|
|
186044
186158
|
APP_DELETE_TERMINAL_STATES = ["completed", ...APP_DELETE_TERMINAL_FAILURE_STATES2];
|
|
186045
186159
|
APP_DELETE_ADMISSION_BLOCKING_STATES = [
|
|
186046
186160
|
...APP_DELETE_ACTIVE_STATES2,
|
|
186047
186161
|
...APP_DELETE_TERMINAL_FAILURE_STATES2
|
|
186048
186162
|
];
|
|
186049
186163
|
RETENTION_MS = 7 * 24 * 60 * 6e4;
|
|
186164
|
+
RECOVERY_DEADLINE_MS = 15 * 6e4;
|
|
186165
|
+
RECOVERY_RECONCILE_INTERVAL_MS = 3e4;
|
|
186050
186166
|
}
|
|
186051
186167
|
});
|
|
186052
186168
|
|
|
@@ -401444,7 +401560,11 @@ async function waitForDirectRunnerHealth(port, timeoutMs, dependencies = {}) {
|
|
|
401444
401560
|
while (now() - startedAt < timeoutMs) {
|
|
401445
401561
|
if (dependencies.shouldContinue && !await dependencies.shouldContinue()) return false;
|
|
401446
401562
|
const remainingMs = Math.max(1, timeoutMs - (now() - startedAt));
|
|
401447
|
-
|
|
401563
|
+
const probeTimeoutMs = Math.min(2e3, remainingMs);
|
|
401564
|
+
if (await probe(port, probeTimeoutMs, dependencies.healthPath)) return true;
|
|
401565
|
+
if (dependencies.fallbackHealthPath && dependencies.fallbackHealthPath !== dependencies.healthPath && await probe(port, probeTimeoutMs, dependencies.fallbackHealthPath)) {
|
|
401566
|
+
return true;
|
|
401567
|
+
}
|
|
401448
401568
|
const remainingAfterProbeMs = timeoutMs - (now() - startedAt);
|
|
401449
401569
|
if (remainingAfterProbeMs <= 0) break;
|
|
401450
401570
|
await sleep6(Math.min(DIRECT_RUNNER_HEALTH_POLL_INTERVAL_MS, remainingAfterProbeMs));
|
|
@@ -403162,7 +403282,8 @@ var init_direct_runner = __esm({
|
|
|
403162
403282
|
const healthy = await spawnLifecycle.waitFor(
|
|
403163
403283
|
this.waitForHealth(port, healthTimeoutMs, {
|
|
403164
403284
|
...options?.lifecycleRole === "candidate" ? { shouldContinue: () => this.isAlive(appName) } : {},
|
|
403165
|
-
...options?.lifecycleRole === "candidate" ? { healthPath: "/health/core-ready" } : {}
|
|
403285
|
+
...options?.lifecycleRole === "candidate" ? { healthPath: "/health/core-ready" } : {},
|
|
403286
|
+
...options?.lifecycleRole === "candidate" ? { fallbackHealthPath: "/health/live" } : {}
|
|
403166
403287
|
})
|
|
403167
403288
|
);
|
|
403168
403289
|
if (!healthy) {
|
|
@@ -424339,10 +424460,21 @@ async function publishIdleRouteAndAwaitAck(input) {
|
|
|
424339
424460
|
WHERE app_id = ${input.appId}
|
|
424340
424461
|
`);
|
|
424341
424462
|
const authority = rowsFromResult34(result2)[0];
|
|
424342
|
-
if (!authority
|
|
424463
|
+
if (!authority) {
|
|
424343
424464
|
fail31("RUNTIME_IDLE_ROUTE_AUTHORITY_MISSING");
|
|
424344
424465
|
}
|
|
424345
424466
|
const current = decodeAuthority(authority);
|
|
424467
|
+
if (current.mode === "tombstoned" && current.disposition === "tombstone") {
|
|
424468
|
+
const convergence = await assessAppServingRouteConvergence({
|
|
424469
|
+
db: input.db,
|
|
424470
|
+
eventId: authority.last_event_id
|
|
424471
|
+
});
|
|
424472
|
+
if (convergence.status !== "converged") fail31("RUNTIME_IDLE_ROUTE_ACK_PENDING");
|
|
424473
|
+
return;
|
|
424474
|
+
}
|
|
424475
|
+
if (authority.app_instance_id !== input.appInstanceId) {
|
|
424476
|
+
fail31("RUNTIME_IDLE_ROUTE_AUTHORITY_MISSING");
|
|
424477
|
+
}
|
|
424346
424478
|
if (current.appId !== input.appId || current.appInstanceId !== input.appInstanceId || current.mode !== "backend_only" && current.mode !== "fullstack" || !current.backend || current.backend.activationId !== input.activationId || current.backend.activationEpoch !== input.activationEpoch) {
|
|
424347
424479
|
fail31("RUNTIME_IDLE_ROUTE_IDENTITY_MISMATCH");
|
|
424348
424480
|
}
|
|
@@ -425511,6 +425643,7 @@ async function armExplicitRuntimeStop(input) {
|
|
|
425511
425643
|
]);
|
|
425512
425644
|
const drain = drainRows[0];
|
|
425513
425645
|
const activity = activityRows[0];
|
|
425646
|
+
const appDeleteWithoutActivityObservation = drain?.reason === "app_delete" && !activity;
|
|
425514
425647
|
if (!drain) throw new Error("RUNTIME_EXPLICIT_DRAIN_EXPIRED");
|
|
425515
425648
|
if (drain.state === "dispatched" || drain.state === "completed") {
|
|
425516
425649
|
const intents = await tx.select().from(runtimeStopIntents).where(eq60(runtimeStopIntents.drainRequestId, drain.id));
|
|
@@ -425523,7 +425656,7 @@ async function armExplicitRuntimeStop(input) {
|
|
|
425523
425656
|
if (!intents[0]) throw new Error("RUNTIME_EXPLICIT_STOP_REPLAY_INVALID");
|
|
425524
425657
|
return { intentId: intents[0].id, drainId: drain.id, replayed: true };
|
|
425525
425658
|
}
|
|
425526
|
-
if (drain.state !== "planned" || !activity || !activity.observationComplete || activity.activationId !== drain.activationId || activity.instanceId !== drain.instanceId || activity.nodeId !== drain.nodeId || activity.nodeEpoch !== drain.nodeEpoch || activity.httpActive !== 0 || activity.streamActive !== 0 || activity.websocketActive !== 0 || activity.workloadActive !== 0) {
|
|
425659
|
+
if (drain.state !== "planned" || !appDeleteWithoutActivityObservation && (!activity || !activity.observationComplete || activity.activationId !== drain.activationId || activity.instanceId !== drain.instanceId || activity.nodeId !== drain.nodeId || activity.nodeEpoch !== drain.nodeEpoch || activity.httpActive !== 0 || activity.streamActive !== 0 || activity.websocketActive !== 0 || activity.workloadActive !== 0)) {
|
|
425527
425660
|
throw new Error("RUNTIME_EXPLICIT_DRAIN_NOT_QUIESCENT");
|
|
425528
425661
|
}
|
|
425529
425662
|
const intent = await createRuntimeStopIntentInTransaction({
|
|
@@ -425539,7 +425672,11 @@ async function armExplicitRuntimeStop(input) {
|
|
|
425539
425672
|
now,
|
|
425540
425673
|
drainRequestId: drain.id
|
|
425541
425674
|
});
|
|
425542
|
-
const armed = await tx.update(runtimeDrainRequests).set({
|
|
425675
|
+
const armed = await tx.update(runtimeDrainRequests).set({
|
|
425676
|
+
state: "armed",
|
|
425677
|
+
activityEpoch: activity?.activityEpoch ?? drain.activityEpoch,
|
|
425678
|
+
updatedAt: now
|
|
425679
|
+
}).where(and56(eq60(runtimeDrainRequests.id, drain.id), eq60(runtimeDrainRequests.state, "planned"))).returning({ id: runtimeDrainRequests.id });
|
|
425543
425680
|
if (!armed[0]) throw new Error("RUNTIME_EXPLICIT_DRAIN_ARM_CAS_FAILED");
|
|
425544
425681
|
await tx.update(runtimeLifecycleRequests).set({ state: "executing", updatedAt: now }).where(eq60(runtimeLifecycleRequests.id, drain.lifecycleRequestId));
|
|
425545
425682
|
return { intentId: intent.id, drainId: drain.id, replayed: false };
|
|
@@ -428050,9 +428187,12 @@ function deriveRuntimeStopOperationState(input) {
|
|
|
428050
428187
|
if (input.drainState === "blocked" && input.terminalResultCode === "RUNTIME_STOP_OWNERSHIP_AMBIGUOUS") {
|
|
428051
428188
|
return "blocked_ambiguous_binding";
|
|
428052
428189
|
}
|
|
428053
|
-
if (input.drainState === "blocked" && [
|
|
428054
|
-
|
|
428055
|
-
|
|
428190
|
+
if (input.drainState === "blocked" && [
|
|
428191
|
+
"RUNTIME_EXPLICIT_DRAIN_TIMEOUT",
|
|
428192
|
+
"RUNTIME_EXPLICIT_DRAIN_EXPIRED",
|
|
428193
|
+
"RUNTIME_EXPLICIT_DRAIN_NOT_QUIESCENT",
|
|
428194
|
+
"RUNTIME_STOP_INTENT_ACTIVITY_CHANGED"
|
|
428195
|
+
].includes(input.terminalResultCode ?? "")) {
|
|
428056
428196
|
return "blocked_active_work";
|
|
428057
428197
|
}
|
|
428058
428198
|
if (input.requestState === "failed" || input.drainState === "cancelled") return "failed";
|
|
@@ -428074,10 +428214,7 @@ async function loadAppDeleteRuntimeRecoveryReceipt(input) {
|
|
|
428074
428214
|
drainReason: runtimeDrainRequests.reason,
|
|
428075
428215
|
intentReason: runtimeStopIntents.reason,
|
|
428076
428216
|
intentCorrelationId: runtimeStopIntents.correlationId
|
|
428077
|
-
}).from(runtimeLifecycleRequests).leftJoin(
|
|
428078
|
-
runtimeDrainRequests,
|
|
428079
|
-
eq70(runtimeDrainRequests.lifecycleRequestId, runtimeLifecycleRequests.id)
|
|
428080
|
-
).leftJoin(runtimeStopIntents, eq70(runtimeStopIntents.drainRequestId, runtimeDrainRequests.id)).where(
|
|
428217
|
+
}).from(runtimeLifecycleRequests).leftJoin(runtimeDrainRequests, eq70(runtimeDrainRequests.lifecycleRequestId, runtimeLifecycleRequests.id)).leftJoin(runtimeStopIntents, eq70(runtimeStopIntents.drainRequestId, runtimeDrainRequests.id)).where(
|
|
428081
428218
|
and66(
|
|
428082
428219
|
eq70(runtimeLifecycleRequests.appId, input.appId),
|
|
428083
428220
|
eq70(runtimeLifecycleRequests.action, "app_delete"),
|
|
@@ -428092,7 +428229,8 @@ async function loadAppDeleteRuntimeRecoveryReceipt(input) {
|
|
|
428092
428229
|
requestState: row.requestState,
|
|
428093
428230
|
drainState: row.drainState,
|
|
428094
428231
|
terminalResultCode: row.terminalResultCode
|
|
428095
|
-
}) !== "blocked_active_work")
|
|
428232
|
+
}) !== "blocked_active_work")
|
|
428233
|
+
return null;
|
|
428096
428234
|
const ownerId = row.leaseOwner;
|
|
428097
428235
|
if (!ownerId || !row.deadlineAt || !Number.isSafeInteger(Number(row.activityEpoch))) return null;
|
|
428098
428236
|
return {
|
|
@@ -428184,10 +428322,12 @@ var init_app_delete_catalog_finalizer = __esm({
|
|
|
428184
428322
|
});
|
|
428185
428323
|
|
|
428186
428324
|
// ../platform/src/app-delete-operation-controller.ts
|
|
428325
|
+
var APP_DELETE_RECOVERY_DEADLINE_MS;
|
|
428187
428326
|
var init_app_delete_operation_controller = __esm({
|
|
428188
428327
|
"../platform/src/app-delete-operation-controller.ts"() {
|
|
428189
428328
|
"use strict";
|
|
428190
428329
|
init_app_delete_operation_store();
|
|
428330
|
+
APP_DELETE_RECOVERY_DEADLINE_MS = 15 * 6e4;
|
|
428191
428331
|
}
|
|
428192
428332
|
});
|
|
428193
428333
|
|
|
@@ -428338,7 +428478,7 @@ function publicAppDeleteErrorCode(error51) {
|
|
|
428338
428478
|
return PUBLICLY_NORMALIZED_APP_DELETE_CODES.has(code) ? "APP_DELETE_OPERATION_PENDING" : code;
|
|
428339
428479
|
}
|
|
428340
428480
|
function appDeleteFailureWithReceipt(error51, receipt) {
|
|
428341
|
-
const code = publicAppDeleteErrorCode(error51);
|
|
428481
|
+
const code = receipt.state === "failed_delete_recovery_required" ? "APP_DELETE_RECOVERY_REQUIRED" : publicAppDeleteErrorCode(error51);
|
|
428342
428482
|
return Object.assign(new Error(code, { cause: error51 }), {
|
|
428343
428483
|
code,
|
|
428344
428484
|
operationId: receipt.id,
|
|
@@ -428348,7 +428488,7 @@ function appDeleteFailureWithReceipt(error51, receipt) {
|
|
|
428348
428488
|
});
|
|
428349
428489
|
}
|
|
428350
428490
|
function appDeleteFailureHttpStatus(state2) {
|
|
428351
|
-
return state2.startsWith("blocked_") ? 409 : 503;
|
|
428491
|
+
return state2.startsWith("blocked_") || state2 === "failed_delete_recovery_required" ? 409 : 503;
|
|
428352
428492
|
}
|
|
428353
428493
|
var PUBLICLY_NORMALIZED_APP_DELETE_CODES;
|
|
428354
428494
|
var init_app_delete_diagnostic = __esm({
|
|
@@ -429573,6 +429713,7 @@ async function bootstrapPlatformRuntime(params) {
|
|
|
429573
429713
|
subdomainRegex,
|
|
429574
429714
|
getBunServer: params.getBunServer,
|
|
429575
429715
|
domainLookupDb: params.db,
|
|
429716
|
+
resolveExistingOnlyRoute: routeProjectionRuntime.resolveExistingOnlyRoute,
|
|
429576
429717
|
async findActiveDomainApp(host) {
|
|
429577
429718
|
const rows4 = await params.db.select({
|
|
429578
429719
|
name: appsTable.name,
|
|
@@ -429916,8 +430057,7 @@ async function bootstrapPlatformRuntime(params) {
|
|
|
429916
430057
|
logger3.error("[ws-gateway] realtime usage metering bootstrap failed:", message);
|
|
429917
430058
|
}
|
|
429918
430059
|
startHeartbeat();
|
|
429919
|
-
|
|
429920
|
-
logger3.log(`[ws-gateway] WS Gateway active (max ${limits.maxConnectionsPerApp}/app, ${limits.maxTotalConnections} total)`);
|
|
430060
|
+
logger3.log(`[ws-gateway] WS Gateway active (max ${getGatewayLimits().maxConnectionsPerApp}/app, ${getGatewayLimits().maxTotalConnections} total)`);
|
|
429921
430061
|
const startAfterListen = async () => {
|
|
429922
430062
|
await routeProjectionRuntime.startAfterRecovery(autoRecoveryRuntime);
|
|
429923
430063
|
explicitStopReconciler.start();
|
|
@@ -448229,7 +448369,10 @@ var APP_DELETE_ACTIVE_STATES = /* @__PURE__ */ new Set([
|
|
|
448229
448369
|
"failed_tenant_db_cleanup",
|
|
448230
448370
|
"failed_catalog_cleanup"
|
|
448231
448371
|
]);
|
|
448232
|
-
var APP_DELETE_TERMINAL_FAILURE_STATES = /* @__PURE__ */ new Set([
|
|
448372
|
+
var APP_DELETE_TERMINAL_FAILURE_STATES = /* @__PURE__ */ new Set([
|
|
448373
|
+
"blocked_catalog_outcome_unknown",
|
|
448374
|
+
"failed_delete_recovery_required"
|
|
448375
|
+
]);
|
|
448233
448376
|
var CAPABILITY_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/u;
|
|
448234
448377
|
function createAppDeleteStatusLoader(getQueryDef2) {
|
|
448235
448378
|
return async ({ ctx, args, result: result2 }) => {
|
|
@@ -448331,7 +448474,7 @@ import { randomUUID as randomUUID7 } from "node:crypto";
|
|
|
448331
448474
|
var POSTGRES_CODE_PATTERN = /^[0-9A-Z]{5}$/u;
|
|
448332
448475
|
var SAFE_CORRELATION_PATTERN = /^[A-Za-z0-9_-]{8,128}$/u;
|
|
448333
448476
|
var SAFE_APP_DELETE_OPERATION_PATTERN = /^app_delete_(?:[a-f0-9]{32}|[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12})$/u;
|
|
448334
|
-
var SAFE_APP_DELETE_STATE_PATTERN = /^(?:accepted|stopping_children|draining_runtime|stop_dispatched|runtime_absent|tenant_db_drop_pending|catalog_delete_pending|completed|blocked_ownership_ambiguous|blocked_active_work|blocked_runtime_outcome_unknown|failed_tenant_db_cleanup|failed_catalog_cleanup)$/u;
|
|
448477
|
+
var SAFE_APP_DELETE_STATE_PATTERN = /^(?:accepted|stopping_children|draining_runtime|stop_dispatched|runtime_absent|tenant_db_drop_pending|catalog_delete_pending|completed|blocked_ownership_ambiguous|blocked_active_work|blocked_runtime_outcome_unknown|blocked_catalog_outcome_unknown|failed_tenant_db_cleanup|failed_catalog_cleanup|failed_delete_recovery_required)$/u;
|
|
448335
448478
|
var SAFE_PUBLIC_ERROR_CODE_PATTERN = /^[A-Z][A-Z0-9_]{2,127}$/u;
|
|
448336
448479
|
var SAFE_RETRY_CLASSES = /* @__PURE__ */ new Set([
|
|
448337
448480
|
"operator-action",
|