| … | … | @@ -96,6 +96,27 @@ await new Promise((r) => server.listen(cfg.port, cfg.bind, r)) |
| 96 | 96 | // 2. UDS control plane + pgh-sidecar registration. |
| 97 | 97 | const control = await startControl({ uds: cfg.uds, name: process.env.PGH_APP_NAME || 'atproto-bridge', version, peers }) |
| 98 | 98 | |
| 99 | // OTA — the app half of the push contract. The sidecar does the FULL install (tree fetch + dep closure + |
| 100 | // materialize + symlink swap) and THEN calls this; our only job is to exit cleanly so the supervisor |
| 101 | // respawns against the new tree. Same shape as pear-git-v3/server.js. |
| 102 | // |
| 103 | // ⚠ DELIBERATELY NOT pgh-runtime's fetch path. pgh-runtime only fetches ROOT trees, not dep closures, so |
| 104 | // having the app pull its own update produces a BROKEN install — the exact failure that took the |
| 105 | // membrane down on 2026-07-31 (a missing dep, MODULE_NOT_FOUND, respawn loop). The sidecar already did |
| 106 | // the work correctly; duplicating it is how you get half of it. |
| 107 | // |
| 108 | // Exit 75 AFTER responding, so the caller sees ok rather than a dropped connection, and after a clean |
| 109 | // shutdown so no store is left locked for the process that replaces us. |
| 110 | if (control && control.svc && !control.svc.hasHandler('release-ready')) { |
| 111 | control.svc.handle('release-ready', async (ctx, params = {}) => { |
| 112 | const ver = (params && params.version) || '?' |
| 113 | console.log(JSON.stringify({ msg: 'ota: release-ready — sidecar installed; exiting 75 for supervisor respawn', version: ver })) |
| 114 | setImmediate(() => { shutdown().catch(() => {}).then(() => process.exit(75)).catch(() => process.exit(75)) }) |
| 115 | return { ok: true, willRespawn: true } |
| 116 | }) |
| 117 | console.log(JSON.stringify({ msg: 'ota: release-ready handler armed (push-based; sidecar installs, we respawn)' })) |
| 118 | } |
| 119 | |
| 99 | 120 | // 3. Warm the fronts in the BACKGROUND — never block the HTTP/UDS listen or the readiness probe. |
| 100 | 121 | // A peer offline at boot (or one that hasn't signed its first commit yet) must not delay the bridge |
| 101 | 122 | // coming up: awaiting fronts here blew past the 30s UDS readiness window → supervisor restart loop. |