diff --git a/docs/constraints/workflow-constraints.md b/docs/constraints/workflow-constraints.md index da49a632def..bb4713990e6 100644 --- a/docs/constraints/workflow-constraints.md +++ b/docs/constraints/workflow-constraints.md @@ -13,6 +13,12 @@ Here are some examples of things you shouldn't do inside of a workflow class: - Don't make network requests to external resources, as these may be slow or unavailable at different times. Instead, pass the necessary data as inputs to the workflow when it is started or use an activity to retrieve the data. - Don't use random number generators (unless using a side effect) or other sources of randomness, as these will produce different results each time they are called. Instead, pass any necessary randomness as an input to the workflow when it is started. +## Logging from workflow code {#workflow-logging} + +A worker reconstructs committed workflow history after activations and cold replacement, so ordinary application logging can repeat earlier messages. Use the replay-aware logger documented for your binding when available. Rust service mode provides the [Rust SDK 4.17 workflow logger](../polyglot/rust.md#workflow-logging); other bindings retain their separately documented contracts. + +Logging is a process observation. Keep durable workflow commands independent of replay-state observations and log delivery. Even a replay-aware logger can repeat a message from an uncommitted attempt after a crash or retry; it is not an exactly-once outbox. Keep host handlers bounded and nonblocking so logging does not stall the worker. Put durable business effects behind the appropriate activity or recorded workflow operation instead. + ## Boot-Time Guardrails When workflow classes are registered under `workflows.v2.types.workflows`, the package scans them at boot time for obvious replay-unsafe calls (`Carbon::now()`, `Auth::user()`, `DB::`, `Http::`, `random_int()`, and similar) and surfaces findings according to `workflows.v2.guardrails.boot`: diff --git a/docs/polyglot/rust.md b/docs/polyglot/rust.md index a546ce8287d..1a45e026f1b 100644 --- a/docs/polyglot/rust.md +++ b/docs/polyglot/rust.md @@ -719,6 +719,22 @@ runs record `max_supported`; existing runs reuse the durable marker. drained. See [Side Effects](/docs/features/side-effects/) and [Versioning](/docs/features/versioning/) for the shared durable semantics. +## Replay-aware workflow logging {#workflow-logging} + +Rust SDK 4.17.0 adds `ctx.logger().info("message")` for observations from workflow code. It routes to the application's existing `tracing` subscriber using target `durable_workflow::workflow`, with SDK-bound immutable `namespace`, `workflow_instance_id` and `workflow_run_id` fields. Configure the host subscriber; the SDK installs no global subscriber. + +Ordinary log calls execute again as a worker reconstructs workflow history. The workflow logger stays quiet for committed-prefix, query/offline and completed-history replay, including cold worker replacement, and outside an active invocation. It can emit only in new execution beyond that prefix with a complete bound run identity. `ctx.replay_state()` observes that live consumed-history boundary rather than a Boolean fixed when the task starts: + +| `WorkflowReplayState` | Observation | +| --- | --- | +| `Replaying` | Reconstructing committed history or a query; workflow logs are suppressed. | +| `Executing` | New execution beyond the committed prefix; an uncommitted task retry can repeat logs. | +| `Unavailable` | Outside this workflow invocation, or the state cannot be read safely; workflow logs are suppressed. | + +Keep durable command order independent of this observation state and log delivery. A log from an uncommitted attempt can repeat after a crash or retry, so the logger is not an exactly-once outbox. Keep application handlers bounded and nonblocking, for example with an application-owned logging queue. Unwinding subscriber panics are isolated from the workflow result; process aborts and blocking handlers remain application responsibilities. + +See the [published logging guide](https://github.com/durable-workflow/sdk-rust/blob/4.17.0/README.md#workflow-logging), [WorkflowLogger API](https://rust.durable-workflow.com/durable_workflow/struct.WorkflowLogger.html) and [WorkflowReplayState API](https://rust.durable-workflow.com/durable_workflow/enum.WorkflowReplayState.html). [Registry lifecycle/deadline controls](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868388853) and [four-process logging acceptance](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868494262) were recorded on the named native Server 3.10.0 linux/amd64 tuple. Other bindings and broader replay/producer qualification retain their own scope. + ## Rust determinism rules {#rust-determinism-rules} A replay must produce the same durable commands in the same order for the recorded input and history. Rust's ordinary collections, clocks and concurrency primitives do not automatically preserve that contract: diff --git a/i18n/de/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md b/i18n/de/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md index bfc873c7b28..d7961c55780 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md @@ -13,6 +13,12 @@ Beispiele für Operationen, die nicht in den Workflow-Code gehören: - Führen Sie keine Netzwerkaufrufe zu externen Ressourcen aus. Verfügbarkeit und Laufzeit können schwanken. Übergeben Sie benötigte Daten beim Start oder lesen Sie sie in einer Aktivität. - Verwenden Sie keine Zufallszahlengeneratoren oder andere Zufallsquellen außerhalb eines Side Effects. Jeder Aufruf kann ein anderes Ergebnis liefern. Übergeben Sie benötigte Zufallswerte als Eingabe. +## Logging aus Workflow-Code {#workflow-logging} + +Ein Worker rekonstruiert nach Aktivierungen und kaltem Austausch den persistierten Workflow-Verlauf. Gewöhnliches Anwendungslogging kann deshalb frühere Meldungen wiederholen. Verwenden Sie den für Ihr Binding dokumentierten replay-bewussten Logger, sofern verfügbar. Rust Service Mode bietet den [Workflow-Logger des Rust SDK 4.17](../polyglot/rust.md#workflow-logging); andere Bindings behalten ihre gesondert dokumentierten Verträge. + +Logging ist eine Prozessbeobachtung. Halten Sie dauerhafte Workflow-Befehle unabhängig von Replay-Zustand und Log-Zustellung. Auch ein replay-bewusster Logger kann eine Meldung aus einem nicht persistierten Versuch nach Absturz oder Retry wiederholen; er ist keine Outbox mit Exactly-once-Garantie. Host-Handler müssen begrenzt und nicht blockierend bleiben, damit Logging den Worker nicht aufhält. Dauerhafte Geschäftseffekte gehören stattdessen in eine passende Activity oder aufgezeichnete Workflow-Operation. + ## Prüfungen beim Anwendungsstart {#boot-time-guardrails} Für unter `workflows.v2.types.workflows` registrierte Workflow-Klassen prüft das Paket beim Start offensichtliche Replay-unsichere Aufrufe wie `Carbon::now()`, `Auth::user()`, `DB::`, `Http::` und `random_int()`. Die Einstellung `workflows.v2.guardrails.boot` bestimmt die Behandlung: diff --git a/i18n/de/docusaurus-plugin-content-docs/current/polyglot/rust.md b/i18n/de/docusaurus-plugin-content-docs/current/polyglot/rust.md index 3d030fded6b..82c35fc97ad 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/polyglot/rust.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/polyglot/rust.md @@ -718,6 +718,22 @@ Marker erneut. `patched(change_id)` bietet die boolesche Rollout-Form. Die gemeinsame dauerhafte Semantik beschreiben [Seiteneffekte](/docs/features/side-effects/) und [Versionierung](/docs/features/versioning/). +## Replay-bewusstes Workflow-Logging {#workflow-logging} + +Rust SDK 4.17.0 ergänzt `ctx.logger().info("message")` für Beobachtungen aus Workflow-Code. Die Ereignisse gehen an den bestehenden `tracing`-Subscriber der Anwendung mit dem Target `durable_workflow::workflow` und den unveränderlichen, vom SDK gebundenen Feldern `namespace`, `workflow_instance_id` und `workflow_run_id`. Konfigurieren Sie den Host-Subscriber; das SDK installiert keinen globalen Subscriber. + +Gewöhnliche Log-Aufrufe werden erneut ausgeführt, wenn ein Worker den Workflow-Verlauf rekonstruiert. Der Workflow-Logger bleibt bei Replay des persistierten Präfixes, Query-/Offline-Replay und abgeschlossenen Verläufen still, auch nach einem kalten Worker-Wechsel und außerhalb eines aktiven Aufrufs. Er kann nur in neuer Ausführung hinter diesem Präfix und mit vollständiger gebundener Run-Identität ausgeben. `ctx.replay_state()` beobachtet diese aktuelle Grenze des konsumierten Verlaufs statt eines beim Task-Start fixierten Boolean: + +| `WorkflowReplayState` | Beobachtung | +| --- | --- | +| `Replaying` | Rekonstruktion des persistierten Verlaufs oder einer Query; Workflow-Logs werden unterdrückt. | +| `Executing` | Neue Ausführung hinter dem persistierten Präfix; ein Retry eines noch nicht persistierten Tasks kann Logs wiederholen. | +| `Unavailable` | Außerhalb dieses Workflow-Aufrufs oder Zustand nicht sicher lesbar; Workflow-Logs werden unterdrückt. | + +Halten Sie die dauerhafte Befehlsreihenfolge unabhängig von diesem Beobachtungszustand und der Log-Zustellung. Ein Log aus einem nicht persistierten Versuch kann nach Absturz oder Retry erneut erscheinen; der Logger ist keine Outbox mit Exactly-once-Garantie. Halten Sie Anwendungshandler begrenzt und nicht blockierend, etwa mit einer anwendungseigenen Logging-Queue. Subscriber-Panics mit Stack-Unwinding werden vom Workflow-Ergebnis isoliert; Prozessabbrüche und blockierende Handler bleiben Anwendungsverantwortung. + +Siehe den [veröffentlichten Logging-Guide](https://github.com/durable-workflow/sdk-rust/blob/4.17.0/README.md#workflow-logging), die [WorkflowLogger-API](https://rust.durable-workflow.com/durable_workflow/struct.WorkflowLogger.html) und die [WorkflowReplayState-API](https://rust.durable-workflow.com/durable_workflow/enum.WorkflowReplayState.html). [Registry-Lifecycle-/Deadline-Kontrollen](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868388853) und [Logging-Abnahme mit vier Prozessen](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868494262) wurden auf dem benannten Tupel mit native Server 3.10.0 unter linux/amd64 erfasst. Andere Bindings und weitergehende Replay-/Producer-Qualifikation behalten ihren eigenen Umfang. + ## Rust-Regeln für Determinismus {#rust-determinism-rules} Ein Replay muss für aufgezeichnete Eingabe und Historie dieselben dauerhaften Befehle in derselben Reihenfolge erzeugen. Gewöhnliche Rust-Sammlungen, Uhren und Nebenläufigkeitsprimitive erhalten diesen Vertrag nicht automatisch: diff --git a/i18n/de/source-hashes.json b/i18n/de/source-hashes.json index b9d558d55e1..094463e2c6f 100644 --- a/i18n/de/source-hashes.json +++ b/i18n/de/source-hashes.json @@ -18,7 +18,7 @@ "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", "constraints/structural-limits.md": "5c7b7f6c86c5ca547eb3f200400ceab3b589f32d83866914f44e3a5a7d81e964", - "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", + "constraints/workflow-constraints.md": "f80f68b13877a67469a313b9fdcdbb27c1de6fe102cdfddb15e2af95997d2517", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", "defining-workflows/activities.md": "05b46f73477a0bbd5f21d17ac37def8a8eac53f1e629155805c98cc46e75b418", @@ -87,7 +87,7 @@ "polyglot/python.md": "82da06617fe24e70c5c89197d192a81430a282b788ef93afd3b3bcb690ba2a9f", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "2cc511074e6d0ce8ababa0ccd6acbdaa7df3bf5d8c67ae5ef2fa07d75a05d2e7", + "polyglot/rust.md": "31950634b8ccdb5c288ba871cc7f816de6683c52bf738bfdc13fa7aa825c6335", "polyglot/server-api-reference.md": "ecd6d358d6e5bde442ebf0e1ec8a072779089e2a5c4427e31eef646f42c6c03c", "polyglot/server-config-reference.md": "aec241c0046f12a9d6efe2d6c1de443d7753bdf34135e06a6f83b3904ed1d429", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", diff --git a/i18n/es/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md b/i18n/es/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md index fab8bf61ffe..e4e802e6258 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md @@ -24,6 +24,12 @@ Ten en cuenta estas reglas al escribir un workflow: hacerlo durante la ejecución, usa un side effect para registrar el resultado. También puedes pasar el valor aleatorio como entrada al iniciar el workflow. +## Logging desde el código del workflow {#workflow-logging} + +Un worker reconstruye el historial confirmado del workflow tras activaciones y reemplazos en frío, por lo que el logging normal de la aplicación puede repetir mensajes anteriores. Use el logger consciente del replay documentado para su binding cuando esté disponible. El modo servicio Rust ofrece el [logger de workflow de Rust SDK 4.17](../polyglot/rust.md#workflow-logging); los demás bindings conservan sus contratos documentados por separado. + +El logging es una observación del proceso. Mantenga los comandos durables del workflow independientes de las observaciones de replay y de la entrega de logs. Incluso un logger consciente del replay puede repetir un mensaje de un intento no confirmado tras un fallo o retry; no es un outbox exactamente una vez. Los handlers del host deben estar acotados y no bloquear para no detener al worker. Sitúe los efectos de negocio durables en la actividad u operación de workflow registrada adecuada. + ## Comprobaciones al iniciar la aplicación {#boot-time-guardrails} Cuando registras clases de workflow en `workflows.v2.types.workflows`, el paquete diff --git a/i18n/es/docusaurus-plugin-content-docs/current/polyglot/rust.md b/i18n/es/docusaurus-plugin-content-docs/current/polyglot/rust.md index aaeb2a6587f..00faa8a3a4a 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/polyglot/rust.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/polyglot/rust.md @@ -547,6 +547,22 @@ El SDK de Rust registra valores no deterministas pequeños con `WorkflowContext: Utiliza `WorkflowContext::get_version(change_id, min_supported, max_supported)` para mantener compatibles con la reproducción las ramas antiguas y nuevas durante un despliegue. Las ejecuciones nuevas registran `max_supported`; las existentes reutilizan el marcador duradero. `patched(change_id)` ofrece la forma booleana del despliegue y `deprecate_patch(change_id)` conserva el marcador tras finalizar la rama heredada. Consulta [Efectos secundarios](/docs/features/side-effects/) y [Versionado](/docs/features/versioning/) para la semántica duradera compartida. +## Logging de workflows consciente del replay {#workflow-logging} + +Rust SDK 4.17.0 añade `ctx.logger().info("message")` para observaciones desde el código del workflow. Envía los eventos al subscriber `tracing` existente de la aplicación con el target `durable_workflow::workflow` y los campos inmutables vinculados por el SDK `namespace`, `workflow_instance_id` y `workflow_run_id`. Configure el subscriber del host; el SDK no instala uno global. + +Las llamadas de log normales vuelven a ejecutarse cuando un worker reconstruye el historial del workflow. El logger del workflow permanece silencioso durante el replay del prefijo confirmado, las consultas/replay offline y los historiales completados, incluso tras reemplazar el worker en frío, y fuera de una invocación activa. Solo puede emitir en ejecución nueva más allá de ese prefijo y con una identidad de run completa y vinculada. `ctx.replay_state()` observa ese límite vivo del historial consumido, en lugar de un booleano fijado al iniciar la tarea: + +| `WorkflowReplayState` | Observación | +| --- | --- | +| `Replaying` | Reconstrucción de historial confirmado o de una consulta; se suprimen los logs del workflow. | +| `Executing` | Ejecución nueva más allá del prefijo confirmado; reintentar una tarea no confirmada puede repetir logs. | +| `Unavailable` | Fuera de esta invocación del workflow o sin lectura segura del estado; se suprimen los logs del workflow. | + +Mantenga el orden de comandos durables independiente de este estado de observación y de la entrega de logs. Un log de un intento no confirmado puede repetirse tras un fallo o retry; el logger no es un outbox exactamente una vez. Mantenga los handlers de la aplicación acotados y no bloqueantes, por ejemplo con una cola de logging propia. Los panics del subscriber con desenrollado de pila se aíslan del resultado del workflow; los abortos del proceso y handlers bloqueantes siguen siendo responsabilidad de la aplicación. + +Consulte la [guía de logging publicada](https://github.com/durable-workflow/sdk-rust/blob/4.17.0/README.md#workflow-logging), la [API WorkflowLogger](https://rust.durable-workflow.com/durable_workflow/struct.WorkflowLogger.html) y la [API WorkflowReplayState](https://rust.durable-workflow.com/durable_workflow/enum.WorkflowReplayState.html). Los [controles de ciclo de vida/deadline desde el registro](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868388853) y la [aceptación de logging con cuatro procesos](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868494262) se registraron en la tupla nombrada native Server 3.10.0 linux/amd64. Los demás bindings y la cualificación más amplia de replay/productor mantienen su propio alcance. + ## Reglas de determinismo de Rust {#rust-determinism-rules} Una reproducción debe generar los mismos comandos duraderos, en el mismo orden, para la entrada y el historial registrados. Las colecciones, relojes y primitivas de concurrencia normales de Rust no mantienen automáticamente ese contrato: diff --git a/i18n/es/source-hashes.json b/i18n/es/source-hashes.json index b9d558d55e1..094463e2c6f 100644 --- a/i18n/es/source-hashes.json +++ b/i18n/es/source-hashes.json @@ -18,7 +18,7 @@ "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", "constraints/structural-limits.md": "5c7b7f6c86c5ca547eb3f200400ceab3b589f32d83866914f44e3a5a7d81e964", - "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", + "constraints/workflow-constraints.md": "f80f68b13877a67469a313b9fdcdbb27c1de6fe102cdfddb15e2af95997d2517", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", "defining-workflows/activities.md": "05b46f73477a0bbd5f21d17ac37def8a8eac53f1e629155805c98cc46e75b418", @@ -87,7 +87,7 @@ "polyglot/python.md": "82da06617fe24e70c5c89197d192a81430a282b788ef93afd3b3bcb690ba2a9f", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "2cc511074e6d0ce8ababa0ccd6acbdaa7df3bf5d8c67ae5ef2fa07d75a05d2e7", + "polyglot/rust.md": "31950634b8ccdb5c288ba871cc7f816de6683c52bf738bfdc13fa7aa825c6335", "polyglot/server-api-reference.md": "ecd6d358d6e5bde442ebf0e1ec8a072779089e2a5c4427e31eef646f42c6c03c", "polyglot/server-config-reference.md": "aec241c0046f12a9d6efe2d6c1de443d7753bdf34135e06a6f83b3904ed1d429", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md b/i18n/fr/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md index ec47fd1f152..8cc8676c3c0 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md @@ -15,6 +15,12 @@ Dans le corps d’un workflow : - Évitez les requêtes réseau directes, dont la réponse, la vitesse et la disponibilité varient. Passez les données en entrée ou récupérez-les dans une activité. - Évitez les générateurs de nombres aléatoires et les autres sources d’aléa, sauf si le résultat est enregistré avec un effet de bord durable. Vous pouvez aussi passer la valeur aléatoire en entrée au démarrage. +## Journaliser depuis le code de workflow {#workflow-logging} + +Un worker reconstruit l’historique validé du workflow après les activations et remplacements à froid ; la journalisation ordinaire de l’application peut donc répéter les messages précédents. Utilisez le logger conscient du replay documenté pour votre binding lorsqu’il existe. Le mode service Rust fournit le [logger de workflow de Rust SDK 4.17](../polyglot/rust.md#workflow-logging) ; les autres bindings conservent leurs contrats documentés séparément. + +La journalisation est une observation du processus. Gardez les commandes durables indépendantes des observations du replay et de la livraison des logs. Même un logger conscient du replay peut répéter un message d’une tentative non validée après un crash ou un retry ; ce n’est pas une outbox garantissant exactement une fois. Les handlers hôtes doivent rester bornés et non bloquants pour ne pas immobiliser le worker. Placez les effets métier durables dans l’activité ou l’opération de workflow enregistrée appropriée. + ## Contrôles au démarrage {#boot-time-guardrails} Au démarrage, le package analyse les classes enregistrées dans `workflows.v2.types.workflows`. Il repère les appels manifestement incompatibles avec la relecture, comme `Carbon::now()`, `Auth::user()`, `DB::`, `Http::` et `random_int()`. La configuration `workflows.v2.guardrails.boot` détermine la réaction : diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/rust.md b/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/rust.md index 4868d6c46d2..77ea9e717de 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/rust.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/rust.md @@ -724,6 +724,22 @@ la forme booléenne de déploiement et `deprecate_patch(change_id)` préserve le marqueur après la fin des anciennes branches. Les [effets de bord](/docs/features/side-effects/) et la [gestion des versions](/docs/features/versioning/) décrivent ces règles communes. +## Journalisation de workflow consciente du replay {#workflow-logging} + +Rust SDK 4.17.0 ajoute `ctx.logger().info("message")` pour les observations issues du code de workflow. Les événements passent par le subscriber `tracing` existant de l’application, avec la cible `durable_workflow::workflow` et les champs immuables liés par le SDK `namespace`, `workflow_instance_id` et `workflow_run_id`. Configurez le subscriber hôte ; le SDK n’en installe aucun globalement. + +Les appels de journalisation ordinaires s’exécutent à nouveau lorsqu’un worker reconstruit l’historique du workflow. Le logger de workflow reste silencieux pendant le replay du préfixe validé, les requêtes/replays hors ligne et les historiques terminés, y compris après un remplacement à froid, ainsi qu’en dehors d’une invocation active. Il peut émettre uniquement dans une nouvelle exécution au-delà du préfixe avec une identité de run complète et liée. `ctx.replay_state()` observe cette frontière vivante de l’historique consommé, plutôt qu’un booléen figé au début de la tâche : + +| `WorkflowReplayState` | Observation | +| --- | --- | +| `Replaying` | Reconstruction de l’historique validé ou d’une requête ; les logs du workflow sont supprimés. | +| `Executing` | Nouvelle exécution au-delà du préfixe validé ; le retry d’une tâche non validée peut répéter des logs. | +| `Unavailable` | En dehors de cette invocation du workflow ou si l’état ne peut pas être lu sûrement ; les logs sont supprimés. | + +Gardez l’ordre des commandes durables indépendant de cet état d’observation et de la livraison des logs. Un log d’une tentative non validée peut se répéter après un crash ou un retry ; ce logger n’est pas une outbox garantissant exactement une fois. Gardez les handlers de l’application bornés et non bloquants, par exemple via une file de journalisation gérée par l’application. Les panics du subscriber avec déroulement de pile sont isolés du résultat du workflow ; les arrêts du processus et handlers bloquants restent à la charge de l’application. + +Consultez le [guide de journalisation publié](https://github.com/durable-workflow/sdk-rust/blob/4.17.0/README.md#workflow-logging), l’[API WorkflowLogger](https://rust.durable-workflow.com/durable_workflow/struct.WorkflowLogger.html) et l’[API WorkflowReplayState](https://rust.durable-workflow.com/durable_workflow/enum.WorkflowReplayState.html). Les [contrôles cycle de vie/deadline depuis le registre](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868388853) et l’[acceptation de journalisation avec quatre processus](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868494262) ont été enregistrés sur le tuple nommé native Server 3.10.0 linux/amd64. Les autres bindings et qualifications plus larges de replay/producteur gardent leur propre périmètre. + ## Règles de déterminisme Rust {#rust-determinism-rules} Une relecture doit produire les mêmes commandes durables dans le même ordre pour l’entrée et l’historique enregistrés. Les collections, horloges et primitives de concurrence ordinaires de Rust ne préservent pas automatiquement ce contrat : diff --git a/i18n/fr/source-hashes.json b/i18n/fr/source-hashes.json index b9d558d55e1..094463e2c6f 100644 --- a/i18n/fr/source-hashes.json +++ b/i18n/fr/source-hashes.json @@ -18,7 +18,7 @@ "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", "constraints/structural-limits.md": "5c7b7f6c86c5ca547eb3f200400ceab3b589f32d83866914f44e3a5a7d81e964", - "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", + "constraints/workflow-constraints.md": "f80f68b13877a67469a313b9fdcdbb27c1de6fe102cdfddb15e2af95997d2517", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", "defining-workflows/activities.md": "05b46f73477a0bbd5f21d17ac37def8a8eac53f1e629155805c98cc46e75b418", @@ -87,7 +87,7 @@ "polyglot/python.md": "82da06617fe24e70c5c89197d192a81430a282b788ef93afd3b3bcb690ba2a9f", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "2cc511074e6d0ce8ababa0ccd6acbdaa7df3bf5d8c67ae5ef2fa07d75a05d2e7", + "polyglot/rust.md": "31950634b8ccdb5c288ba871cc7f816de6683c52bf738bfdc13fa7aa825c6335", "polyglot/server-api-reference.md": "ecd6d358d6e5bde442ebf0e1ec8a072779089e2a5c4427e31eef646f42c6c03c", "polyglot/server-config-reference.md": "aec241c0046f12a9d6efe2d6c1de443d7753bdf34135e06a6f83b3904ed1d429", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md b/i18n/ja/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md index 1bc58badfe0..05595ec1c64 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md @@ -15,6 +15,12 @@ description: リプレイの決定性を保ち、起動時に安全でない呼 - 外部ネットワークへの直接リクエストは、応答、速度、可用性が変化します。必要なデータを開始時の入力に渡すか、アクティビティで取得してください。 - `sideEffect` に結果を記録する場合を除き、乱数生成器などのランダムな値を使わないでください。必要な値を開始時の入力に渡す方法もあります。 +## ワークフローコードからのロギング {#workflow-logging} + +worker は起動ごとの再開やコールド置換後に確定済みワークフロー履歴を再構築するため、通常のアプリケーションログは以前のメッセージを繰り返し得ます。利用可能なら、その binding で文書化されたリプレイ対応ロガーを使ってください。Rust サービスモードには [Rust SDK 4.17 のワークフローロガー](../polyglot/rust.md#workflow-logging)があります。他の binding はそれぞれの文書化された契約に従います。 + +ロギングはプロセスの観測です。永続ワークフローコマンドを、replay state の観測やログ配送に依存させないでください。リプレイ対応ロガーでも、未確定試行のメッセージはクラッシュや retry 後に重複し得ます。exactly-once outbox ではありません。ホスト handler は有界かつ非ブロッキングにし、worker を停止させないようにしてください。永続的な業務効果は、適切な activity または記録されるワークフロー操作に置いてください。 + ## 起動時のチェック {#boot-time-guardrails} `workflows.v2.types.workflows` に登録したクラスは、アプリ起動時にスキャンされます。`Carbon::now()`、`Auth::user()`、`DB::`、`Http::`、`random_int()` など、明らかにリプレイに安全でない呼び出しを検出します。`workflows.v2.guardrails.boot` で対応を指定します。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/rust.md b/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/rust.md index a73fd487283..12950e94741 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/rust.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/rust.md @@ -536,6 +536,22 @@ Rust SDK は `WorkflowContext::side_effect` で小さな非決定的値を記録 ロールアウト中に古いワークフロー分岐と新しい分岐のリプレイ互換性を保つには `WorkflowContext::get_version(change_id, min_supported, max_supported)` を使います。新しい実行は `max_supported` を記録し、既存の実行は永続マーカーを再利用します。`patched(change_id)` は真偽値形式のロールアウトを提供し、`deprecate_patch(change_id)` は古い分岐の処理完了後もマーカーを維持します。共有の永続的意味は[副作用](/docs/features/side-effects/)と[バージョニング](/docs/features/versioning/)を参照してください。 +## リプレイを認識するワークフローロギング {#workflow-logging} + +Rust SDK 4.17.0 はワークフローコードからの観測に `ctx.logger().info("message")` を提供します。アプリケーションの既存 `tracing` subscriber に、target `durable_workflow::workflow` と SDK が結び付けた不変の `namespace`、`workflow_instance_id`、`workflow_run_id` を付けて送ります。ホスト側 subscriber を設定してください。SDK はグローバル subscriber を登録しません。 + +通常のログ呼び出しは、worker がワークフロー履歴を再構築するたびに再実行されます。ワークフローロガーは、確定済みプレフィックス、query/offline、完了済み履歴のリプレイ中、worker のコールド置換後も、また有効な呼び出しの外でも出力しません。そのプレフィックスを越える新規実行で、完全な run identity が結び付いている場合にのみ出力できます。`ctx.replay_state()` は、タスク開始時に固定した boolean ではなく、消費した履歴の現在の境界を観測します。 + +| `WorkflowReplayState` | 観測 | +| --- | --- | +| `Replaying` | 確定済み履歴または query を再構築中です。ワークフローのログを抑制します。 | +| `Executing` | 確定済みプレフィックスを越える新規実行です。未確定タスクの再試行ではログが重複し得ます。 | +| `Unavailable` | このワークフロー呼び出しの外、または状態を安全に読めない場合です。ログを抑制します。 | + +永続コマンドの順序を、この観測状態やログ配送から独立させてください。未確定の試行のログはクラッシュや retry 後に重複し得るため、このロガーは exactly-once outbox ではありません。アプリ所有のログキューなどを用い、handler を有界かつ非ブロッキングにしてください。スタックを巻き戻す subscriber panic はワークフロー結果から隔離されます。プロセスの abort とブロッキング handler はアプリケーションの責任です。 + +[公開済みロギングガイド](https://github.com/durable-workflow/sdk-rust/blob/4.17.0/README.md#workflow-logging)、[WorkflowLogger API](https://rust.durable-workflow.com/durable_workflow/struct.WorkflowLogger.html)、[WorkflowReplayState API](https://rust.durable-workflow.com/durable_workflow/enum.WorkflowReplayState.html)を参照してください。[registry からの lifecycle/deadline 検証](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868388853)と[4プロセスのロギング受入検証](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868494262)は、明記された native Server 3.10.0 linux/amd64 の組合せで記録されました。他の binding や、より広い replay/producer の適格性は別の範囲です。 + ## Rust の決定性ルール {#rust-determinism-rules} リプレイでは、記録済みの入力と履歴に対して、同じ順序で同じ永続コマンドを生成する必要があります。Rust の通常のコレクション、時計、並行処理のプリミティブは、この契約を自動では保ちません。 diff --git a/i18n/ja/source-hashes.json b/i18n/ja/source-hashes.json index b9d558d55e1..094463e2c6f 100644 --- a/i18n/ja/source-hashes.json +++ b/i18n/ja/source-hashes.json @@ -18,7 +18,7 @@ "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", "constraints/structural-limits.md": "5c7b7f6c86c5ca547eb3f200400ceab3b589f32d83866914f44e3a5a7d81e964", - "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", + "constraints/workflow-constraints.md": "f80f68b13877a67469a313b9fdcdbb27c1de6fe102cdfddb15e2af95997d2517", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", "defining-workflows/activities.md": "05b46f73477a0bbd5f21d17ac37def8a8eac53f1e629155805c98cc46e75b418", @@ -87,7 +87,7 @@ "polyglot/python.md": "82da06617fe24e70c5c89197d192a81430a282b788ef93afd3b3bcb690ba2a9f", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "2cc511074e6d0ce8ababa0ccd6acbdaa7df3bf5d8c67ae5ef2fa07d75a05d2e7", + "polyglot/rust.md": "31950634b8ccdb5c288ba871cc7f816de6683c52bf738bfdc13fa7aa825c6335", "polyglot/server-api-reference.md": "ecd6d358d6e5bde442ebf0e1ec8a072779089e2a5c4427e31eef646f42c6c03c", "polyglot/server-config-reference.md": "aec241c0046f12a9d6efe2d6c1de443d7753bdf34135e06a6f83b3904ed1d429", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md b/i18n/pt-BR/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md index 56a797d9211..b28155f7dd5 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md @@ -15,6 +15,12 @@ Evite estas operações dentro de uma classe de workflow: - Não faça chamadas de rede para recursos externos, que podem estar lentos ou indisponíveis em momentos diferentes. Passe os dados necessários como entrada ao iniciar o workflow ou use uma atividade para buscá-los. - Não use geradores de números aleatórios, exceto dentro de um efeito registrado com `sideEffect`, nem outras fontes de aleatoriedade. Passe os valores aleatórios necessários como entrada ao iniciar o workflow. +## Logging no código do workflow {#workflow-logging} + +Um worker reconstrói o histórico confirmado após ativações e substituição a frio, por isso o logging comum da aplicação pode repetir mensagens anteriores. Use o logger consciente de replay documentado para seu binding quando disponível. O modo serviço Rust oferece o [logger de workflow do Rust SDK 4.17](../polyglot/rust.md#workflow-logging); outros bindings mantêm seus contratos documentados separadamente. + +Logging é uma observação do processo. Mantenha os comandos duráveis independentes das observações de replay e da entrega dos logs. Mesmo um logger consciente de replay pode repetir uma mensagem de tentativa não confirmada após falha ou retry; ele não é um outbox exatamente uma vez. Os handlers do host devem ser limitados e não bloqueantes para não parar o worker. Coloque efeitos duráveis de negócio na atividade ou operação registrada do workflow apropriada. + ## Verificações na inicialização {#boot-time-guardrails} Quando classes de workflow são registradas em `workflows.v2.types.workflows`, o pacote analisa o código na inicialização da aplicação para identificar chamadas obviamente inseguras para replay, como `Carbon::now()`, `Auth::user()`, `DB::`, `Http::` e `random_int()`. O tratamento dos resultados é definido por `workflows.v2.guardrails.boot`: diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/rust.md b/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/rust.md index aed47cf4a73..c3d8da26bff 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/rust.md +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/rust.md @@ -706,6 +706,22 @@ durável. `patched(change_id)` fornece a forma booleana de rollout, e drenado. Veja [Efeitos colaterais](/docs/features/side-effects/) e [Versionamento](/docs/features/versioning/) para a semântica durável compartilhada. +## Logging de workflow consciente de replay {#workflow-logging} + +O Rust SDK 4.17.0 adiciona `ctx.logger().info("message")` para observações no código do workflow. Os eventos vão para o subscriber `tracing` existente da aplicação, com target `durable_workflow::workflow` e os campos imutáveis vinculados pelo SDK `namespace`, `workflow_instance_id` e `workflow_run_id`. Configure o subscriber do host; o SDK não instala um subscriber global. + +Chamadas comuns de log executam novamente quando um worker reconstrói o histórico do workflow. O logger fica silencioso no replay do prefixo confirmado, de consultas/offline e de históricos concluídos, inclusive após substituição a frio do worker, e fora de uma invocação ativa. Ele só pode emitir em execução nova além desse prefixo com uma identidade de run completa e vinculada. `ctx.replay_state()` observa essa fronteira viva do histórico consumido, em vez de um booleano fixado no início da tarefa: + +| `WorkflowReplayState` | Observação | +| --- | --- | +| `Replaying` | Reconstrução de histórico confirmado ou consulta; logs do workflow são suprimidos. | +| `Executing` | Execução nova além do prefixo confirmado; repetir uma tarefa não confirmada pode repetir logs. | +| `Unavailable` | Fora desta invocação do workflow ou sem leitura segura do estado; os logs são suprimidos. | + +Mantenha a ordem de comandos duráveis independente desse estado de observação e da entrega de logs. Um log de tentativa não confirmada pode repetir após falha ou retry; o logger não é um outbox exatamente uma vez. Mantenha os handlers da aplicação limitados e não bloqueantes, por exemplo com uma fila de logging própria. Panics do subscriber com desempilhamento são isolados do resultado do workflow; abortos do processo e handlers bloqueantes continuam sendo responsabilidade da aplicação. + +Veja o [guia publicado de logging](https://github.com/durable-workflow/sdk-rust/blob/4.17.0/README.md#workflow-logging), a [API WorkflowLogger](https://rust.durable-workflow.com/durable_workflow/struct.WorkflowLogger.html) e a [API WorkflowReplayState](https://rust.durable-workflow.com/durable_workflow/enum.WorkflowReplayState.html). Os [controles de lifecycle/deadline do registro](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868388853) e a [aceitação de logging com quatro processos](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868494262) foram registrados na tupla nomeada native Server 3.10.0 linux/amd64. Outros bindings e qualificações mais amplas de replay/produtor mantêm seus próprios escopos. + ## Regras de determinismo do Rust {#rust-determinism-rules} Um replay deve produzir os mesmos comandos duráveis, na mesma ordem, para a entrada e o histórico registrados. Coleções, relógios e primitivas de concorrência comuns do Rust não preservam automaticamente esse contrato: diff --git a/i18n/pt-BR/source-hashes.json b/i18n/pt-BR/source-hashes.json index b9d558d55e1..094463e2c6f 100644 --- a/i18n/pt-BR/source-hashes.json +++ b/i18n/pt-BR/source-hashes.json @@ -18,7 +18,7 @@ "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", "constraints/structural-limits.md": "5c7b7f6c86c5ca547eb3f200400ceab3b589f32d83866914f44e3a5a7d81e964", - "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", + "constraints/workflow-constraints.md": "f80f68b13877a67469a313b9fdcdbb27c1de6fe102cdfddb15e2af95997d2517", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", "defining-workflows/activities.md": "05b46f73477a0bbd5f21d17ac37def8a8eac53f1e629155805c98cc46e75b418", @@ -87,7 +87,7 @@ "polyglot/python.md": "82da06617fe24e70c5c89197d192a81430a282b788ef93afd3b3bcb690ba2a9f", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "2cc511074e6d0ce8ababa0ccd6acbdaa7df3bf5d8c67ae5ef2fa07d75a05d2e7", + "polyglot/rust.md": "31950634b8ccdb5c288ba871cc7f816de6683c52bf738bfdc13fa7aa825c6335", "polyglot/server-api-reference.md": "ecd6d358d6e5bde442ebf0e1ec8a072779089e2a5c4427e31eef646f42c6c03c", "polyglot/server-config-reference.md": "aec241c0046f12a9d6efe2d6c1de443d7753bdf34135e06a6f83b3904ed1d429", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md b/i18n/uk/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md index b3be3fe2b56..28de05ffa3d 100644 --- a/i18n/uk/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md +++ b/i18n/uk/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md @@ -26,6 +26,12 @@ sidebar_position: 2 без побічного ефекту, бо кожен виклик дає інший результат. Передавайте потрібну випадковість як вхідні дані workflow під час запуску. +## Журналювання з коду workflow {#workflow-logging} + +Worker відновлює зафіксовану історію workflow після активацій і холодної заміни, тому звичайне журналювання застосунку може повторювати попередні повідомлення. За наявності використовуйте документований для вашого binding logger з урахуванням replay. Rust service mode надає [logger workflow у Rust SDK 4.17](../polyglot/rust.md#workflow-logging); інші binding зберігають окремо документовані контракти. + +Журналювання — це спостереження процесу. Довговічні команди workflow мають бути незалежними від спостережень replay-state та доставки журналу. Навіть logger з урахуванням replay може повторити повідомлення незафіксованої спроби після збою чи retry; це не outbox із гарантією exactly-once. Обробники хоста мають бути обмеженими й неблокувальними, щоб журналювання не затримувало worker. Довговічні бізнес-ефекти розміщуйте у відповідній activity або записаній операції workflow. + ## Перевірки під час запуску застосунку {#boot-time-guardrails} Коли класи workflow зареєстровані в `workflows.v2.types.workflows`, пакет під час diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/rust.md b/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/rust.md index f4086570efa..dce817ab2cd 100644 --- a/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/rust.md +++ b/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/rust.md @@ -715,6 +715,22 @@ Rust SDK записує невеликі недетерміновані знач Спільну durable-семантику описано в [side effects](/docs/features/side-effects/) та [версіюванні](/docs/features/versioning/). +## Журналювання workflow з урахуванням replay {#workflow-logging} + +Rust SDK 4.17.0 додає `ctx.logger().info("message")` для спостережень із коду workflow. Події надходять до наявного `tracing` subscriber застосунку з target `durable_workflow::workflow` та незмінними прив’язаними SDK полями `namespace`, `workflow_instance_id` і `workflow_run_id`. Налаштуйте subscriber хоста; SDK не встановлює глобальний subscriber. + +Звичайні виклики журналювання виконуються знову, коли worker відновлює історію workflow. Logger workflow не видає повідомлень під час replay зафіксованого префікса, query/offline та завершених історій, зокрема після холодної заміни worker, а також поза активним викликом. Він може видавати повідомлення лише в новому виконанні після цього префікса з повною прив’язаною ідентичністю run. `ctx.replay_state()` спостерігає поточну межу спожитої історії, а не Boolean, зафіксований на початку task: + +| `WorkflowReplayState` | Спостереження | +| --- | --- | +| `Replaying` | Відновлення зафіксованої історії або query; повідомлення workflow пригнічуються. | +| `Executing` | Нове виконання після зафіксованого префікса; повтор незафіксованої task може повторити повідомлення. | +| `Unavailable` | Поза цим викликом workflow або без можливості безпечно прочитати стан; повідомлення пригнічуються. | + +Порядок довговічних команд має бути незалежним від цього стану спостереження й доставки журналу. Повідомлення незафіксованої спроби може повторитися після збою чи retry; logger не є outbox із гарантією exactly-once. Обробники застосунку мають бути обмеженими й неблокувальними, наприклад із власною чергою журналювання. Panic subscriber з розкручуванням стека ізольовано від результату workflow; переривання процесу та блокувальні обробники залишаються відповідальністю застосунку. + +Дивіться [опублікований посібник журналювання](https://github.com/durable-workflow/sdk-rust/blob/4.17.0/README.md#workflow-logging), [API WorkflowLogger](https://rust.durable-workflow.com/durable_workflow/struct.WorkflowLogger.html) та [API WorkflowReplayState](https://rust.durable-workflow.com/durable_workflow/enum.WorkflowReplayState.html). [Registry-перевірки lifecycle/deadline](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868388853) і [приймання журналювання з чотирма процесами](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868494262) записано на вказаному кортежі native Server 3.10.0 linux/amd64. Інші binding та ширша кваліфікація replay/producer зберігають окремі межі. + ## Правила детермінізму Rust {#rust-determinism-rules} Replay має створювати ті самі durable-команди в тому самому порядку для записаного входу й історії. Звичайні колекції, годинники та примітиви конкурентності Rust не зберігають цей контракт автоматично: diff --git a/i18n/uk/source-hashes.json b/i18n/uk/source-hashes.json index b9d558d55e1..094463e2c6f 100644 --- a/i18n/uk/source-hashes.json +++ b/i18n/uk/source-hashes.json @@ -18,7 +18,7 @@ "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", "constraints/structural-limits.md": "5c7b7f6c86c5ca547eb3f200400ceab3b589f32d83866914f44e3a5a7d81e964", - "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", + "constraints/workflow-constraints.md": "f80f68b13877a67469a313b9fdcdbb27c1de6fe102cdfddb15e2af95997d2517", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", "defining-workflows/activities.md": "05b46f73477a0bbd5f21d17ac37def8a8eac53f1e629155805c98cc46e75b418", @@ -87,7 +87,7 @@ "polyglot/python.md": "82da06617fe24e70c5c89197d192a81430a282b788ef93afd3b3bcb690ba2a9f", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "2cc511074e6d0ce8ababa0ccd6acbdaa7df3bf5d8c67ae5ef2fa07d75a05d2e7", + "polyglot/rust.md": "31950634b8ccdb5c288ba871cc7f816de6683c52bf738bfdc13fa7aa825c6335", "polyglot/server-api-reference.md": "ecd6d358d6e5bde442ebf0e1ec8a072779089e2a5c4427e31eef646f42c6c03c", "polyglot/server-config-reference.md": "aec241c0046f12a9d6efe2d6c1de443d7753bdf34135e06a6f83b3904ed1d429", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", diff --git a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md index 30f97e4450c..0f54fe06626 100644 --- a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md +++ b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/constraints/workflow-constraints.md @@ -15,6 +15,12 @@ description: 保持重放的确定性,并在应用启动时发现不安全的 - 不要直接请求外部网络资源,因为其响应、速度和可用性可能变化。在启动时传入所需数据,或通过活动获取数据。 - 不要直接使用随机数生成器或其他随机来源,除非将结果记录在 `sideEffect` 中。也可以在启动工作流时把所需随机值作为输入传入。 +## 从 workflow 代码记录日志 {#workflow-logging} + +worker 在激活和冷替换后重建已提交的 workflow 历史,因此普通应用日志可能重复先前的消息。若对应 binding 提供了已文档化的重放感知 logger,请使用该接口。Rust 服务模式提供 [Rust SDK 4.17 workflow logger](../polyglot/rust.md#workflow-logging);其他 binding 保留各自文档中的契约。 + +日志是进程观测。持久 workflow 命令应独立于重放状态观测和日志投递。即使使用重放感知 logger,未提交尝试的消息也可能在崩溃或 retry 后重复;它不是 exactly-once outbox。主机 handler 应有界且非阻塞,避免日志阻塞 worker。应通过合适的 activity 或有记录的 workflow 操作执行持久业务效果。 + ## 启动时检查 {#boot-time-guardrails} 注册在 `workflows.v2.types.workflows` 下的工作流类,会在应用启动时接受扫描,检测 `Carbon::now()`、`Auth::user()`、`DB::`、`Http::`、`random_int()` 等明显不安全的重放调用。`workflows.v2.guardrails.boot` 决定如何处理结果: diff --git a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/rust.md b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/rust.md index 7a7fa7c3cbc..ab57802a6a6 100644 --- a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/rust.md +++ b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/rust.md @@ -531,6 +531,22 @@ Rust SDK 使用 `WorkflowContext::side_effect` 记录小型非确定性值,并 使用 `WorkflowContext::get_version(change_id, min_supported, max_supported)`,在发布期间保持新旧工作流分支重放兼容。新运行记录 `max_supported`;现有运行复用持久标记。`patched(change_id)` 提供布尔形式的发布控制;旧分支排空后,`deprecate_patch(change_id)` 保留标记。共享持久语义见[副作用](/docs/features/side-effects/)和[版本管理](/docs/features/versioning/)。 +## 感知重放的 workflow 日志 {#workflow-logging} + +Rust SDK 4.17.0 添加 `ctx.logger().info("message")`,用于 workflow 代码中的观测。它通过应用已有的 `tracing` subscriber 发送事件,使用 target `durable_workflow::workflow`,以及由 SDK 绑定的不可变字段 `namespace`、`workflow_instance_id` 和 `workflow_run_id`。请配置主机 subscriber;SDK 不安装全局 subscriber。 + +worker 重建 workflow 历史时,普通日志调用会再次执行。workflow logger 在已提交前缀、query/offline 和已完成历史的重放期间保持静默,包括 worker 冷替换后;在活动调用之外也保持静默。它只能在前缀之后的新执行中、且有完整绑定的 run identity 时发送日志。`ctx.replay_state()` 观测已消费历史的实时边界,而不是 task 开始时固定的布尔值: + +| `WorkflowReplayState` | 观测 | +| --- | --- | +| `Replaying` | 正在重建已提交历史或 query;抑制 workflow 日志。 | +| `Executing` | 已提交前缀之后的新执行;未提交 task 的重试可能重复日志。 | +| `Unavailable` | 在本次 workflow 调用之外,或无法安全读取状态;抑制日志。 | + +持久命令顺序应独立于该观测状态及日志投递。未提交尝试的日志可能在崩溃或 retry 后重复,因此 logger 不是 exactly-once outbox。应用 handler 应有界且非阻塞,例如使用应用自行管理的日志队列。会展开栈的 subscriber panic 与 workflow 结果隔离;进程 abort 和阻塞 handler 仍由应用负责。 + +参见[已发布日志指南](https://github.com/durable-workflow/sdk-rust/blob/4.17.0/README.md#workflow-logging)、[WorkflowLogger API](https://rust.durable-workflow.com/durable_workflow/struct.WorkflowLogger.html) 和 [WorkflowReplayState API](https://rust.durable-workflow.com/durable_workflow/enum.WorkflowReplayState.html)。[registry lifecycle/deadline 控制](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868388853)与[四进程日志验收](https://github.com/durable-workflow/sdk-rust/pull/269#issuecomment-6868494262)记录于明确指定的 native Server 3.10.0 linux/amd64 组合。其他 binding 以及更广泛的 replay/producer 验收各自保留范围。 + ## Rust 确定性规则 {#rust-determinism-rules} 对于已记录的输入和历史,重放必须按相同顺序生成相同的持久命令。Rust 常规集合、时钟和并发原语不会自动保持这一约定: diff --git a/i18n/zh-Hans/source-hashes.json b/i18n/zh-Hans/source-hashes.json index b9d558d55e1..094463e2c6f 100644 --- a/i18n/zh-Hans/source-hashes.json +++ b/i18n/zh-Hans/source-hashes.json @@ -18,7 +18,7 @@ "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", "constraints/structural-limits.md": "5c7b7f6c86c5ca547eb3f200400ceab3b589f32d83866914f44e3a5a7d81e964", - "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", + "constraints/workflow-constraints.md": "f80f68b13877a67469a313b9fdcdbb27c1de6fe102cdfddb15e2af95997d2517", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", "defining-workflows/activities.md": "05b46f73477a0bbd5f21d17ac37def8a8eac53f1e629155805c98cc46e75b418", @@ -87,7 +87,7 @@ "polyglot/python.md": "82da06617fe24e70c5c89197d192a81430a282b788ef93afd3b3bcb690ba2a9f", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "2cc511074e6d0ce8ababa0ccd6acbdaa7df3bf5d8c67ae5ef2fa07d75a05d2e7", + "polyglot/rust.md": "31950634b8ccdb5c288ba871cc7f816de6683c52bf738bfdc13fa7aa825c6335", "polyglot/server-api-reference.md": "ecd6d358d6e5bde442ebf0e1ec8a072779089e2a5c4427e31eef646f42c6c03c", "polyglot/server-config-reference.md": "aec241c0046f12a9d6efe2d6c1de443d7753bdf34135e06a6f83b3904ed1d429", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", diff --git a/static/stable-releases.json b/static/stable-releases.json index 0b411f67243..362f997607f 100644 --- a/static/stable-releases.json +++ b/static/stable-releases.json @@ -1,13 +1,13 @@ { "schema": "durable-workflow.docs.stable-releases", "schema_version": 1, - "updated_at": "2026-11-13", + "updated_at": "2026-11-14", "artifacts": { "cli": "2.8.0", "helm-chart": "2.0.0", "sdk-php": "3.18.2", "sdk-python": "2.17.2", - "sdk-rust": "4.16.0", + "sdk-rust": "4.17.0", "server": "3.10.0", "waterline": "2.18.0", "workflow": "2.28.0"