Off charge, the runner leaves with a minute's notice ed6c64d23fca
Taken off charge, the phone finishes a job the hub expects to end within a minute and hands back any other, its checkpoint saved; off Wi-Fi it still hands back at once. Pins OxygenFlow's main (checkpoints, leave_within). refs #8
- Author
- Andy McCall @andymccall <[email protected]>
- When
- · 2026-10-26 00:37 UTC
- Signature
- ✔ signed by Andy McCall
- Hash
ed6c64d23fca272d2ab54c611bc5995fa64d865d2e481ab1233028f631481d43- Depends on
- 0414607973cb 41e2e862abce 4aee5293461d 57c0824300db
- Depended on by
- 8440d51a2275 26530d9758ee 62429abe5869 a49fd826e10b
- In bookmarks
- main
- In tags
- v0.1.0 v0.1.1 v0.1.2 v0.1.3 v0.1.4 v0.1.5 v0.1.6 v0.1.7 v0.1.8 v0.1.9
- Edits
- 15 atoms, 0 tree operations, 6 files
Browse the tree at this change
modified CHANGELOG.md +1 −0
| … | 1 unchanged lines |
||
| 2 | 2 | ||
| 3 | 3 | ## Unreleased |
|
| 4 | 4 | ||
| 5 | + | - **Off charge, the runner gives a minute's notice (#8, oxygenflow#76/#77):** taken off charge, the phone claims nothing more, finishes a job the hub expects to end within a minute and hands back any other to another runner, its checkpoint saved so the next attempt resumes where it stopped. Leaving Wi-Fi still hands back at once. Pins OxygenFlow's main (checkpoints, `leave_within`). |
|
| 5 | 6 | - **Diffs on a change (#21):** each file a change touched shows its diff in the app: context, removed and added lines with their old and new numbers, tinted, long lines wrapped, gaps between hunks marked. A small change (up to five files, 400 lines) opens every diff; a larger one starts folded and a file's row opens it. The icon on the row still opens the file at the change. From the hub's change API (hub #320); an older hub sends no lines, and the row says so. |
|
| 6 | 7 | - **The phone as an OxygenFlow runner (#8, first part):** Account → OxygenFlow runner → *Offer this phone as a runner* asks the hub for a one-time token (`POST /api/v1/user/runner-token`) and registers the phone as a runner for your own repositories, labelled `android`, offering the WASM tier. The runner is OxygenFlow's own, built into the app through rust-core (OxygenFlow is a subrepo, `oxygenflow/`, and rust-core's oxy-core is the one it pins), running WASM modules in a thread with wasmtime. It runs in a foreground service with a notification, only while the phone is charging on Wi-Fi (an unmetered network); coming off charge or off Wi-Fi drains it (it takes nothing more and finishes its job). Start and Stop on the card. The app is larger: the runner and wasmtime are about 29 MB per architecture. |
|
| 7 | 8 | - **Proposals on the dashboard (#18):** Waiting for your review (open proposals by others in your repositories you have not reviewed) and Your proposals (your open ones and drafts), as the hub's dashboard lists them, each opening the proposal screen where it can be landed. From the hub's `GET /api/v1/user/proposals`; a hub without it shows neither. |
|
| … | 6 unchanged lines |
modified app/src/main/java/io/oxygenhub/android/runner/PhoneRunner.kt +10 −8
| … | 41 unchanged lines |
||
| 42 | 42 | /** Told to stop: finishing what it holds. */ |
|
| 43 | 43 | data class Draining(val why: String) : State |
|
| 44 | 44 | ||
| 45 | - | /** Told to leave: handing its job back to the hub for another runner. */ |
|
| 46 | - | data class Leaving(val why: String) : State |
|
| 45 | + | /** Told to leave: handing its job back to the hub for another runner, unless due within [noticeSecs]. */ |
|
| 46 | + | data class Leaving(val why: String, val noticeSecs: Long = 0) : State |
|
| 47 | 47 | ||
| 48 | 48 | data class Failed(val message: String) : State |
|
| 49 | 49 | } |
|
| … | 82 unchanged lines |
||
| 132 | 132 | } |
|
| 133 | 133 | ||
| 134 | 134 | /** |
|
| 135 | - | * Leave now (oxygenflow#76): stop what it holds and hand it back to the |
|
| 136 | - | * hub, which gives it to another runner ahead of new work. For leaving |
|
| 137 | - | * the allowed network: finishing would use the network the owner ruled out. |
|
| 135 | + | * Leave (oxygenflow#76): claim nothing more and hand what it holds back |
|
| 136 | + | * to the hub, which gives it to another runner ahead of new work. With |
|
| 137 | + | * [noticeSecs], a job the hub expects to finish within it finishes |
|
| 138 | + | * first: a minute off charge. None off the allowed network, where |
|
| 139 | + | * finishing would use the network the owner ruled out. |
|
| 138 | 140 | */ |
|
| 139 | - | fun leave(why: String) { |
|
| 141 | + | fun leave(why: String, noticeSecs: Long = 0) { |
|
| 140 | 142 | val now = _state.value |
|
| 141 | 143 | if (now == State.Running || now is State.Draining) { |
|
| 142 | - | _state.value = State.Leaving(why) |
|
| 143 | - | runnerLeave(why) |
|
| 144 | + | _state.value = State.Leaving(why, noticeSecs) |
|
| 145 | + | runnerLeave(why, noticeSecs.toULong()) |
|
| 144 | 146 | } |
|
| 145 | 147 | } |
|
| 146 | 148 | } |
modified app/src/main/java/io/oxygenhub/android/runner/RunnerCard.kt +5 −1
| … | 62 unchanged lines |
||
| 63 | 63 | is PhoneRunner.State.Waiting -> "Not running: ${s.why}." to MaterialTheme.colorScheme.onSurfaceVariant |
|
| 64 | 64 | PhoneRunner.State.Running -> "Running as ${PhoneRunner.name()}: taking WASM jobs." to status.ok |
|
| 65 | 65 | is PhoneRunner.State.Draining -> "Draining (${s.why}): finishing its job, then stopping." to status.warn |
|
| 66 | - | is PhoneRunner.State.Leaving -> "Leaving (${s.why}): handing its job back for another runner, then stopping." to status.warn |
|
| 66 | + | is PhoneRunner.State.Leaving -> if (s.noticeSecs > 0) { |
|
| 67 | + | "Leaving (${s.why}): finishing a job due within ${s.noticeSecs} s, handing back any other, then stopping." to status.warn |
|
| 68 | + | } else { |
|
| 69 | + | "Leaving (${s.why}): handing its job back for another runner, then stopping." to status.warn |
|
| 70 | + | } |
|
| 67 | 71 | is PhoneRunner.State.Failed -> "Stopped: ${s.message}" to status.bad |
|
| 68 | 72 | } |
|
| 69 | 73 | Text(line, style = MaterialTheme.typography.bodyMedium, color = colour) |
|
| … | 33 unchanged lines |
modified app/src/main/java/io/oxygenhub/android/runner/RunnerService.kt +6 −5
| … | 22 unchanged lines |
||
| 23 | 23 | /** |
|
| 24 | 24 | * Runs the phone's OxygenFlow runner (#8) in the foreground, with a |
|
| 25 | 25 | * notification saying so, while the phone is on charge and on Wi-Fi. |
|
| 26 | - | * Leaving the charger drains it (it claims nothing more, finishes and |
|
| 27 | - | * reports the job it holds); leaving Wi-Fi hands the job back to the hub |
|
| 28 | - | * for another runner (oxygenflow#76). While its owner wants it, the service |
|
| 26 | + | * Leaving the charger gives it a minute: it claims nothing more, finishes |
|
| 27 | + | * a job the hub expects to end within it and hands back any other, its |
|
| 28 | + | * checkpoint saved; leaving Wi-Fi hands the job back at once |
|
| 29 | + | * (oxygenflow#76). While its owner wants it, the service |
|
| 29 | 30 | * then waits, and serves again once the phone is back on charge and Wi-Fi. |
|
| 30 | 31 | */ |
|
| 31 | 32 | class RunnerService : Service() { |
|
| … | 6 unchanged lines |
||
| 38 | 39 | override fun onReceive(context: Context, intent: Intent) { |
|
| 39 | 40 | when (intent.action) { |
|
| 40 | 41 | Intent.ACTION_POWER_DISCONNECTED -> { |
|
| 41 | - | PhoneRunner.drain("taken off charge") |
|
| 42 | - | notify("Draining: taken off charge") |
|
| 42 | + | PhoneRunner.leave("taken off charge", noticeSecs = 60) |
|
| 43 | + | notify("Leaving: taken off charge") |
|
| 43 | 44 | } |
|
| 44 | 45 | Intent.ACTION_POWER_CONNECTED -> serveIfAllowed() |
|
| 45 | 46 | } |
|
| … | 133 unchanged lines |
replaced oxygenflow +0 −0
No line changes.
modified rust-core/src/lib.rs +8 −6
| … | 61 unchanged lines |
||
| 62 | 62 | flow::runner::stop(); |
|
| 63 | 63 | } |
|
| 64 | 64 | ||
| 65 | - | /// Leave now (oxygenflow#76): claim nothing more, stop the jobs it holds |
|
| 66 | - | /// and hand them back to the hub, which gives them to another runner ahead |
|
| 67 | - | /// of new work; [`runner_serve`] then returns. For leaving the allowed |
|
| 68 | - | /// network, where finishing would use the network the owner ruled out. |
|
| 65 | + | /// Leave (oxygenflow#76): claim nothing more, and hand the jobs it holds |
|
| 66 | + | /// back to the hub, which gives them to another runner ahead of new work; |
|
| 67 | + | /// [`runner_serve`] then returns. With `notice_secs`, a job the hub expects |
|
| 68 | + | /// to finish within the notice finishes first (its checkpoint saved if |
|
| 69 | + | /// not). 0 for leaving the allowed network, where finishing would use the |
|
| 70 | + | /// network the owner ruled out; a minute for leaving the charger. |
|
| 69 | 71 | #[uniffi::export] |
|
| 70 | - | pub fn runner_leave(reason: String) { |
|
| 71 | - | flow::runner::leave(&reason); |
|
| 72 | + | pub fn runner_leave(reason: String, notice_secs: u64) { |
|
| 73 | + | flow::runner::leave_within(&reason, std::time::Duration::from_secs(notice_secs)); |
|
| 72 | 74 | } |
|
| 73 | 75 | ||
| 74 | 76 | /// The tiers this phone offers (the WASM tier), and why not the others. |
|
| … | 8 unchanged lines |