Add server hibernation#51
Conversation
|
@jmunckhof is attempting to deploy a commit to the Hayden Bleasel Team on Vercel. A member of the Team first needs to authorize it. |
|
Nice work on this — the overall shape (atomic state claims, FatalError ordering so a stuck snapshot can't nuke the VM, idempotent step keys) is solid. A few things worth tackling before this comes out of draft: Correctness
Smaller stuff
Things that read well
Test plan looks comprehensive; only thing I'd add is a cheap unit test on the action-level guards (e.g. "rejects when observedState=hibernating") since those are easy to regress. |
|
Updated this on top of the provider refactor that landed in main. Pulled out the IP-reservation toggle for now Rest of the flow is the same: STOP → shutdown → snapshot → delete VM on hibernate, then create from snapshot → |
- Never tear down the VM (or snapshot) when the snapshot polls time out;
the VM holds the only copy of the data, so timeouts now just mark the
server failed and leave everything for a retry to reuse
- Wait for the VM to actually power off (ACPI, then hard poweroff) before
snapshotting, instead of imaging a running disk
- Atomically claim hibernate/wake state transitions with a guarded
updateMany so double-clicks can't fan out duplicate workflows, and roll
the row back if the workflow fails to start
- Allow retrying from "failed": a failed hibernation can be re-hibernated
and a failed wake re-woken (the workflow reuses a surviving VM), so
timeouts are no longer dead-end states
- Distinguish a snapshot that vanished ("missing") from a bad status, and
clear the dangling image id so retries start fresh
- Clear providerServerId when the provider VM 404s during wake so a retry
recreates it from the snapshot
- Reset the pending UI state in a finally block so a thrown action can't
permanently disable the actions menu
- Drop hibernating/waking from PROVISIONING_PHASES: the provisioning
checklist can't represent them and would pin to "Create server"
- Add the Prisma migration for the new enum values and columns
c3f8baa to
07b5521
Compare
|
Heads up @jmunckhof — all merged now but had to make some small changes! What changed: Rebased onto current main. The branch predated the Ghost 2.0 single-tenant rework (#76), so your four commits were squashed into one (authorship preserved) and ported: actions moved to Added a hardening commit on top, addressing review findings:
The reserve-IP setting mentioned in the PR description was never part of the diff and remains unimplemented — the dialog copy correctly says the IP changes on wake. Thanks for the feature! |
Closes #50.
Adds a hibernate / wake lifecycle so an idle game server can stop paying compute. Snapshots the disk to Hetzner image storage, deletes the VM, and restores it on demand.
Summary
desiredState:hibernated, observed stateshibernating/hibernated/wakinghibernateServer(drain agent → optional IP reserve → shutdown → snapshot → delete VM) andwakeServer(create VM from snapshot → wait for agent → drop snapshot)hibernate,wake, plus ahibernate-settingsaction to toggle "reserve IP across hibernate"emitActivityCost shape (rough)
Notes for reviewer
prisma/schema.prismachanged but I haven't generated the migration yet — happy to add one before this comes out of draftupdateManyso a double-click can't fan out two workflows; both roll back the DB if the workflowstartitself throwsFatalErrorinstead of falling through to VM deletion (so a stuck snapshot can never silently nuke the world)Out of scope
Test plan
hibernatingstate, confirm the action rejects cleanly