Skip to content

Keep a loaded prediction worker ready between keyboard opens - #923

Merged
enaboapps merged 4 commits into
mainfrom
922-spare-prediction-worker
Sep 27, 2026
Merged

enaboapps merged 4 commits into
mainfrom
922-spare-prediction-worker

Conversation

@enaboapps

Copy link
Copy Markdown
Contributor

Closes #922

Problem

Word prediction reloaded its model on every keyboard open, leaving suggestions blank for about a second each time. Release build measurements: 580 to 980 ms per load, of which 480 to 810 ms is building the ONNX session.

Change

  • prediction::close() runs when the keyboard closes. It kills and reaps the worker that held the typed text, then starts a fresh worker that loads the model and waits.
  • The next keyboard open adopts the spare instead of starting a new process.
  • The spare is discarded when it has waited two minutes, was started for different switch keys, or has exited.
  • prediction::stop() now also kills the spare. It still runs when scanning ends, when Word prediction is off and on Retry predictions.
  • The worker starts its activity observer on its first request, so a spare observes nothing while it waits.
  • Only a keyboard that had a working worker leaves a spare, so a failed worker is not respawned in a loop.

No protocol interface or persisted schema changes. The pipe messages are unchanged.

Trade-offs

  • The first keyboard open of a scanning session still loads the model.
  • The spare holds the loaded model, roughly 250 MB, for up to two minutes after the keyboard closes.

Validation

All run locally on Windows and passing:

  • npm run prediction-model
  • npm run lint
  • npm test
  • npm run build
  • cargo fmt --manifest-path src-tauri/Cargo.toml --check
  • cargo clippy --manifest-path src-tauri/Cargo.toml --all-targets -- -D warnings
  • cargo test --manifest-path src-tauri/Cargo.toml: 569 passed

New tests use sleeping subprocesses as fake workers and inject no input. They cover adoption, the three discard cases, expiry, no spare after a failed worker, and stop() killing the spare.

Not verified: the reopen timing in the running app. The built executable cannot be launched from an unelevated shell here, so step 6 of the native checklist in docs/word-prediction.md still needs a manual run on Windows and macOS.

🤖 Generated with Claude Code

Closing the keyboard still kills the worker that held the typed text,
then starts a fresh one that loads the model and waits. The next open
adopts it instead of reloading. The spare expires after two minutes and
starts its activity observer only on its first request.

Closes #922

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@enaboapps enaboapps added this to the v1.0.0-rc.16 milestone Sep 27, 2026
OwenMcGirr and others added 3 commits September 27, 2026 14:11
Review follow-up: prove the text-holding worker is dead before the
spare starts, prove the observer starts once on the first request,
resolve the model once, compare switch keys as a set, and correct the
docs on when a later open still loads the model.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Review follow-up: a disabled setting now kills the spare worker
directly, and the fake worker liveness check matches the image name so
a reused process id cannot fail the test.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@enaboapps
enaboapps marked this pull request as ready for review September 27, 2026 13:17
@enaboapps
enaboapps merged commit f29990d into main Sep 27, 2026
6 checks passed
@enaboapps
enaboapps deleted the 922-spare-prediction-worker branch September 27, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Keep a loaded prediction worker ready so reopening the keyboard does not reload the model

2 participants