// apply-plan.js — what "apply the update" means, separated from the RN glue that performs it.
//
// ⛔ THE DEFECT THIS FIXES. "restart" was `stopNode(); startNode()`: terminate the worklet, start a
// new one, inside the SAME process. Measured on a handset — a staged bundle pressed through that
// path never became the running one, while `adb shell am force-stop` followed by a relaunch applied
// it every time. The only difference between those two is the process, so the process is what has
// to go: dlopen'd addons, a half-torn-down corestore and lingering swarm sockets all outlive a
// thread and none of them outlive a process.
//
// ⛔ AND IT IS THE WHOLE UPDATE MECHANISM. `chooseBundle` runs at worklet start and nowhere else. A
// restart that does not really restart means no update can be applied from the device at all —
// every one needs a cable and somebody at a desk, which is not an update mechanism.
//
// ⚠ HERE RATHER THAN IN worklet.js, because that file imports react-native at module scope and can
// only run on a handset — #70 already names it as the one file exercised solely on a device. This is
// the same split `boot-plan.js` makes: the decision is testable, the glue is thin.
export const RESTART_DELAY_MS = 250
/**
* Ask for a real restart, and be honest about what was actually obtained.
*
* ⚠ FALLS BACK, LOUDLY. On a device that refuses the alarm, the thread restart is still better than
* nothing. What must not happen is quietly doing the weaker one and reporting success — that is
* exactly how a restart button that did nothing survived this long.
*/
export async function planApply ({ native, restartNode, log = () => {} } = {}) {
if (native && typeof native.restartProcess === 'function') {
try {
await native.restartProcess(RESTART_DELAY_MS)
return { restarted: 'process', degraded: false }
} catch (err) {
// Reported rather than swallowed: if this is failing, every future update fails with it.
log({ msg: 'process restart refused — falling back to the worklet', error: String((err && err.message) || err) })
}
} else {
log({ msg: 'this shell cannot restart its own process — updates will not apply until it can' })
}
if (typeof restartNode === 'function') await restartNode()
return { restarted: 'worklet', degraded: true }
}
export default { planApply, RESTART_DELAY_MS }