(args)
| 67 | } |
| 68 | |
| 69 | async function run(args) { |
| 70 | const config = await loadConfig(args); |
| 71 | config.localUrl = ( |
| 72 | args["local-url"] || |
| 73 | config.localUrl || |
| 74 | defaultLocalUrl |
| 75 | ).replace(/\/$/, ""); |
| 76 | config.localToken = args["local-token"] || config.localToken || ""; |
| 77 | config.maxCapacity = clampCapacity( |
| 78 | Number(args["max-capacity"] || config.maxCapacity || 1), |
| 79 | ); |
| 80 | config.workRoot = args["work-root"] || config.workRoot || defaultWorkRoot; |
| 81 | config.simulatorTemplateName = |
| 82 | args["simulator-template"] || |
| 83 | config.simulatorTemplateName || |
| 84 | "iPhone 17 Pro"; |
| 85 | config.pollIntervalMs = Number(args["poll-interval-ms"] || 750); |
| 86 | config.heartbeatIntervalMs = Number(args["heartbeat-interval-ms"] || 15000); |
| 87 | config.proxyTimeoutMs = Number(args["proxy-timeout-ms"] || 25000); |
| 88 | config.videoCodec = args["video-codec"] || config.videoCodec || "software"; |
| 89 | config.streamQuality = |
| 90 | args["stream-quality"] || config.streamQuality || "smooth"; |
| 91 | |
| 92 | await fs.promises.mkdir(config.workRoot, { recursive: true }); |
| 93 | const state = { |
| 94 | activeRequests: new Set(), |
| 95 | activeSessions: new Map(), |
| 96 | inFlightAllocations: 0, |
| 97 | lastHeartbeatAt: 0, |
| 98 | stopped: false, |
| 99 | }; |
| 100 | for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) { |
| 101 | process.once(signal, () => { |
| 102 | state.stopped = true; |
| 103 | }); |
| 104 | } |
| 105 | |
| 106 | await ensureService(config); |
| 107 | await heartbeat(config, state, true); |
| 108 | console.log( |
| 109 | `[simdeck-provider] online as ${config.hostId} for ${config.studioUrl}`, |
| 110 | ); |
| 111 | |
| 112 | while (!state.stopped) { |
| 113 | try { |
| 114 | if (Date.now() - state.lastHeartbeatAt >= config.heartbeatIntervalMs) { |
| 115 | await heartbeat(config, state, false); |
| 116 | } |
| 117 | await Promise.all([pollJob(config, state), pollRpc(config, state)]); |
| 118 | } catch (error) { |
| 119 | console.error(`[simdeck-provider] ${describeError(error)}`); |
| 120 | await sleep(1000); |
| 121 | } |
| 122 | await sleep(config.pollIntervalMs); |
| 123 | } |
| 124 | |
| 125 | await Promise.allSettled(state.activeRequests); |
| 126 | await heartbeat(config, state, false, "draining"); |
no test coverage detected