Alle PlaybooksNative Utility

Einen Job-Handler hinzufügen

Lange Produktarbeit als Job in einer eigenen Crate ausführen, mit Checkpoints für Pause und Abbruch, Fortschrittsereignissen, stabilen Fehlercodes und Tests über die öffentliche app-api.

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-api abhängen; die Template-Crates (crates/app-*) hängen nie von einem Produkt ab.
  • Ein Befehl wartet nie auf einen Job. start_job gibt sofort die ID zurück und die UI folgt den Ereignissen; wait_for_job ist 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

  1. Lege crates/acme-import/ mit einer Cargo.toml wie examples/rescuewerk/crates/rescuewerk-scan/Cargo.toml an (Workspace-Felder, app-api und serde_json, app-config für Tests). Der Workspace enthält crates/* bereits. Lege Produkt-Crates unter crates/ ab: Der Katalogtest in packages/i18n/src/catalog.test.ts prüft die RW_*-Codes in crates/ und apps/, nicht in examples/.
  2. Implementiere JobHandler wie in rescuewerk-scan/src/lib.rs und docs/job-engine.md: Lies und prüfe ctx.params() und scheitere bei ungültiger Eingabe mit JobError::failed("RW_IMPORT_..."); rufe ctx.checkpoint()? in der Schleife auf; melde ctx.progress(done, total) (None, solange die Gesamtzahl unbekannt ist, am Ende den Endwert); nutze ctx.warn für überspringbare Elemente. Exportiere die Art als Konstante, zum Beispiel pub const IMPORT_JOB_KIND: &str = "acme.import";.
  3. Teste den Job in crates/acme-import/tests/ über AppApi, wie rescuewerk-scan/tests/scan.rs: Baue die API mit in_memory() und .job_handler(IMPORT_JOB_KIND, Arc::new(ImportJob)), starte den Job, warte mit wait_for_job und prüfe Endzustand, done/total und den error_code bei ungültiger Eingabe. Verwende Dateien unter fixtures/, nie Pfade des Entwicklerrechners.
  4. Registriere den Handler in der Shell: Ergänze acme-import = { path = "crates/acme-import" } in [workspace.dependencies] der Cargo.toml und acme-import.workspace = true in apps/desktop/src-tauri/Cargo.toml, dann rufe .job_handler(...) am Builder in apps/desktop/src-tauri/src/main.rs auf. Mach dasselbe in apps/cli, wenn die CLI den Job ausführen soll, und committe die aktualisierte Cargo.lock (die CI führt cargo fetch --locked aus). Ein neuer Tauri-Befehl ist nicht nötig: start_job, pause_job, resume_job und cancel_job gibt es schon.
  5. Baue in der UI die Anfrage in einem Service der Feature, wie sampleJobRequest in apps/desktop/src/features/jobs/services/job-requests.ts: Prüfe und begrenze die Parameter und löse Pfade vorher mit validatePath auf. Starte den Job mit startJob und folge ihm über die Job-Queries, die die Ereignisse bereits aktualisieren.
  6. Bring MockNativeClient in packages/native-client/src/mock.ts die neue Art bei (unbekannte Arten lehnt er mit RW_JOB_KIND_UNKNOWN ab), damit pnpm dev und die Komponententests ohne Rust funktionieren.
  7. Ergänze jeden neuen RW_*-Code in packages/i18n/locales/*/errors.json in de-DE, en und it-IT und die UI-Texte in common.json.

Fertig, wenn

  • die Prüfbefehle durchlaufen;
  • der Job während der Ausführung pausiert, fortgesetzt und abgebrochen werden kann und COMPLETED oder FAILED mit einem übersetzten Code erreicht;
  • der Integrationstest über AppApi ohne Netzwerk und ohne Rechnerpfade läuft;
  • jeder neue Code in den drei Sprachen existiert.