Skip to content

[P1/P2] Recover interrupted install/update/uninstall transactions after hard process termination #32

Description

@gitcoder89431

Problem

Current rollback handles ordinary command/script failures well, but an ERR/EXIT trap cannot run after events such as kill -9, power loss, kernel/system crash, or abrupt machine reset.

A lifecycle operation interrupted between plugin/config mutations can therefore leave a partially applied state even though normal failures roll back correctly.

Goal

Add durable transaction metadata so the next mutating Ruixen lifecycle command can detect and safely recover an unfinished operation before doing new work.

Suggested design

Before exposing live mutations, create a transaction directory such as:

~/.local/state/ruixen/transactions/<token>/
  journal.json
  shell.json.before
  ...

The journal should record schema version, operation type, transaction token, phase, exact managed targets, whether each target existed before, backup/snapshot locations, config snapshot metadata, and whether live mutation/restart began.

On startup of any mutating lifecycle command:

  1. acquire the lifecycle lock
  2. detect unfinished transactions
  3. validate journal/snapshot paths and schema
  4. recover or finish the prior transaction safely
  5. only then begin the new command

Critical safety requirements

  • Never trust arbitrary paths from a journal without validating they are under expected Ruixen/Omarchy roots.
  • Refuse symlinked/malformed transaction roots.
  • Do not delete the journal if recovery itself fails.
  • Recovery should be idempotent.
  • Existing normal rollback remains useful; the journal covers crash/interruption durability.
  • Do not stop or mutate the shell until all required recovery data has been validated.

Acceptance tests

Simulate termination after first plugin replacement, after all plugins before shell.json, after shell.json before looknfeel, after looknfeel before restart, after restart begins before success commit, and during uninstall.

For each case, terminate without executing shell traps, run a new lifecycle command, verify the previous working installation/config is recovered, verify no mixed old/new plugin set remains, and remove the transaction directory only after successful recovery.

Also corrupt a journal/snapshot and confirm Ruixen refuses unsafe recovery instead of guessing.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions