@percher/core 0.3.0 → 0.4.1
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/commands/account.d.ts +24 -14
- package/dist/commands/account.d.ts.map +1 -1
- package/dist/commands/account.js +17 -4
- package/dist/commands/account.js.map +1 -1
- package/dist/commands/admin-reconcile-routes.d.ts +18 -0
- package/dist/commands/admin-reconcile-routes.d.ts.map +1 -0
- package/dist/commands/admin-reconcile-routes.js +22 -0
- package/dist/commands/admin-reconcile-routes.js.map +1 -0
- package/dist/commands/ai-files.d.ts +5 -17
- package/dist/commands/ai-files.d.ts.map +1 -1
- package/dist/commands/ai-files.js +3 -4
- package/dist/commands/ai-files.js.map +1 -1
- package/dist/commands/alerts.d.ts +69 -0
- package/dist/commands/alerts.d.ts.map +1 -0
- package/dist/commands/alerts.js +80 -0
- package/dist/commands/alerts.js.map +1 -0
- package/dist/commands/app-resources.d.ts +30 -0
- package/dist/commands/app-resources.d.ts.map +1 -0
- package/dist/commands/app-resources.js +34 -0
- package/dist/commands/app-resources.js.map +1 -0
- package/dist/commands/app-topology.d.ts +18 -0
- package/dist/commands/app-topology.d.ts.map +1 -0
- package/dist/commands/app-topology.js +25 -0
- package/dist/commands/app-topology.js.map +1 -0
- package/dist/commands/billing.d.ts +8 -8
- package/dist/commands/billing.d.ts.map +1 -1
- package/dist/commands/billing.js +1 -1
- package/dist/commands/billing.js.map +1 -1
- package/dist/commands/continue.d.ts +1 -1
- package/dist/commands/create.d.ts +2 -12
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +1 -1
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/dashboard.d.ts +2 -8
- package/dist/commands/dashboard.d.ts.map +1 -1
- package/dist/commands/dashboard.js +1 -1
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/data-export.d.ts +2 -8
- package/dist/commands/data-export.d.ts.map +1 -1
- package/dist/commands/data-export.js +1 -1
- package/dist/commands/data-export.js.map +1 -1
- package/dist/commands/data.d.ts +2 -8
- package/dist/commands/data.d.ts.map +1 -1
- package/dist/commands/data.js +1 -1
- package/dist/commands/data.js.map +1 -1
- package/dist/commands/delete.d.ts +2 -8
- package/dist/commands/delete.d.ts.map +1 -1
- package/dist/commands/delete.js +1 -1
- package/dist/commands/delete.js.map +1 -1
- package/dist/commands/deploys.d.ts +4 -28
- package/dist/commands/deploys.d.ts.map +1 -1
- package/dist/commands/deploys.js +1 -1
- package/dist/commands/deploys.js.map +1 -1
- package/dist/commands/dev.d.ts +2 -6
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +3 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/diagnose.d.ts +2 -22
- package/dist/commands/diagnose.d.ts.map +1 -1
- package/dist/commands/diagnose.js +1 -1
- package/dist/commands/diagnose.js.map +1 -1
- package/dist/commands/doctor.d.ts +20 -35
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +42 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/domains.d.ts +5 -27
- package/dist/commands/domains.d.ts.map +1 -1
- package/dist/commands/domains.js +1 -1
- package/dist/commands/domains.js.map +1 -1
- package/dist/commands/env-scan.js +1 -1
- package/dist/commands/env-scan.js.map +1 -1
- package/dist/commands/env.d.ts +4 -20
- package/dist/commands/env.d.ts.map +1 -1
- package/dist/commands/env.js +1 -1
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/export.d.ts +1 -1
- package/dist/commands/forgejo.d.ts +45 -0
- package/dist/commands/forgejo.d.ts.map +1 -0
- package/dist/commands/forgejo.js +125 -0
- package/dist/commands/forgejo.js.map +1 -0
- package/dist/commands/generate.d.ts +2 -6
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +1 -1
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/github.d.ts +4 -15
- package/dist/commands/github.d.ts.map +1 -1
- package/dist/commands/github.js +17 -1
- package/dist/commands/github.js.map +1 -1
- package/dist/commands/import-project.d.ts +13 -9
- package/dist/commands/import-project.d.ts.map +1 -1
- package/dist/commands/import-project.js +73 -22
- package/dist/commands/import-project.js.map +1 -1
- package/dist/commands/init.d.ts +26 -11
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +103 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/insights.d.ts +2 -6
- package/dist/commands/insights.d.ts.map +1 -1
- package/dist/commands/insights.js +1 -1
- package/dist/commands/insights.js.map +1 -1
- package/dist/commands/login.d.ts +2 -8
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +22 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logs.d.ts +25 -10
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +65 -5
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/mcp.d.ts +2 -2
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +1 -1
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/migrate-supabase-map.d.ts +171 -0
- package/dist/commands/migrate-supabase-map.d.ts.map +1 -0
- package/dist/commands/migrate-supabase-map.js +452 -0
- package/dist/commands/migrate-supabase-map.js.map +1 -0
- package/dist/commands/migrate-supabase-schema.d.ts +67 -0
- package/dist/commands/migrate-supabase-schema.d.ts.map +1 -0
- package/dist/commands/migrate-supabase-schema.js +321 -0
- package/dist/commands/migrate-supabase-schema.js.map +1 -0
- package/dist/commands/migrate-supabase-scripts.d.ts +64 -0
- package/dist/commands/migrate-supabase-scripts.d.ts.map +1 -0
- package/dist/commands/migrate-supabase-scripts.js +564 -0
- package/dist/commands/migrate-supabase-scripts.js.map +1 -0
- package/dist/commands/migrate-supabase-sdk.d.ts +133 -0
- package/dist/commands/migrate-supabase-sdk.d.ts.map +1 -0
- package/dist/commands/migrate-supabase-sdk.js +1119 -0
- package/dist/commands/migrate-supabase-sdk.js.map +1 -0
- package/dist/commands/migrate-supabase-walker.d.ts +93 -0
- package/dist/commands/migrate-supabase-walker.d.ts.map +1 -0
- package/dist/commands/migrate-supabase-walker.js +413 -0
- package/dist/commands/migrate-supabase-walker.js.map +1 -0
- package/dist/commands/migrate-supabase.d.ts +81 -0
- package/dist/commands/migrate-supabase.d.ts.map +1 -0
- package/dist/commands/migrate-supabase.js +579 -0
- package/dist/commands/migrate-supabase.js.map +1 -0
- package/dist/commands/open.d.ts +2 -6
- package/dist/commands/open.d.ts.map +1 -1
- package/dist/commands/open.js +1 -1
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/publish-api-error.d.ts +46 -0
- package/dist/commands/publish-api-error.d.ts.map +1 -0
- package/dist/commands/publish-api-error.js +307 -0
- package/dist/commands/publish-api-error.js.map +1 -0
- package/dist/commands/publish-failure.d.ts.map +1 -1
- package/dist/commands/publish-failure.js +11 -3
- package/dist/commands/publish-failure.js.map +1 -1
- package/dist/commands/publish-node.d.ts +5 -2
- package/dist/commands/publish-node.d.ts.map +1 -1
- package/dist/commands/publish-node.js +7 -3
- package/dist/commands/publish-node.js.map +1 -1
- package/dist/commands/publish.d.ts +58 -17
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +407 -145
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/push.d.ts +2 -12
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +25 -7
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/redeploy.d.ts +2 -8
- package/dist/commands/redeploy.d.ts.map +1 -1
- package/dist/commands/redeploy.js +20 -16
- package/dist/commands/redeploy.js.map +1 -1
- package/dist/commands/rename.d.ts +2 -8
- package/dist/commands/rename.d.ts.map +1 -1
- package/dist/commands/rename.js +1 -1
- package/dist/commands/rename.js.map +1 -1
- package/dist/commands/reproduce.d.ts +2 -8
- package/dist/commands/reproduce.d.ts.map +1 -1
- package/dist/commands/reproduce.js +1 -1
- package/dist/commands/reproduce.js.map +1 -1
- package/dist/commands/reset-superuser.d.ts +2 -16
- package/dist/commands/reset-superuser.d.ts.map +1 -1
- package/dist/commands/reset-superuser.js +1 -1
- package/dist/commands/reset-superuser.js.map +1 -1
- package/dist/commands/restore.d.ts +7 -22
- package/dist/commands/restore.d.ts.map +1 -1
- package/dist/commands/restore.js +1 -1
- package/dist/commands/restore.js.map +1 -1
- package/dist/commands/resume.d.ts +2 -6
- package/dist/commands/resume.d.ts.map +1 -1
- package/dist/commands/resume.js +1 -1
- package/dist/commands/resume.js.map +1 -1
- package/dist/commands/rollback.d.ts +4 -9
- package/dist/commands/rollback.d.ts.map +1 -1
- package/dist/commands/rollback.js +3 -2
- package/dist/commands/rollback.js.map +1 -1
- package/dist/commands/sharing.d.ts +48 -0
- package/dist/commands/sharing.d.ts.map +1 -0
- package/dist/commands/sharing.js +85 -0
- package/dist/commands/sharing.js.map +1 -0
- package/dist/commands/status.d.ts +29 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +48 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/transfers.d.ts +34 -0
- package/dist/commands/transfers.d.ts.map +1 -0
- package/dist/commands/transfers.js +62 -0
- package/dist/commands/transfers.js.map +1 -0
- package/dist/commands/unsuspend.d.ts +2 -6
- package/dist/commands/unsuspend.d.ts.map +1 -1
- package/dist/commands/unsuspend.js +1 -1
- package/dist/commands/unsuspend.js.map +1 -1
- package/dist/commands/versions.d.ts +2 -6
- package/dist/commands/versions.d.ts.map +1 -1
- package/dist/commands/versions.js +1 -1
- package/dist/commands/versions.js.map +1 -1
- package/dist/commands/wait-deploy.d.ts +2 -12
- package/dist/commands/wait-deploy.d.ts.map +1 -1
- package/dist/commands/wait-deploy.js +5 -4
- package/dist/commands/wait-deploy.js.map +1 -1
- package/dist/context.d.ts +15 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/detect.d.ts +11 -0
- package/dist/detect.d.ts.map +1 -1
- package/dist/detect.js +31 -8
- package/dist/detect.js.map +1 -1
- package/dist/env-scan-source.js +1 -1
- package/dist/env-scan-source.js.map +1 -1
- package/dist/error-classifier.d.ts +17 -0
- package/dist/error-classifier.d.ts.map +1 -1
- package/dist/error-classifier.js +95 -9
- package/dist/error-classifier.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/event-renderer.d.ts +17 -0
- package/dist/event-renderer.d.ts.map +1 -0
- package/dist/event-renderer.js +130 -0
- package/dist/event-renderer.js.map +1 -0
- package/dist/index.d.ts +63 -47
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -40
- package/dist/index.js.map +1 -1
- package/dist/plans.d.ts +70 -5
- package/dist/plans.d.ts.map +1 -1
- package/dist/plans.js +83 -18
- package/dist/plans.js.map +1 -1
- package/dist/poll-deployment.d.ts +13 -1
- package/dist/poll-deployment.d.ts.map +1 -1
- package/dist/poll-deployment.js +37 -1
- package/dist/poll-deployment.js.map +1 -1
- package/dist/publish-retry.d.ts +29 -0
- package/dist/publish-retry.d.ts.map +1 -0
- package/dist/publish-retry.js +224 -0
- package/dist/publish-retry.js.map +1 -0
- package/dist/recovery.d.ts +60 -3
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +24 -1
- package/dist/recovery.js.map +1 -1
- package/dist/static-docker.d.ts +77 -0
- package/dist/static-docker.d.ts.map +1 -0
- package/dist/static-docker.js +105 -0
- package/dist/static-docker.js.map +1 -0
- package/dist/structured-error-codes.d.ts +30 -0
- package/dist/structured-error-codes.d.ts.map +1 -0
- package/dist/structured-error-codes.js +86 -0
- package/dist/structured-error-codes.js.map +1 -0
- package/dist/tarball.d.ts +11 -0
- package/dist/tarball.d.ts.map +1 -1
- package/dist/tarball.js +31 -10
- package/dist/tarball.js.map +1 -1
- package/dist/templates/ai-files/cursor-percher-mdc.d.ts.map +1 -1
- package/dist/templates/ai-files/cursor-percher-mdc.js +12 -9
- package/dist/templates/ai-files/cursor-percher-mdc.js.map +1 -1
- package/dist/templates.js +11 -11
- package/dist/templates.js.map +1 -1
- package/dist/watcher.js +1 -1
- package/dist/watcher.js.map +1 -1
- package/package.json +7 -2
package/dist/plans.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pool sizes are derived from `docs/operations/capacity-model.md`'s
|
|
3
|
+
* "Konkreta startpooler" table. They are the *sellable* totals per
|
|
4
|
+
* tier — the user can fill them with any mix of apps × sizes as
|
|
5
|
+
* long as the sum fits. Per-app `memory` / `cpu` are now defaults
|
|
6
|
+
* (used when `[resources]` is omitted in percher.toml), not hard
|
|
7
|
+
* ceilings.
|
|
8
|
+
*
|
|
9
|
+
* `apps` is a hard cap (anti-abuse backstop) enforced at app-create;
|
|
10
|
+
* pool dimensions are the load-bearing constraint.
|
|
11
|
+
*/
|
|
1
12
|
export const PLAN_CATALOG = {
|
|
2
13
|
free: {
|
|
3
14
|
label: "Free",
|
|
4
15
|
priceEur: 0,
|
|
5
16
|
limits: {
|
|
6
|
-
apps:
|
|
17
|
+
apps: 3,
|
|
7
18
|
deploysPerMonth: 50,
|
|
8
19
|
deploysPerHour: 12,
|
|
9
20
|
memory: "256mb",
|
|
@@ -21,23 +32,34 @@ export const PLAN_CATALOG = {
|
|
|
21
32
|
cronJobs: 1,
|
|
22
33
|
storageMb: 500,
|
|
23
34
|
instances: 1,
|
|
24
|
-
slaUptime: null,
|
|
25
|
-
supportResponseTime: null,
|
|
26
35
|
kvStorageMb: 10,
|
|
27
36
|
uptimeIntervalSec: 0,
|
|
28
37
|
dailyLiveDeploys: 50,
|
|
29
38
|
dailyPreviewDeploys: 25,
|
|
39
|
+
userConcurrentDeploys: 2,
|
|
40
|
+
// 512 MB pool / 0.5 vCPU pool / 1 GB disk — per capacity-model
|
|
41
|
+
// CX22 line. Free relies on auto-sleep as the pressure valve,
|
|
42
|
+
// so committed actual usage is ≈ 0 when idle.
|
|
43
|
+
ramPoolMb: 512,
|
|
44
|
+
vcpuPool: 0.5,
|
|
45
|
+
diskPoolMb: 1_000,
|
|
30
46
|
},
|
|
31
47
|
},
|
|
32
48
|
starter: {
|
|
33
49
|
label: "Starter",
|
|
34
50
|
priceEur: 3,
|
|
35
51
|
limits: {
|
|
36
|
-
apps:
|
|
52
|
+
apps: 10,
|
|
37
53
|
deploysPerMonth: 200,
|
|
38
54
|
deploysPerHour: 30,
|
|
39
55
|
memory: "512mb",
|
|
40
|
-
|
|
56
|
+
// 0.25 default × 1 instance (Starter cap) = 0.25, fits the 1.0
|
|
57
|
+
// vCPU pool with generous headroom for users to bump per-app
|
|
58
|
+
// cpu in their toml. FUTURE21 rounded the pool from 0.75 to a
|
|
59
|
+
// full vCPU for round-number sellability — CPU isn't a hard
|
|
60
|
+
// capacity gate (kernel time-shares; we monitor cgroup
|
|
61
|
+
// throttling), so a half-vCPU bump costs nothing operationally.
|
|
62
|
+
cpu: 0.25,
|
|
41
63
|
pids: 256,
|
|
42
64
|
activePreviewsPerApp: 3,
|
|
43
65
|
customDomainsPerApp: 2,
|
|
@@ -51,23 +73,32 @@ export const PLAN_CATALOG = {
|
|
|
51
73
|
cronJobs: 3,
|
|
52
74
|
storageMb: 5000,
|
|
53
75
|
instances: 1,
|
|
54
|
-
slaUptime: null,
|
|
55
|
-
supportResponseTime: "72h email",
|
|
56
76
|
kvStorageMb: 50,
|
|
57
77
|
uptimeIntervalSec: 300,
|
|
58
78
|
dailyLiveDeploys: 100,
|
|
59
79
|
dailyPreviewDeploys: 50,
|
|
80
|
+
userConcurrentDeploys: 3,
|
|
81
|
+
// 1.5 GB / 1.0 vCPU / 5 GB disk — capacity-model CX22 line.
|
|
82
|
+
// FUTURE21 rounded vcpuPool from 0.75 → 1.0 for round-number
|
|
83
|
+
// sellability (CPU is time-shared by the kernel, not hard-gated).
|
|
84
|
+
ramPoolMb: 1_536,
|
|
85
|
+
vcpuPool: 1.0,
|
|
86
|
+
diskPoolMb: 5_000,
|
|
60
87
|
},
|
|
61
88
|
},
|
|
62
89
|
maker: {
|
|
63
90
|
label: "Maker",
|
|
64
91
|
priceEur: 12,
|
|
65
92
|
limits: {
|
|
66
|
-
apps:
|
|
93
|
+
apps: 20,
|
|
67
94
|
deploysPerMonth: 500,
|
|
68
95
|
deploysPerHour: 60,
|
|
69
96
|
memory: "1gb",
|
|
70
|
-
|
|
97
|
+
// 0.5 default × 2 instances (Maker cap) = 1.0, fits 2 vCPU
|
|
98
|
+
// pool with 1.0 headroom for users to bump per-app cpu. Was
|
|
99
|
+
// 1 — that saturated the pool with a single app × 2 instances
|
|
100
|
+
// and made the documented multi-app cap meaningless on CPU.
|
|
101
|
+
cpu: 0.5,
|
|
71
102
|
pids: 512,
|
|
72
103
|
activePreviewsPerApp: 3,
|
|
73
104
|
customDomainsPerApp: 5,
|
|
@@ -79,25 +110,41 @@ export const PLAN_CATALOG = {
|
|
|
79
110
|
logRetentionDays: 30,
|
|
80
111
|
buildLogRetentionDays: 30,
|
|
81
112
|
cronJobs: 10,
|
|
82
|
-
storageMb:
|
|
113
|
+
storageMb: 25_000,
|
|
83
114
|
instances: 2,
|
|
84
|
-
slaUptime: "99.5%",
|
|
85
|
-
supportResponseTime: "24h email",
|
|
86
115
|
kvStorageMb: 200,
|
|
87
116
|
uptimeIntervalSec: 60,
|
|
88
117
|
dailyLiveDeploys: 200,
|
|
89
118
|
dailyPreviewDeploys: 100,
|
|
119
|
+
userConcurrentDeploys: 5,
|
|
120
|
+
// 4 GB / 2 vCPU / 25 GB disk — capacity-model CX22 line.
|
|
121
|
+
// FUTURE21 halved diskPoolMb from 50 GB → 25 GB to keep the
|
|
122
|
+
// promised pool fits-on-disk-honestly on CX32 (80 GB local disk
|
|
123
|
+
// minus platform overhead). storageMb tracks diskPoolMb so the
|
|
124
|
+
// worst-case PB-app charge still fits exactly one PB-app per
|
|
125
|
+
// account (the existing 1-PB-app-per-account invariant).
|
|
126
|
+
// Worst-case committed (pool + 20 PB-sidecars) = 6.56 GB RAM,
|
|
127
|
+
// which is why Maker is closed on CX22 (committed_budget = 4.4 GB).
|
|
128
|
+
ramPoolMb: 4_096,
|
|
129
|
+
vcpuPool: 2,
|
|
130
|
+
diskPoolMb: 25_000,
|
|
90
131
|
},
|
|
91
132
|
},
|
|
92
133
|
pro: {
|
|
93
134
|
label: "Pro",
|
|
94
135
|
priceEur: 29,
|
|
95
136
|
limits: {
|
|
96
|
-
apps:
|
|
137
|
+
apps: 40,
|
|
97
138
|
deploysPerMonth: "unlimited",
|
|
98
139
|
deploysPerHour: 120,
|
|
99
|
-
memory: "
|
|
100
|
-
|
|
140
|
+
memory: "1gb",
|
|
141
|
+
// 1.0 default × 4 instances (Pro cap) = 4.0, fits 4 vCPU pool
|
|
142
|
+
// exactly with no headroom. Was 2 — that would have made any
|
|
143
|
+
// multi-instance deploy exceed the pool at default cpu. Users
|
|
144
|
+
// can drop per-app cpu in toml to leave headroom for more
|
|
145
|
+
// apps, or bump it on a single-instance app up to the full
|
|
146
|
+
// pool (= dedicated 4 vCPU).
|
|
147
|
+
cpu: 1,
|
|
101
148
|
pids: 1024,
|
|
102
149
|
activePreviewsPerApp: 3,
|
|
103
150
|
customDomainsPerApp: 10,
|
|
@@ -109,14 +156,24 @@ export const PLAN_CATALOG = {
|
|
|
109
156
|
logRetentionDays: 90,
|
|
110
157
|
buildLogRetentionDays: 90,
|
|
111
158
|
cronJobs: 25,
|
|
112
|
-
storageMb:
|
|
159
|
+
storageMb: 75_000,
|
|
113
160
|
instances: 4,
|
|
114
|
-
slaUptime: "99.9%",
|
|
115
|
-
supportResponseTime: "8h email + priority Discord",
|
|
116
161
|
kvStorageMb: 1000,
|
|
117
162
|
uptimeIntervalSec: 30,
|
|
118
163
|
dailyLiveDeploys: 1000,
|
|
119
164
|
dailyPreviewDeploys: 500,
|
|
165
|
+
userConcurrentDeploys: 20,
|
|
166
|
+
// 10 GB / 4 vCPU / 75 GB disk — capacity-model CX22 line.
|
|
167
|
+
// FUTURE21 sized diskPoolMb down from 200 GB → 75 GB so the
|
|
168
|
+
// promised pool actually fits on the boxes we run (CX42 has
|
|
169
|
+
// 160 GB local disk — 75 GB pool leaves room for platform +
|
|
170
|
+
// one more paying customer). storageMb tracks diskPoolMb so a
|
|
171
|
+
// single PB-app per account remains the worst-case reservation.
|
|
172
|
+
// Worst-case committed (pool + 40 PB-sidecars) = 15.36 GB RAM,
|
|
173
|
+
// which is why Pro still requires CX42 minimum.
|
|
174
|
+
ramPoolMb: 10_240,
|
|
175
|
+
vcpuPool: 4,
|
|
176
|
+
diskPoolMb: 75_000,
|
|
120
177
|
},
|
|
121
178
|
},
|
|
122
179
|
};
|
|
@@ -158,6 +215,7 @@ export function getEffectivePlanLimits(plan, isAdmin = false) {
|
|
|
158
215
|
deploysPerHour: INF,
|
|
159
216
|
dailyLiveDeploys: INF,
|
|
160
217
|
dailyPreviewDeploys: INF,
|
|
218
|
+
userConcurrentDeploys: INF,
|
|
161
219
|
activePreviewsPerApp: INF,
|
|
162
220
|
customDomainsPerApp: INF,
|
|
163
221
|
autoSleep: false,
|
|
@@ -168,6 +226,13 @@ export function getEffectivePlanLimits(plan, isAdmin = false) {
|
|
|
168
226
|
buildLogRetentionDays: INF,
|
|
169
227
|
cronJobs: INF,
|
|
170
228
|
kvStorageMb: INF,
|
|
229
|
+
// FUTURE20 Fas 3 — admin bypasses pool checks too. Otherwise
|
|
230
|
+
// the operator's own apps would hit "your tier pool is full"
|
|
231
|
+
// when running platform-management apps (admin tooling,
|
|
232
|
+
// dogfood deploys, etc.).
|
|
233
|
+
ramPoolMb: INF,
|
|
234
|
+
vcpuPool: INF,
|
|
235
|
+
diskPoolMb: INF,
|
|
171
236
|
// Admin probes still happen at the pro cadence (30s) — no point in
|
|
172
237
|
// trying to make this "infinite", and faster than 30s starts to
|
|
173
238
|
// matter for outbound bandwidth without paying for itself.
|
package/dist/plans.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plans.js","sourceRoot":"","sources":["../src/plans.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plans.js","sourceRoot":"","sources":["../src/plans.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DeployEvent } from "@percher/client";
|
|
1
2
|
import type { Context } from "./context";
|
|
2
3
|
export interface DeploymentLike {
|
|
3
4
|
id: string;
|
|
@@ -11,10 +12,21 @@ export interface PollDeploymentOptions<D extends DeploymentLike> {
|
|
|
11
12
|
terminal?: readonly string[];
|
|
12
13
|
/** Polling interval in ms (default 2000). */
|
|
13
14
|
intervalMs?: number;
|
|
14
|
-
/** Total wall-clock budget in ms
|
|
15
|
+
/** Total wall-clock budget in ms. Defaults to the shared
|
|
16
|
+
* `clientPublishPoll` budget so every CLI poll site stays aligned
|
|
17
|
+
* with the API → worker fetch timeout (Phase 7.1). */
|
|
15
18
|
timeoutMs?: number;
|
|
16
19
|
/** Callback fired on each successful poll — for status emission. */
|
|
17
20
|
onTick?: (deployment: D) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Phase 6.1 — fires for each newly-recorded deploy event observed
|
|
23
|
+
* since the last poll. The poll loop fetches events alongside the
|
|
24
|
+
* deployment row, diffs against an internal seen-IDs set, and
|
|
25
|
+
* invokes this for each new row in chronological order. Any
|
|
26
|
+
* exception in the events-fetch path is swallowed so a failing
|
|
27
|
+
* events endpoint never crashes the deployment poll itself.
|
|
28
|
+
*/
|
|
29
|
+
onEvent?: (event: DeployEvent) => void;
|
|
18
30
|
/** Hook called when wall-clock timeout is hit. Should throw. */
|
|
19
31
|
onTimeout: (deployment: D) => never;
|
|
20
32
|
/** App display name, used in the network-error hint message. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poll-deployment.d.ts","sourceRoot":"","sources":["../src/poll-deployment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,cAAc;IAC7D,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,CAAC;IACX,uEAAuE;IACvE,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB
|
|
1
|
+
{"version":3,"file":"poll-deployment.d.ts","sourceRoot":"","sources":["../src/poll-deployment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,cAAc;IAC7D,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,CAAC;IACX,uEAAuE;IACvE,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;2DAEuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,KAAK,IAAI,CAAC;IACjC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACvC,gEAAgE;IAChE,SAAS,EAAE,CAAC,UAAU,EAAE,CAAC,KAAK,KAAK,CAAC;IACpC,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CACzC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAAC,CAAC,SAAS,cAAc,EAC3D,IAAI,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC,CA+DZ"}
|
package/dist/poll-deployment.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TIMEOUTS } from "@percher/shared/timeouts";
|
|
1
2
|
/**
|
|
2
3
|
* Poll `getDeployment` until the deployment reaches a terminal status.
|
|
3
4
|
*
|
|
@@ -16,10 +17,18 @@
|
|
|
16
17
|
export async function pollDeployment(opts) {
|
|
17
18
|
const terminal = opts.terminal ?? ["live", "failed"];
|
|
18
19
|
const intervalMs = opts.intervalMs ?? 2000;
|
|
19
|
-
const timeoutMs = opts.timeoutMs ??
|
|
20
|
+
const timeoutMs = opts.timeoutMs ?? TIMEOUTS.clientPublishPoll;
|
|
20
21
|
const maxRetries = opts.maxRetries ?? 5;
|
|
21
22
|
let deployment = opts.initial;
|
|
22
23
|
const startedAt = Date.now();
|
|
24
|
+
const seenEventIds = new Set();
|
|
25
|
+
// Drain any pre-existing events for this deploy on the first tick so
|
|
26
|
+
// a long-running poll doesn't replay rows that landed before the
|
|
27
|
+
// caller started watching. The events between initial and first poll
|
|
28
|
+
// are still surfaced — see the post-poll fetch below.
|
|
29
|
+
if (opts.onEvent) {
|
|
30
|
+
await drainNewEvents(opts, deployment.id, seenEventIds);
|
|
31
|
+
}
|
|
23
32
|
while (!terminal.includes(deployment.status)) {
|
|
24
33
|
if (Date.now() - startedAt > timeoutMs) {
|
|
25
34
|
opts.onTimeout(deployment);
|
|
@@ -51,7 +60,34 @@ export async function pollDeployment(opts) {
|
|
|
51
60
|
await new Promise((r) => setTimeout(r, backoff));
|
|
52
61
|
}
|
|
53
62
|
}
|
|
63
|
+
if (opts.onEvent) {
|
|
64
|
+
await drainNewEvents(opts, deployment.id, seenEventIds);
|
|
65
|
+
}
|
|
54
66
|
}
|
|
55
67
|
return deployment;
|
|
56
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Fetch events for the active deploy and emit any rows whose ID
|
|
71
|
+
* hasn't been seen before. Errors from the events endpoint are
|
|
72
|
+
* intentionally swallowed: the deployment-status poll is the
|
|
73
|
+
* load-bearing primitive, and a transient events-fetch failure
|
|
74
|
+
* should never propagate up to the publish caller (which would
|
|
75
|
+
* surface as "publish crashed" while the deploy is running fine).
|
|
76
|
+
*/
|
|
77
|
+
async function drainNewEvents(opts, deployId, seenEventIds) {
|
|
78
|
+
if (!opts.onEvent)
|
|
79
|
+
return;
|
|
80
|
+
try {
|
|
81
|
+
const { events } = await opts.ctx.client.apps.getDeployEvents(opts.appId, deployId);
|
|
82
|
+
for (const event of events) {
|
|
83
|
+
if (seenEventIds.has(event.id))
|
|
84
|
+
continue;
|
|
85
|
+
seenEventIds.add(event.id);
|
|
86
|
+
opts.onEvent(event);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// Events fetch is best-effort. Status poll still drives the loop.
|
|
91
|
+
}
|
|
92
|
+
}
|
|
57
93
|
//# sourceMappingURL=poll-deployment.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poll-deployment.js","sourceRoot":"","sources":["../src/poll-deployment.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"poll-deployment.js","sourceRoot":"","sources":["../src/poll-deployment.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface RetryDecision {
|
|
2
|
+
retryable: boolean;
|
|
3
|
+
delayMs: number;
|
|
4
|
+
/** Short reason for the decision — surfaces to the CLI status line. */
|
|
5
|
+
reason: string;
|
|
6
|
+
/** Canonical category used in retry telemetry / logs. */
|
|
7
|
+
category: "worker_unavailable" | "rate_limited" | "network" | "http_5xx" | "non_retryable" | "persistent";
|
|
8
|
+
}
|
|
9
|
+
export declare function classifyDeployRetry(err: unknown, attempt: number): RetryDecision;
|
|
10
|
+
export interface RetryAttemptInfo {
|
|
11
|
+
attempt: number;
|
|
12
|
+
decision: RetryDecision;
|
|
13
|
+
err: unknown;
|
|
14
|
+
}
|
|
15
|
+
export interface RunWithRetryOptions<T> {
|
|
16
|
+
call: (attempt: number) => Promise<T>;
|
|
17
|
+
/** Called before the next attempt's wait. Use to surface progress. */
|
|
18
|
+
onRetry?: (info: RetryAttemptInfo) => void;
|
|
19
|
+
/** Override the sleep impl in tests so the backoff is instant. */
|
|
20
|
+
sleep?: (ms: number) => Promise<void>;
|
|
21
|
+
/** Hard cap; defaults to 4 (1 initial + 3 retries). */
|
|
22
|
+
maxAttempts?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface RunWithRetryResult<T> {
|
|
25
|
+
result: T;
|
|
26
|
+
attempts: number;
|
|
27
|
+
}
|
|
28
|
+
export declare function runDeployWithRetry<T>(opts: RunWithRetryOptions<T>): Promise<RunWithRetryResult<T>>;
|
|
29
|
+
//# sourceMappingURL=publish-retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish-retry.d.ts","sourceRoot":"","sources":["../src/publish-retry.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,QAAQ,EACJ,oBAAoB,GACpB,cAAc,GACd,SAAS,GACT,UAAU,GACV,eAAe,GACf,YAAY,CAAC;CAClB;AA2BD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CA2JhF;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,aAAa,CAAC;IACxB,GAAG,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACtC,sEAAsE;IACtE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC3C,kEAAkE;IAClE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,MAAM,EAAE,CAAC,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,IAAI,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAqBhC"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Publish-retry classifier and runner (Phase 7.2).
|
|
3
|
+
*
|
|
4
|
+
* The 2026-05-07 incident batch surfaced a class of agent-perceived
|
|
5
|
+
* failure where the platform's `WORKER_UNAVAILABLE` (transient — the
|
|
6
|
+
* worker was restarting) bubbled through the CLI as a hard error.
|
|
7
|
+
* Humans/agents recovered by typing `percher publish` again. The CLI
|
|
8
|
+
* should do that itself.
|
|
9
|
+
*
|
|
10
|
+
* Rules table (mirrored in `docs/plans/IMPLEMENTING_publish-resilience-and-clarity-plan.md`):
|
|
11
|
+
*
|
|
12
|
+
* WORKER_UNAVAILABLE retry 3× — 5s / 15s / 45s
|
|
13
|
+
* WORKER_UNAVAILABLE_PERSISTENT no retry — surface as platform incident
|
|
14
|
+
* DEPLOY_RATE_LIMITED retry 2× — honour retryAfterSec from response
|
|
15
|
+
* network error / TCP reset retry 3× — 2s / 8s / 24s
|
|
16
|
+
* HTTP 5xx retry 2× — 5s / 20s
|
|
17
|
+
* HTTP 4xx (incl. 429 quota, 422 config) no retry
|
|
18
|
+
* BUILD_FAILED / BUILD_TIMEOUT / DEPLOY_STALLED no retry — these are
|
|
19
|
+
* observed during the *poll* phase, not the upload, but listed here
|
|
20
|
+
* defensively so any future code path that encounters them while
|
|
21
|
+
* retrying still classifies them correctly.
|
|
22
|
+
*
|
|
23
|
+
* Every retry reuses the same `Idempotency-Key` header so the API treats
|
|
24
|
+
* a re-attempt as "are you still working on this one?" rather than
|
|
25
|
+
* minting a new deploy row. The caller is responsible for generating the
|
|
26
|
+
* key (via `crypto.randomUUID()`) and threading it into the request.
|
|
27
|
+
*/
|
|
28
|
+
import { PercherApiError } from "@percher/client";
|
|
29
|
+
const NON_RETRYABLE_CODES = new Set([
|
|
30
|
+
"WORKER_UNAVAILABLE_PERSISTENT",
|
|
31
|
+
"BUILD_FAILED",
|
|
32
|
+
"BUILD_TIMEOUT",
|
|
33
|
+
"DEPLOY_STALLED",
|
|
34
|
+
"REQUIRED_ENV_MISSING",
|
|
35
|
+
"ENV_KEY_UNDECLARED",
|
|
36
|
+
"DAILY_QUOTA_EXCEEDED",
|
|
37
|
+
"RETRY_LIMIT_REACHED",
|
|
38
|
+
"ACCOUNT_SUSPENDED",
|
|
39
|
+
"APP_SUSPENDED",
|
|
40
|
+
"EMAIL_NOT_VERIFIED",
|
|
41
|
+
"PREVIEW_LIMIT_REACHED",
|
|
42
|
+
"VALIDATION_ERROR",
|
|
43
|
+
// Phase 8.1 — past hardCap the queue is so deep that retry-after
|
|
44
|
+
// would lie about wait time. Treat as a platform incident: surface
|
|
45
|
+
// immediately so the user sees the status-page link instead of
|
|
46
|
+
// a CLI that loops every minute claiming "should be back in 5s".
|
|
47
|
+
"PLATFORM_DOWN",
|
|
48
|
+
]);
|
|
49
|
+
const WORKER_UNAVAILABLE_BACKOFF_MS = [5_000, 15_000, 45_000];
|
|
50
|
+
const NETWORK_BACKOFF_MS = [2_000, 8_000, 24_000];
|
|
51
|
+
const HTTP_5XX_BACKOFF_MS = [5_000, 20_000];
|
|
52
|
+
export function classifyDeployRetry(err, attempt) {
|
|
53
|
+
// attempt is 1-indexed — `attempt = 1` means "first failure, decide
|
|
54
|
+
// delay before attempt 2"; the schedule arrays are 0-indexed.
|
|
55
|
+
const idx = attempt - 1;
|
|
56
|
+
if (err instanceof PercherApiError) {
|
|
57
|
+
if (err.code === "WORKER_UNAVAILABLE_PERSISTENT") {
|
|
58
|
+
return {
|
|
59
|
+
retryable: false,
|
|
60
|
+
delayMs: 0,
|
|
61
|
+
reason: "platform circuit breaker open — surfacing as incident",
|
|
62
|
+
category: "persistent",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (err.code === "WORKER_UNAVAILABLE") {
|
|
66
|
+
const delay = WORKER_UNAVAILABLE_BACKOFF_MS[idx];
|
|
67
|
+
if (delay === undefined) {
|
|
68
|
+
return {
|
|
69
|
+
retryable: false,
|
|
70
|
+
delayMs: 0,
|
|
71
|
+
reason: "worker unavailable after 3 attempts",
|
|
72
|
+
category: "worker_unavailable",
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
retryable: true,
|
|
77
|
+
delayMs: delay,
|
|
78
|
+
reason: "worker was restarting",
|
|
79
|
+
category: "worker_unavailable",
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (err.code === "DEPLOY_RATE_LIMITED") {
|
|
83
|
+
if (idx >= 2) {
|
|
84
|
+
return {
|
|
85
|
+
retryable: false,
|
|
86
|
+
delayMs: 0,
|
|
87
|
+
reason: "rate-limited after 2 attempts",
|
|
88
|
+
category: "rate_limited",
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const retryAfterSec = typeof err.extra?.retryAfterSec === "number" ? err.extra.retryAfterSec : 5;
|
|
92
|
+
return {
|
|
93
|
+
retryable: true,
|
|
94
|
+
delayMs: Math.min(60_000, Math.max(1_000, retryAfterSec * 1000)),
|
|
95
|
+
reason: "per-app rate limit",
|
|
96
|
+
category: "rate_limited",
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (err.code === "USER_CONCURRENT_LIMIT") {
|
|
100
|
+
// Phase 8.2 — the user has the most parallel deploys their plan
|
|
101
|
+
// allows. Retrying after the suggested window often clears one
|
|
102
|
+
// of the in-flight builds. Single retry is enough; past that the
|
|
103
|
+
// user almost certainly needs to take action (upgrade or stop
|
|
104
|
+
// looping), so surface the error.
|
|
105
|
+
if (idx >= 1) {
|
|
106
|
+
return {
|
|
107
|
+
retryable: false,
|
|
108
|
+
delayMs: 0,
|
|
109
|
+
reason: "concurrent-deploy cap still saturated after one wait",
|
|
110
|
+
category: "rate_limited",
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const retryAfterSec = typeof err.extra?.retryAfterSec === "number" ? err.extra.retryAfterSec : 60;
|
|
114
|
+
return {
|
|
115
|
+
retryable: true,
|
|
116
|
+
delayMs: Math.min(2 * 60_000, Math.max(5_000, retryAfterSec * 1000)),
|
|
117
|
+
reason: "per-user concurrent-deploy cap",
|
|
118
|
+
category: "rate_limited",
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (err.code === "PLATFORM_OVERLOADED") {
|
|
122
|
+
// Phase 8.1 — global backpressure. The API supplies a
|
|
123
|
+
// Retry-After header computed from the realistic drain estimate;
|
|
124
|
+
// honor it (capped at 5 min so a misbehaving server can't hold
|
|
125
|
+
// the CLI hostage). Up to 3 retries — past that the queue isn't
|
|
126
|
+
// draining for this caller and surfacing the incident is fairer.
|
|
127
|
+
if (idx >= 3) {
|
|
128
|
+
return {
|
|
129
|
+
retryable: false,
|
|
130
|
+
delayMs: 0,
|
|
131
|
+
reason: "platform overloaded after 3 attempts",
|
|
132
|
+
category: "rate_limited",
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const retryAfterSec = typeof err.extra?.retryAfterSec === "number" ? err.extra.retryAfterSec : 30;
|
|
136
|
+
return {
|
|
137
|
+
retryable: true,
|
|
138
|
+
delayMs: Math.min(5 * 60_000, Math.max(5_000, retryAfterSec * 1000)),
|
|
139
|
+
reason: "platform overloaded — queue-depth backpressure",
|
|
140
|
+
category: "rate_limited",
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
if (NON_RETRYABLE_CODES.has(err.code)) {
|
|
144
|
+
return {
|
|
145
|
+
retryable: false,
|
|
146
|
+
delayMs: 0,
|
|
147
|
+
reason: `non-retryable: ${err.code}`,
|
|
148
|
+
category: "non_retryable",
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
if (err.status >= 500 && err.status < 600) {
|
|
152
|
+
const delay = HTTP_5XX_BACKOFF_MS[idx];
|
|
153
|
+
if (delay === undefined) {
|
|
154
|
+
return {
|
|
155
|
+
retryable: false,
|
|
156
|
+
delayMs: 0,
|
|
157
|
+
reason: `HTTP ${err.status} after 2 attempts`,
|
|
158
|
+
category: "http_5xx",
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
retryable: true,
|
|
163
|
+
delayMs: delay,
|
|
164
|
+
reason: `HTTP ${err.status}`,
|
|
165
|
+
category: "http_5xx",
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
retryable: false,
|
|
170
|
+
delayMs: 0,
|
|
171
|
+
reason: `HTTP ${err.status} ${err.code}`,
|
|
172
|
+
category: "non_retryable",
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
if (err instanceof Error &&
|
|
176
|
+
/network error|fetch failed|ECONNRESET|ENOTFOUND|ETIMEDOUT/i.test(err.message)) {
|
|
177
|
+
const delay = NETWORK_BACKOFF_MS[idx];
|
|
178
|
+
if (delay === undefined) {
|
|
179
|
+
return {
|
|
180
|
+
retryable: false,
|
|
181
|
+
delayMs: 0,
|
|
182
|
+
reason: "network error after 3 attempts",
|
|
183
|
+
category: "network",
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
retryable: true,
|
|
188
|
+
delayMs: delay,
|
|
189
|
+
reason: "network blip",
|
|
190
|
+
category: "network",
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
retryable: false,
|
|
195
|
+
delayMs: 0,
|
|
196
|
+
reason: "unknown error",
|
|
197
|
+
category: "non_retryable",
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
const defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
201
|
+
export async function runDeployWithRetry(opts) {
|
|
202
|
+
const max = opts.maxAttempts ?? 4;
|
|
203
|
+
const sleep = opts.sleep ?? defaultSleep;
|
|
204
|
+
let attempt = 0;
|
|
205
|
+
let lastErr;
|
|
206
|
+
while (attempt < max) {
|
|
207
|
+
attempt += 1;
|
|
208
|
+
try {
|
|
209
|
+
const result = await opts.call(attempt);
|
|
210
|
+
return { result, attempts: attempt };
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
lastErr = err;
|
|
214
|
+
const decision = classifyDeployRetry(err, attempt);
|
|
215
|
+
if (!decision.retryable || attempt >= max) {
|
|
216
|
+
throw err;
|
|
217
|
+
}
|
|
218
|
+
opts.onRetry?.({ attempt, decision, err });
|
|
219
|
+
await sleep(decision.delayMs);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
throw lastErr;
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=publish-retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish-retry.js","sourceRoot":"","sources":["../src/publish-retry.ts"],"names":[],"mappings":"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"}
|