Wann du es brauchst
Das Produkt erledigt Arbeit, die Sekunden oder Stunden dauern kann: einen
Ordnerbaum lesen, Dateien importieren, mit einem Gerät sprechen. Die Schritte
verwenden einen Job acme.import in einer Crate crates/acme-import als
Beispiel; examples/rescuewerk zeigt dasselbe Muster mit einem Ordner-Scan.
Regeln
- Produktcode lebt in Produkt-Crates, die von
app-apiabhängen; die Template-Crates (crates/app-*) hängen nie von einem Produkt ab. - Ein Befehl wartet nie auf einen Job.
start_jobgibt sofort die ID zurück und die UI folgt den Ereignissen;wait_for_jobist nur für CLI und Tests. - Der Handler ruft
ctx.checkpoint()?mindestens einmal pro Arbeitseinheit auf: Pause und Abbruch greifen nur dort. - Fehler und Warnungen sind stabile
RW_*-Codes, übersetzt in den drei Sprachen. Schreibe nie Sätze oder Nutzerpfade in einen Code. - Ein in der UI gewählter Pfad läuft durch
validatePath, bevor er zum Job-Parameter wird.
Schritte
- Lege
crates/acme-import/mit einerCargo.tomlwieexamples/rescuewerk/crates/rescuewerk-scan/Cargo.tomlan (Workspace-Felder,app-apiundserde_json,app-configfür Tests). Der Workspace enthältcrates/*bereits. Lege Produkt-Crates untercrates/ab: Der Katalogtest inpackages/i18n/src/catalog.test.tsprüft dieRW_*-Codes incrates/undapps/, nicht inexamples/. - Implementiere
JobHandlerwie inrescuewerk-scan/src/lib.rsunddocs/job-engine.md: Lies und prüfectx.params()und scheitere bei ungültiger Eingabe mitJobError::failed("RW_IMPORT_..."); rufectx.checkpoint()?in der Schleife auf; meldectx.progress(done, total)(None, solange die Gesamtzahl unbekannt ist, am Ende den Endwert); nutzectx.warnfür überspringbare Elemente. Exportiere die Art als Konstante, zum Beispielpub const IMPORT_JOB_KIND: &str = "acme.import";. - Teste den Job in
crates/acme-import/tests/überAppApi, wierescuewerk-scan/tests/scan.rs: Baue die API mitin_memory()und.job_handler(IMPORT_JOB_KIND, Arc::new(ImportJob)), starte den Job, warte mitwait_for_jobund prüfe Endzustand,done/totalund denerror_codebei ungültiger Eingabe. Verwende Dateien unterfixtures/, nie Pfade des Entwicklerrechners. - Registriere den Handler in der Shell: Ergänze
acme-import = { path = "crates/acme-import" }in[workspace.dependencies]derCargo.tomlundacme-import.workspace = trueinapps/desktop/src-tauri/Cargo.toml, dann rufe.job_handler(...)am Builder inapps/desktop/src-tauri/src/main.rsauf. Mach dasselbe inapps/cli, wenn die CLI den Job ausführen soll, und committe die aktualisierteCargo.lock(die CI führtcargo fetch --lockedaus). Ein neuer Tauri-Befehl ist nicht nötig:start_job,pause_job,resume_jobundcancel_jobgibt es schon. - Baue in der UI die Anfrage in einem Service der Feature, wie
sampleJobRequestinapps/desktop/src/features/jobs/services/job-requests.ts: Prüfe und begrenze die Parameter und löse Pfade vorher mitvalidatePathauf. Starte den Job mitstartJobund folge ihm über die Job-Queries, die die Ereignisse bereits aktualisieren. - Bring
MockNativeClientinpackages/native-client/src/mock.tsdie neue Art bei (unbekannte Arten lehnt er mitRW_JOB_KIND_UNKNOWNab), damitpnpm devund die Komponententests ohne Rust funktionieren. - Ergänze jeden neuen
RW_*-Code inpackages/i18n/locales/*/errors.jsonin de-DE, en und it-IT und die UI-Texte incommon.json.
Fertig, wenn
- die Prüfbefehle durchlaufen;
- der Job während der Ausführung pausiert, fortgesetzt und abgebrochen werden
kann und
COMPLETEDoderFAILEDmit einem übersetzten Code erreicht; - der Integrationstest über
AppApiohne Netzwerk und ohne Rechnerpfade läuft; - jeder neue Code in den drei Sprachen existiert.
