fix: single relay host per machine via cooperative claim lock
All local instances share the data dir and therefore the relay identity
(serverId), so concurrent relay hosts evicted each other at the relay worker
(4001: Control replaced) and paired devices landed on whichever local process
won last — often a stale dev server, surfacing as 'Unable to reach server'
and devices stuck on relay with 503s on newer endpoints.
- relay/host-lock.js: per-machine claim file (relay-host.lock, {pid}); stale
claims from dead pids are ignored; unwritable data dir falls back to
pre-lock behavior
- relay/service.js: start only when the claim is free or ours, otherwise
'standby' with the holder pid in lastError; 30s watcher takes over when the
claimant dies and stands down when another process claims; pairing-link
creation and explicit /relay/enable force-claim (user intent wins)
- mobileConnections.ts: log candidate-refresh skip reasons and the refresh
result instead of failing silently
This commit is contained in:
@@ -93,6 +93,7 @@ import { createClientPairingRuntime } from './lib/client-auth/pairing.js';
|
||||
import { createPreviewProxyRuntime } from './lib/preview/proxy-runtime.js';
|
||||
import { attachRealtimeProxy } from './lib/realtime-proxy.js';
|
||||
import { createRelayService } from './lib/relay/service.js';
|
||||
import { createRelayHostLock } from './lib/relay/host-lock.js';
|
||||
import { createProxyMiddleware, responseInterceptor } from 'http-proxy-middleware';
|
||||
import webPush from 'web-push';
|
||||
|
||||
@@ -1476,6 +1477,14 @@ async function main(options = {}) {
|
||||
readSettingsStrict: readSettingsFromDiskStrict,
|
||||
remoteClientAuthRuntime,
|
||||
getLocalPort: () => tunnelRuntimeContext.getActivePort(),
|
||||
// One relay host per machine: every instance sharing this data dir shares
|
||||
// the relay identity (serverId), so concurrent hosts evict each other at
|
||||
// the relay worker and devices land on a random local instance.
|
||||
hostLock: createRelayHostLock({
|
||||
lockFilePath: path.join(OPENCHAMBER_DATA_DIR, 'relay-host.lock'),
|
||||
fs,
|
||||
process,
|
||||
}),
|
||||
// Relay demand = any paired device or pending pairing session that uses the
|
||||
// relay transport. Drives the auto on/off lifecycle.
|
||||
hasRelayDemand: async () => {
|
||||
|
||||
Reference in New Issue
Block a user