Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/constraints/workflow-constraints.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`:
Expand Down
16 changes: 16 additions & 0 deletions docs/polyglot/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
16 changes: 16 additions & 0 deletions i18n/de/docusaurus-plugin-content-docs/current/polyglot/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions i18n/de/source-hashes.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions i18n/es/docusaurus-plugin-content-docs/current/polyglot/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions i18n/es/source-hashes.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 :
Expand Down
Loading
Loading