diff --git a/docs/constraints/structural-limits.md b/docs/constraints/structural-limits.md index 9821426b7d7..780674815d2 100644 --- a/docs/constraints/structural-limits.md +++ b/docs/constraints/structural-limits.md @@ -261,69 +261,10 @@ The full contract is available in the `structural_limits` section of the backend Waterline surfaces structural-limit failures in the exceptions table with the `structural_limit` failure category. The timeline failure details include the limit kind, current value, and configured ceiling. -## Server request-boundary limits +## Service Mode limits {#server-request-boundary-limits} -When using the standalone server, a separate set of caps is enforced at the HTTP request boundary before a workflow task, signal, update, or query ever reaches the control plane. These limits fail fast with a `422 validation_failed` (or `413 payload_too_large` for whole-body checks) response so clients learn the rejection reason without the server writing any row to the database. - -| Limit | Default | Config key | What it caps | -|---|---|---|---| -| Body size | 2 MiB | `server.limits.max_payload_bytes` | Total HTTP request body bytes, except a workflow-task completion on native Server 3.6.0 or later (next row) | -| Workflow-task completion size | 32 MiB (16 × body size) | derived from `server.limits.max_payload_bytes` | Native Server 3.6.0 or later: a request that completes a workflow task with commands. Each command's arguments still meet the per-payload limit | -| Memo size | 256 KiB | `server.limits.max_memo_bytes` | Serialized memo on `POST /workflows` and `POST /schedules` | -| Search-attribute count | 100 | `server.limits.max_search_attributes` | Registered custom search attributes per namespace | -| Search-attribute key length | 128 bytes | `server.limits.max_search_attribute_key_length` | Length of a single SA key on start | -| Search-attribute value size | 2 KiB | `server.limits.max_search_attribute_value_bytes` | Each string value (and each element of an array value) on start | -| Signal / update / query name | 256 bytes | `server.limits.max_operation_name_length` | URL path segment for signal/update/query names | -| `workflow_id` length | 128 chars | controller validator | Workflow ID on `POST /workflows` | -| `workflow_type` / `task_queue` / `business_key` | 255 chars | controller validator | String fields on `POST /workflows` | -| `request_id` | 255 chars | controller validator | Deduplication token on signals/updates/cancel/terminate | -| `reason` | 1,000 chars | controller validator | Reason text on cancel/terminate/archive | - -Each limit is individually configurable via `DW_*` environment variables (see `config/dw-contract.php` for the full contract). Setting a value of `0` disables the check for that specific limit, but leaves the others in force. - -The currently-configured values are published under `limits` on the `GET /api/cluster/info` response, so clients can discover them at runtime: - -```json -{ - "limits": { - "max_payload_bytes": 2097152, - "max_memo_bytes": 262144, - "max_search_attributes": 100, - "max_search_attribute_key_length": 128, - "max_search_attribute_value_bytes": 2048, - "max_operation_name_length": 256, - "max_pending_activities": 2000, - "max_pending_children": 2000 - } -} -``` - -Validation errors are returned in the standard control-plane error envelope with `reason: "validation_failed"` and a `validation_errors` map keyed by the offending field (`signal_name`, `update_name`, `query_name`, `search_attributes`, `memo`, and so on). Payload-size rejections use `reason: "payload_too_large"` and the `413` status code. +Server and Cloud HTTP request limits are separate from these embedded Laravel controls. See the [Server request reference](../polyglot/server-config-reference.md#server-request-boundary-limits). ### Workflow-task completion size {#workflow-task-completion-size} -On native Server 3.6.0 and later, a request that completes a workflow task -with commands (`POST /api/worker/workflow-tasks/{id}/complete` and -`POST /api/worker/activity-tasks/{id}/continuation/complete`) may be up to 16 -times `max_payload_bytes`: 32 MiB with the default 2 MiB. It follows -`DW_MAX_PAYLOAD_BYTES` and has no setting of its own. Each command's arguments -still meet the per-payload limit inside the completion. PHP Server 2.x and -earlier native releases cap a completion at one payload limit, like any other -request. - -A larger completion is refused with `413 payload_too_large` and -`limit_kind: workflow_task_completion_bytes` before anything is recorded. -Replaying the task produces the same commands, so sending the completion again -gets the same refusal. PHP SDK 3.17.0 and later never resend it: the worker -fails the run once with a `fail_workflow` command whose message starts -`Structural limit exceeded: workflow_task_completion_bytes:` and names both -sizes, and the Server records the failure with -`failure_category = structural_limit`. The Python and Rust SDKs will do the -same in their next releases. - -To keep a completion within the limit: - -- Split a large fan-out into smaller batches across workflow tasks. -- Move work into child workflows, or continue as new. -- Store large arguments with external payload storage, so the completion - carries references instead of the payloads. +Service Mode completion caps and SDK refusal behavior are covered in the [Server reference](../polyglot/server-config-reference.md#workflow-task-completion-size). diff --git a/docs/polyglot/cli-reference.md b/docs/polyglot/cli-reference.md index 6871b1379fb..0a8bbc17158 100644 --- a/docs/polyglot/cli-reference.md +++ b/docs/polyglot/cli-reference.md @@ -238,6 +238,7 @@ runtime environment and not in the profile file. | `dw workflow:signal ` | Send a signal. | `--run-id`, input options, `--json` | | `dw workflow:query ` | Execute a read-only workflow query. | `--run-id`, input options, `--json` | | `dw workflow:update ` | Submit or execute a workflow update. | `--wait=accepted\|completed`, `--run-id`, input options, `--json` | +| `dw workflow:update-outcome ` | Read a retained update outcome without submitting it again. | `--wait=accepted\|completed`, `--wait-timeout`, `--json` | | `dw workflow:cancel [workflow-id]` | Close one workflow or a selected batch as cancelled; no workflow-code cleanup runs. | `--reason`, `--run-id`, `--all-matching`, `--type`, `--status`, `--limit`, `--yes`, `--json` | | `dw workflow:terminate ` | Force terminate a workflow. | `--reason`, `--run-id`, `--json` | | `dw workflow:repair ` | Ask the server to repair a stuck or retryable run. | `--json` | @@ -262,6 +263,28 @@ dw workflow:cancel --all-matching='WorkflowType = "ImportJob"' --limit=25 --yes validate canonical request fields against the server-published request contract. Non-canonical legacy aliases are rejected before the request is sent. +### Read an update outcome {#read-update-outcome} + +CLI 2.8 and later can read an accepted update by its `update_id` on a Server +that advertises `capabilities.update_outcome_reads` (native 3.6.0 or later). +Use the ID from the accepted receipt: + +```bash +dw workflow:update-outcome order-123 "$UPDATE_ID" +dw workflow:update-outcome order-123 "$UPDATE_ID" --wait=completed --wait-timeout=30 +``` + +The default `--wait=accepted` answers immediately. An accepted update that has +not finished stays pending, including when a completion wait expires. A +completed update can have a null result. `--json` returns the checked receipt, +so use its `update_status` to distinguish these cases. Each invocation makes +one outcome read and never resubmits the update. + +`--wait-timeout` requires `--wait=completed` and an integer of at least one +second. A failed update exits 2. An unknown or pruned update ID exits 5, which +does not prove the update was never admitted. A Server without the capability, +including PHP Server 2.x, exits 8 before an outcome request is sent. + ## Service Call Inspection Use `dw service-call:describe ` diff --git a/docs/polyglot/cli.mdx b/docs/polyglot/cli.mdx index 93103a2b4e8..8e32cbc7dd4 100644 --- a/docs/polyglot/cli.mdx +++ b/docs/polyglot/cli.mdx @@ -279,6 +279,11 @@ Every command that accepts caller payloads uses the same input shape: and `--input-encoding=json|raw|base64`. JSON is the default; raw and base64 inputs are passed as one positional workflow argument. +Use `dw workflow:update-outcome` to read an accepted update later without +submitting it again. Pending is distinct from a completed null result. See +[read an update outcome](./cli-reference.md#read-update-outcome) for the Server +capability requirement and wait options. + ### Bridge Adapters ```bash diff --git a/docs/polyglot/python.md b/docs/polyglot/python.md index 239cba5369d..c9c090ba258 100644 --- a/docs/polyglot/python.md +++ b/docs/polyglot/python.md @@ -131,6 +131,17 @@ Python SDK 2.15 and 2.16 add: See the [2.16.0 changelog](https://github.com/durable-workflow/sdk-python/blob/2.16.0/CHANGELOG.md) for the complete list. +Python SDK 2.17 adds `Client.update_outcome` and +`Client.update_outcome_receipt` to read an accepted update later without +submitting it again. These methods require +`capabilities.update_outcome_reads` (native Server 3.6.0 or later). +`update_outcome` waits for completion by default and raises `UpdateStillPending` +if the update is unfinished. A returned `None` is a completed null result. +`update_outcome_receipt` defaults to the accepted stage and preserves the +explicit `update_status`. See the +[Python SDK update-outcome guide](https://python.durable-workflow.com/reference/client/#read-an-update-outcome) +for language-specific examples. + ## Quickstart Here is a complete Python program that defines a workflow with one activity, starts it against a local Durable Workflow server, and waits for the result: @@ -452,13 +463,20 @@ end-to-end rollout walkthrough; the CLI mirrors of these methods are | `await client.export_history(workflow_id, run_id)` | decoded archival history payload | `WorkflowNotFound`, auth/server errors | | `await client.signal_workflow(workflow_id, signal_name, args=None)` | `None` | `WorkflowNotFound`, `InvalidArgument`, auth/server errors | | `await client.query_workflow(workflow_id, query_name, args=None)` | decoded query result | `QueryFailed`, `WorkflowNotFound`, auth/server errors | -| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | decoded update result | `UpdateRejected`, `WorkflowNotFound`, auth/server errors | +| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | update receipt (`dict`) | `UpdateRejected`, `UpdateValidationFailed`, `UpdateFailed`, `WorkflowNotFound`, auth/server errors | | `await client.cancel_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, auth/server errors | | `await client.terminate_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, auth/server errors | | `await client.repair_workflow(workflow_id)` | `WorkflowCommandResult` | `WorkflowNotFound`, auth/server errors | | `await client.archive_workflow(workflow_id, reason=None)` | `WorkflowCommandResult` | `WorkflowNotFound`, auth/server errors | | `await client.get_result(handle, poll_interval=0.5, timeout=30.0)` | decoded workflow output | `WorkflowFailed`, `WorkflowCancelled`, `WorkflowTerminated`, `TimeoutError` | +`update_workflow` defaults to `wait_for="accepted"`. Its receipt can have +`update_status="accepted"` and `result=None`. With `wait_for="completed"`, +`wait_timeout_seconds` bounds the wait. On expiry, the receipt stays accepted +and sets `wait_timed_out=True`. Only `update_status="completed"` identifies a +finished result, including `None`. Keep `update_id` for +[later outcome reads](https://python.durable-workflow.com/reference/client/#read-an-update-outcome). + `start_workflow` accepts `workflow_type`, `task_queue`, optional `workflow_id`, optional `input`, `duplicate_policy`, `memo`, `search_attributes`, `business_key`, `execution_timeout_seconds`, and diff --git a/docs/polyglot/rust.md b/docs/polyglot/rust.md index 618609c2af9..5a43d2fee12 100644 --- a/docs/polyglot/rust.md +++ b/docs/polyglot/rust.md @@ -137,6 +137,21 @@ protocol manifests determine compatibility. See the [4.13.0 changelog](https://github.com/durable-workflow/sdk-rust/blob/4.13.0/CHANGELOG.md). +## Read retained update outcomes {#read-update-outcome} + +Rust SDK 4.15 adds `Client::update_outcome` and +`Client::update_outcome_receipt` to read an accepted update by ID without +submitting it again. These methods require `capabilities.update_outcome_reads` +(native Server 3.6.0 or later). `update_outcome` returns +`Error::UpdateStillPending` for an unfinished update. A completed null result +is `Ok(Value::Null)`. Receipt reads preserve the explicit `update_status`. +See the [Client API](https://rust.durable-workflow.com/durable_workflow/struct.Client.html#method.update_outcome) +for the Rust interface. + +Rust SDK 4.15.0 still applies the ordinary payload ceiling to the whole +command batch. See the [known planner limit](./server-config-reference.md#rust-completion-planning) +before running a large fan-out without external payload storage. + ## Condition wait deadlines and worker upgrades {#condition-wait-deadlines} Rust SDK 4.11.2 measures an ungrouped `wait_condition` timeout from its first diff --git a/docs/polyglot/server-config-reference.md b/docs/polyglot/server-config-reference.md index d8e4b5aacc3..a3761b93c5a 100644 --- a/docs/polyglot/server-config-reference.md +++ b/docs/polyglot/server-config-reference.md @@ -342,6 +342,95 @@ default. | `DW_MAX_NEXUS_OPERATIONS_PER_CALLER` | `200` | Maximum Nexus operations returned per caller from the operations history surface before clients must paginate. | `WORKFLOW_MAX_NEXUS_OPERATIONS_PER_CALLER` | | `DW_COMPRESSION_ENABLED` | `true` | Enable JSON response compression above the minimum size threshold. | `WORKFLOW_SERVER_COMPRESSION_ENABLED` | +## Server request-boundary limits {#server-request-boundary-limits} + +When using the standalone server, a separate set of caps is enforced at the HTTP request boundary before a workflow task, signal, update, or query ever reaches the control plane. These limits fail fast with a `422 validation_failed` (or `413 payload_too_large` for whole-body checks) response so clients learn the rejection reason without the server writing any row to the database. + +| Limit | Default | Config key | What it caps | +|---|---|---|---| +| Body size | 2 MiB | `server.limits.max_payload_bytes` | Total HTTP request body bytes, except a workflow-task completion on native Server 3.6.0 or later (next row) | +| Workflow-task completion size | 32 MiB (16 × body size) | derived from `server.limits.max_payload_bytes` | Native Server 3.6.0 or later: a request that completes a workflow task with commands. Each command's arguments still meet the per-payload limit | +| Memo size | 256 KiB | `server.limits.max_memo_bytes` | Serialized memo on `POST /workflows` and `POST /schedules` | +| Search-attribute count | 100 | `server.limits.max_search_attributes` | Registered custom search attributes per namespace | +| Search-attribute key length | 128 bytes | `server.limits.max_search_attribute_key_length` | Length of a single SA key on start | +| Search-attribute value size | 2 KiB | `server.limits.max_search_attribute_value_bytes` | Each string value (and each element of an array value) on start | +| Signal / update / query name | 256 bytes | `server.limits.max_operation_name_length` | URL path segment for signal/update/query names | +| `workflow_id` length | 128 chars | controller validator | Workflow ID on `POST /workflows` | +| `workflow_type` / `task_queue` / `business_key` | 255 chars | controller validator | String fields on `POST /workflows` | +| `request_id` | 255 chars | controller validator | Deduplication token on signals/updates/cancel/terminate | +| `reason` | 1,000 chars | controller validator | Reason text on cancel/terminate/archive | + +Use the documented `DW_*` settings for configurable PHP Server 2.x limits. +Controller-validator bounds are fixed. Native Server 3.x supports the settings +listed in its [implementation notes](#native-server-3x). On native 3.8.0, +`DW_MAX_PAYLOAD_BYTES=0` sets a zero-byte ceiling for ordinary requests and +workflow-task completions, rejecting nonempty bodies. Its operation-name +ceiling is fixed at 256 bytes. + +The currently-configured values are published under `limits` on the `GET /api/cluster/info` response, so clients can discover them at runtime: + +```json +{ + "limits": { + "max_payload_bytes": 2097152, + "max_memo_bytes": 262144, + "max_search_attributes": 100, + "max_search_attribute_key_length": 128, + "max_search_attribute_value_bytes": 2048, + "max_operation_name_length": 256, + "max_pending_activities": 2000, + "max_pending_children": 2000 + } +} +``` + +Validation errors are returned in the standard control-plane error envelope with `reason: "validation_failed"` and a `validation_errors` map keyed by the offending field (`signal_name`, `update_name`, `query_name`, `search_attributes`, `memo`, and so on). Payload-size rejections use `reason: "payload_too_large"` and the `413` status code. + +### Workflow-task completion size {#workflow-task-completion-size} + +On native Server 3.6.0 and later, a request that completes a workflow task +with commands (`POST /api/worker/workflow-tasks/{id}/complete` and +`POST /api/worker/activity-tasks/{id}/continuation/complete`) may be up to 16 +times `max_payload_bytes`: 32 MiB with the default 2 MiB. It follows +`DW_MAX_PAYLOAD_BYTES` and has no setting of its own. Each command's arguments +still meet the per-payload limit inside the completion. PHP Server 2.x and +earlier native releases cap a completion at one payload limit, like any other +request. + +A larger completion is refused with `413 payload_too_large` and +`limit_kind: workflow_task_completion_bytes` before anything is recorded. +Replaying the task produces the same commands, so sending the completion again +gets the same refusal. When PHP SDK 3.17.0 or later receives this typed refusal, it does not resend +the completion: the worker fails the run once with a `fail_workflow` command whose message starts +`Structural limit exceeded: workflow_task_completion_bytes:` and names both +sizes, and the Server records the failure with +`failure_category = structural_limit`. + +Python SDK 2.17 and Rust SDK 4.15 include handling for the typed refusal. +On Server 3.8.0, an oversized completion can fail at the transport before the +worker receives HTTP 413. In the published Python test, `httpx.ReadError` left +the workflow pending instead of failing structurally. Published-Server +over-limit acceptance remains open under the +[Server response fix](https://github.com/durable-workflow/.github/issues/228#issuecomment-6848969678). +Reduce completion sizes until that path is qualified. + +To keep a completion within the limit: + +- Split a large fan-out into smaller batches across workflow tasks. +- Move work into child workflows, or continue as new. +- Store large arguments with external payload storage, so the completion + carries references instead of the payloads. + +#### Rust command planning {#rust-completion-planning} + +Rust SDK 4.15.0 still uses the ordinary per-payload limit as the aggregate +command-planning ceiling (2 MiB by default), before the Server's larger +completion allowance. Without namespace external payload storage, the +published 300 × 10 KB fan-out is refused with `external_payload_unavailable`; +the worker exits and the run remains pending. Use smaller command batches +while the [SDK aggregate planner fix](https://github.com/durable-workflow/sdk-rust/issues/254) +is pending. This SDK path does not yet implement the larger Server allowance. + ## Docker Bootstrap And Provenance | Variable | Default | Purpose | Legacy alias | diff --git a/i18n/de/docusaurus-plugin-content-docs/current/constraints/structural-limits.md b/i18n/de/docusaurus-plugin-content-docs/current/constraints/structural-limits.md index 7a275a610fe..5920576cb4c 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/constraints/structural-limits.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/constraints/structural-limits.md @@ -326,66 +326,10 @@ Waterline zeigt Fehler struktureller Grenzen in der Ausnahmentabelle mit der Fehlerkategorie `structural_limit`. Die Fehlerdetails der Zeitleiste enthalten Grenzart, aktuellen Wert und konfigurierte Obergrenze. -## Grenzen an der Server-Anfragegrenze {#server-request-boundary-limits} - -Beim eigenständigen Server werden separate Grenzen an der -HTTP-Anfragegrenze durchgesetzt, bevor Workflow-Aufgabe, Signal, Update oder -Abfrage die Steuerungsebene erreichen. Diese Grenzen liefern sofort -`422 validation_failed` (oder `413 payload_too_large` bei Prüfung des gesamten -Anfragetexts). Clients erfahren so den Ablehnungsgrund, ohne dass der Server -eine Datenbankzeile schreibt. - -| Grenze | Standard | Konfigurationsschlüssel | Was sie begrenzt | -|---|---|---|---| -| Anfragetextgröße | 2 MiB | `server.limits.max_payload_bytes` | Gesamtzahl der Bytes im HTTP-Anfragetext, außer bei einem Workflow-Task-Abschluss auf nativem Server 3.6.0 oder neuer (nächste Zeile) | -| Größe eines Workflow-Task-Abschlusses | 32 MiB (16 × Anfragetextgröße) | abgeleitet von `server.limits.max_payload_bytes` | Nativer Server 3.6.0 oder neuer: eine Anfrage, die einen Workflow-Task mit Befehlen abschließt. Die Argumente jedes Befehls müssen weiterhin die Grenze pro Payload einhalten | -| Memo-Größe | 256 KiB | `server.limits.max_memo_bytes` | Serialisiertes Memo auf `POST /workflows` und `POST /schedules` | -| Anzahl der Suchattribute | 100 | `server.limits.max_search_attributes` | Registrierte eigene Suchattribute pro Namespace | -| Suchattribut-Schlüssellänge | 128 Bytes | `server.limits.max_search_attribute_key_length` | Länge eines einzelnen SA-Schlüssels beim Start | -| Suchattribut-Wertgröße | 2 KiB | `server.limits.max_search_attribute_value_bytes` | Jeder Zeichenfolgenwert und jedes Element eines Array-Werts beim Start | -| Signal-/Update-/Abfragename | 256 Bytes | `server.limits.max_operation_name_length` | URL-Pfadsegment für Signal-/Update-/Abfragenamen | -| Länge von `workflow_id` | 128 Zeichen | Controller-Validator | Workflow-ID auf `POST /workflows` | -| `workflow_type` / `task_queue` / `business_key` | 255 Zeichen | Controller-Validator | Zeichenfolgenfelder auf `POST /workflows` | -| `request_id` | 255 Zeichen | Controller-Validator | Deduplizierungstoken für Signale/Updates/Abbrechen/Beenden | -| `reason` | 1.000 Zeichen | Controller-Validator | Begründungstext für Abbrechen/Beenden/Archivieren | - -Jede Grenze ist einzeln über `DW_*`-Umgebungsvariablen konfigurierbar -(vollständiger Vertrag in `config/dw-contract.php`). Der Wert `0` deaktiviert -die Prüfung für diese einzelne Grenze; die anderen bleiben wirksam. - -Die aktuell konfigurierten Werte werden unter `limits` in der Antwort von -`GET /api/cluster/info` veröffentlicht. Clients können sie dadurch zur Laufzeit -ermitteln: +## Grenzen im Service Mode {#server-request-boundary-limits} -```json -{ - "limits": { - "max_payload_bytes": 2097152, - "max_memo_bytes": 262144, - "max_search_attributes": 100, - "max_search_attribute_key_length": 128, - "max_search_attribute_value_bytes": 2048, - "max_operation_name_length": 256, - "max_pending_activities": 2000, - "max_pending_children": 2000 - } -} -``` - -Validierungsfehler werden im Standard-Fehlerumschlag der Steuerungsebene mit -`reason: "validation_failed"` und einer Zuordnung `validation_errors` -zurückgegeben. Deren Schlüssel sind die betroffenen Felder (`signal_name`, -`update_name`, `query_name`, `search_attributes`, `memo` usw.). Ablehnungen wegen -der Payload-Größe verwenden `reason: "payload_too_large"` und Statuscode `413`. +Die HTTP-Anfragegrenzen von Server und Cloud gelten getrennt von diesen eingebetteten Laravel-Grenzen. Siehe die [Server-Anfragereferenz](../polyglot/server-config-reference.md#server-request-boundary-limits). ### Größe eines Workflow-Task-Abschlusses {#workflow-task-completion-size} -Auf nativem Server 3.6.0 und neuer darf eine Anfrage, die einen Workflow-Task mit Befehlen abschließt (`POST /api/worker/workflow-tasks/{id}/complete` und `POST /api/worker/activity-tasks/{id}/continuation/complete`), bis zum 16-Fachen von `max_payload_bytes` groß sein: 32 MiB beim Standardwert von 2 MiB. Sie folgt `DW_MAX_PAYLOAD_BYTES` und hat keine eigene Einstellung. Die Argumente jedes Befehls müssen innerhalb des Abschlusses weiterhin die Grenze pro Payload einhalten. PHP-Server 2.x und frühere native Versionen begrenzen einen Abschluss wie jede andere Anfrage auf eine Payload-Grenze. - -Ein größerer Abschluss wird mit `413 payload_too_large` und `limit_kind: workflow_task_completion_bytes` abgelehnt, bevor etwas aufgezeichnet wird. Eine erneute Ausführung des Tasks erzeugt dieselben Befehle, daher führt erneutes Senden zur selben Ablehnung. PHP SDK 3.17.0 und neuer senden ihn nie erneut: Der Worker lässt den Lauf einmal mit einem `fail_workflow`-Befehl fehlschlagen, dessen Nachricht mit `Structural limit exceeded: workflow_task_completion_bytes:` beginnt und beide Größen nennt, und der Server zeichnet den Fehler mit `failure_category = structural_limit` auf. Die Python- und Rust-SDKs tun dasselbe in ihren nächsten Versionen. - -So bleibt ein Abschluss innerhalb der Grenze: - -- Teilen Sie ein großes Fan-out in kleinere Stapel über mehrere Workflow-Tasks auf. -- Verlagern Sie Arbeit in Child-Workflows, oder verwenden Sie Continue-as-New. -- Speichern Sie große Argumente im externen Payload-Speicher, sodass der Abschluss Referenzen statt der Payloads enthält. +Completion-Grenzen und die Behandlung von SDK-Ablehnungen im Service Mode stehen in der [Server-Referenz](../polyglot/server-config-reference.md#workflow-task-completion-size). diff --git a/i18n/de/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md b/i18n/de/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md index 08797ec2d81..4fc8d6536a7 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md @@ -235,6 +235,7 @@ der Laufzeitumgebung statt in der Profildatei bleiben. | `dw workflow:signal ` | Signal senden. | `--run-id`, Eingabeoptionen, `--json` | | `dw workflow:query ` | Schreibgeschützte Workflow-Abfrage ausführen. | `--run-id`, Eingabeoptionen, `--json` | | `dw workflow:update ` | Workflow-Update übermitteln oder ausführen. | `--wait=accepted\|completed`, `--run-id`, Eingabeoptionen, `--json` | +| `dw workflow:update-outcome ` | Ein gespeichertes Update-Ergebnis lesen, ohne das Update erneut einzureichen. | `--wait=accepted\|completed`, `--wait-timeout`, `--json` | | `dw workflow:cancel [workflow-id]` | Einen Workflow oder ausgewählten Batch als abgebrochen schließen; keine Bereinigung durch Workflow-Code. | `--reason`, `--run-id`, `--all-matching`, `--type`, `--status`, `--limit`, `--yes`, `--json` | | `dw workflow:terminate ` | Workflow zwangsweise terminieren. | `--reason`, `--run-id`, `--json` | | `dw workflow:repair ` | Server um Reparatur eines festhängenden oder wiederholbaren Laufs bitten. | `--json` | @@ -259,6 +260,29 @@ dw workflow:cancel --all-matching='WorkflowType = "ImportJob"' --limit=25 --yes prüfen kanonische Anfragefelder gegen den vom Server veröffentlichten Anfragevertrag. Nichtkanonische alte Aliase werden vor dem Senden abgelehnt. +### Ein Update-Ergebnis lesen {#read-update-outcome} + +CLI ab 2.8 kann ein angenommenes Update über seine `update_id` lesen, wenn der +Server `capabilities.update_outcome_reads` meldet (native ab 3.6.0). Verwenden +Sie die ID aus der Annahmebestätigung: + +```bash +dw workflow:update-outcome order-123 "$UPDATE_ID" +dw workflow:update-outcome order-123 "$UPDATE_ID" --wait=completed --wait-timeout=30 +``` + +Der Standard `--wait=accepted` antwortet sofort. Ein angenommenes, noch nicht +abgeschlossenes Update bleibt ausstehend, auch wenn eine Wartefrist abläuft. +Ein abgeschlossenes Update kann ein null-Ergebnis haben. `--json` liefert die +geprüfte Bestätigung. Unterscheiden Sie die Fälle über `update_status`. Jeder +Aufruf liest das Ergebnis einmal und reicht das Update niemals erneut ein. + +`--wait-timeout` erfordert `--wait=completed` und eine ganze Zahl von mindestens +einer Sekunde. Ein fehlgeschlagenes Update endet mit Exitcode 2. Eine unbekannte +oder entfernte Update-ID endet mit 5. Das beweist nicht, dass das Update nie +angenommen wurde. Ohne die Fähigkeit, auch bei PHP Server 2.x, endet der Befehl +mit 8, bevor eine Ergebnisanfrage gesendet wird. + ## Dienstaufrufe untersuchen {#service-call-inspection} Mit `dw service-call:describe ` diff --git a/i18n/de/docusaurus-plugin-content-docs/current/polyglot/cli.mdx b/i18n/de/docusaurus-plugin-content-docs/current/polyglot/cli.mdx index db9cb9698ab..b99a4836c95 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/polyglot/cli.mdx +++ b/i18n/de/docusaurus-plugin-content-docs/current/polyglot/cli.mdx @@ -291,6 +291,11 @@ für Inline-Werte, `--input-file` für einen Dateipfad oder `-` für stdin und `--input-encoding=json|raw|base64`. JSON ist Standard. Raw- und Base64-Eingaben werden als ein Positionsargument des Workflows übergeben. +Mit `dw workflow:update-outcome` lesen Sie ein angenommenes Update später, +ohne es erneut einzureichen. Ausstehend und abgeschlossen mit null-Ergebnis +sind unterschiedliche Zustände. Unter [Update-Ergebnis lesen](./cli-reference.md#read-update-outcome) +stehen die erforderliche Server-Fähigkeit und die Warteoptionen. + ### Brückenadapter {#bridge-adapters} ```bash diff --git a/i18n/de/docusaurus-plugin-content-docs/current/polyglot/python.md b/i18n/de/docusaurus-plugin-content-docs/current/polyglot/python.md index 4085c901c3d..f60f5dc73b6 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/polyglot/python.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/polyglot/python.md @@ -120,6 +120,17 @@ Python-SDK 2.15 und 2.16 ergänzen: Die vollständige Liste steht im [Changelog zu 2.16.0](https://github.com/durable-workflow/sdk-python/blob/2.16.0/CHANGELOG.md). +Python SDK 2.17 ergänzt `Client.update_outcome` und +`Client.update_outcome_receipt`, um ein angenommenes Update später zu lesen, +ohne es erneut einzureichen. Diese Methoden erfordern +`capabilities.update_outcome_reads` (native Server ab 3.6.0). +`update_outcome` wartet standardmäßig auf den Abschluss und wirft +`UpdateStillPending`, wenn das Update noch nicht fertig ist. Ein zurückgegebenes +`None` ist ein abgeschlossenes null-Ergebnis. `update_outcome_receipt` verwendet +standardmäßig die Annahmephase und erhält den expliziten `update_status`. +Sprachspezifische Beispiele stehen in der +[Python-SDK-Anleitung](https://python.durable-workflow.com/reference/client/#read-an-update-outcome). + ## Schnellstart {#quickstart} Dieses vollständige Python-Programm definiert einen Workflow mit einer Aktivität, startet ihn gegen einen lokalen Durable Workflow Server und wartet auf das Ergebnis: @@ -403,13 +414,21 @@ Die entsprechenden CLI-Befehle sind `dw task-queue:build-ids`, | `await client.export_history(workflow_id, run_id)` | decodierte Archivhistoriennutzlast | `WorkflowNotFound`, Authentifizierungs-/Serverfehler | | `await client.signal_workflow(workflow_id, signal_name, args=None)` | `None` | `WorkflowNotFound`, `InvalidArgument`, Authentifizierungs-/Serverfehler | | `await client.query_workflow(workflow_id, query_name, args=None)` | decodiertes Abfrageergebnis | `QueryFailed`, `WorkflowNotFound`, Authentifizierungs-/Serverfehler | -| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | decodiertes Update-Ergebnis | `UpdateRejected`, `WorkflowNotFound`, Authentifizierungs-/Serverfehler | +| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | Update-Bestätigung (`dict`) | `UpdateRejected`, `UpdateValidationFailed`, `UpdateFailed`, `WorkflowNotFound`, Authentifizierungs-/Serverfehler | | `await client.cancel_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, Authentifizierungs-/Serverfehler | | `await client.terminate_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, Authentifizierungs-/Serverfehler | | `await client.repair_workflow(workflow_id)` | `WorkflowCommandResult` | `WorkflowNotFound`, Authentifizierungs-/Serverfehler | | `await client.archive_workflow(workflow_id, reason=None)` | `WorkflowCommandResult` | `WorkflowNotFound`, Authentifizierungs-/Serverfehler | | `await client.get_result(handle, poll_interval=0.5, timeout=30.0)` | decodierte Workflow-Ausgabe | `WorkflowFailed`, `WorkflowCancelled`, `WorkflowTerminated`, `TimeoutError` | +`update_workflow` verwendet standardmäßig `wait_for="accepted"`. Die +Bestätigung kann `update_status="accepted"` und `result=None` enthalten. Bei +`wait_for="completed"` begrenzt `wait_timeout_seconds` die Wartezeit. Nach deren +Ablauf bleibt die Bestätigung angenommen und setzt `wait_timed_out=True`. +Nur `update_status="completed"` kennzeichnet ein abgeschlossenes Ergebnis, +einschließlich `None`. Bewahren Sie `update_id` für +[spätere Ergebnisabfragen](https://python.durable-workflow.com/reference/client/#read-an-update-outcome) auf. + `start_workflow` akzeptiert `workflow_type`, `task_queue`, optional `workflow_id`, optional `input`, `duplicate_policy`, `memo`, `search_attributes`, `business_key`, `execution_timeout_seconds` und `run_timeout_seconds`. Alle Aufrufernutzlasten 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 eb171483f62..60d79901306 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/polyglot/rust.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/polyglot/rust.md @@ -131,6 +131,21 @@ unabhängig geführt. Ihre Laufzeit-Protokollmanifeste bestimmen die Kompatibili Siehe den [Changelog zu 4.13.0](https://github.com/durable-workflow/sdk-rust/blob/4.13.0/CHANGELOG.md). +## Gespeicherte Update-Ergebnisse lesen {#read-update-outcome} + +Rust SDK 4.15 ergänzt `Client::update_outcome` und +`Client::update_outcome_receipt`, um ein angenommenes Update über seine ID zu +lesen, ohne es erneut einzureichen. Diese Methoden erfordern +`capabilities.update_outcome_reads` (native Server ab 3.6.0). `update_outcome` +liefert für ein noch nicht abgeschlossenes Update `Error::UpdateStillPending`. +Ein abgeschlossenes null-Ergebnis ist `Ok(Value::Null)`. Ergebnisbestätigungen +erhalten den expliziten `update_status`. Die Rust-Schnittstelle steht in der +[Client-API](https://rust.durable-workflow.com/durable_workflow/struct.Client.html#method.update_outcome). + +Rust SDK 4.15.0 wendet die gewöhnliche Payload-Grenze weiterhin auf den ganzen +Befehlsbatch an. Beachten Sie die [bekannte Planergrenze](./server-config-reference.md#rust-completion-planning), +bevor Sie einen großen Fan-out ohne externen Payload-Speicher ausführen. + ## Fristen für Bedingungswarteoperationen und Worker-Upgrades {#condition-wait-deadlines} Rust SDK 4.11.2 misst das Timeout eines nicht gruppierten `wait_condition` diff --git a/i18n/de/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md b/i18n/de/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md index 8990967a1bc..e73740a8acf 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md @@ -262,6 +262,93 @@ Diese Einstellungen begrenzen Anfragen und Zustandswachstum. Wenn eine Anwendung | `DW_MAX_NEXUS_OPERATIONS_PER_CALLER` | `200` | Höchstzahl von Nexus-Vorgängen je Aufrufer in der Vorgangshistorie vor erforderlicher Paginierung. | `WORKFLOW_MAX_NEXUS_OPERATIONS_PER_CALLER` | | `DW_COMPRESSION_ENABLED` | `true` | Aktiviert die Komprimierung von JSON-Antworten oberhalb der Mindestgröße. | `WORKFLOW_SERVER_COMPRESSION_ENABLED` | +## Grenzen an der Server-Anfragegrenze {#server-request-boundary-limits} + +Beim eigenständigen Server werden separate Grenzen an der +HTTP-Anfragegrenze durchgesetzt, bevor Workflow-Aufgabe, Signal, Update oder +Abfrage die Steuerungsebene erreichen. Diese Grenzen liefern sofort +`422 validation_failed` (oder `413 payload_too_large` bei Prüfung des gesamten +Anfragetexts). Clients erfahren so den Ablehnungsgrund, ohne dass der Server +eine Datenbankzeile schreibt. + +| Grenze | Standard | Konfigurationsschlüssel | Was sie begrenzt | +|---|---|---|---| +| Anfragetextgröße | 2 MiB | `server.limits.max_payload_bytes` | Gesamtzahl der Bytes im HTTP-Anfragetext, außer bei einem Workflow-Task-Abschluss auf nativem Server 3.6.0 oder neuer (nächste Zeile) | +| Größe eines Workflow-Task-Abschlusses | 32 MiB (16 × Anfragetextgröße) | abgeleitet von `server.limits.max_payload_bytes` | Nativer Server 3.6.0 oder neuer: eine Anfrage, die einen Workflow-Task mit Befehlen abschließt. Die Argumente jedes Befehls müssen weiterhin die Grenze pro Payload einhalten | +| Memo-Größe | 256 KiB | `server.limits.max_memo_bytes` | Serialisiertes Memo auf `POST /workflows` und `POST /schedules` | +| Anzahl der Suchattribute | 100 | `server.limits.max_search_attributes` | Registrierte eigene Suchattribute pro Namespace | +| Suchattribut-Schlüssellänge | 128 Bytes | `server.limits.max_search_attribute_key_length` | Länge eines einzelnen SA-Schlüssels beim Start | +| Suchattribut-Wertgröße | 2 KiB | `server.limits.max_search_attribute_value_bytes` | Jeder Zeichenfolgenwert und jedes Element eines Array-Werts beim Start | +| Signal-/Update-/Abfragename | 256 Bytes | `server.limits.max_operation_name_length` | URL-Pfadsegment für Signal-/Update-/Abfragenamen | +| Länge von `workflow_id` | 128 Zeichen | Controller-Validator | Workflow-ID auf `POST /workflows` | +| `workflow_type` / `task_queue` / `business_key` | 255 Zeichen | Controller-Validator | Zeichenfolgenfelder auf `POST /workflows` | +| `request_id` | 255 Zeichen | Controller-Validator | Deduplizierungstoken für Signale/Updates/Abbrechen/Beenden | +| `reason` | 1.000 Zeichen | Controller-Validator | Begründungstext für Abbrechen/Beenden/Archivieren | + +Verwenden Sie die dokumentierten `DW_*`-Einstellungen für konfigurierbare +Grenzen von PHP Server 2.x. Grenzen der Controller-Validierung sind fest. +Native Server 3.x unterstützt die in seinen [Implementierungshinweisen](#native-server-3x) +genannten Einstellungen. Bei native 3.8.0 setzt `DW_MAX_PAYLOAD_BYTES=0` die +Grenze für gewöhnliche Anfragen und Workflow-Task-Completions auf null Bytes, +sodass nichtleere Bodys abgelehnt werden. Die Grenze für Operationsnamen ist +fest auf 256 Bytes gesetzt. + +Die aktuell konfigurierten Werte werden unter `limits` in der Antwort von +`GET /api/cluster/info` veröffentlicht. Clients können sie dadurch zur Laufzeit +ermitteln: + +```json +{ + "limits": { + "max_payload_bytes": 2097152, + "max_memo_bytes": 262144, + "max_search_attributes": 100, + "max_search_attribute_key_length": 128, + "max_search_attribute_value_bytes": 2048, + "max_operation_name_length": 256, + "max_pending_activities": 2000, + "max_pending_children": 2000 + } +} +``` + +Validierungsfehler werden im Standard-Fehlerumschlag der Steuerungsebene mit +`reason: "validation_failed"` und einer Zuordnung `validation_errors` +zurückgegeben. Deren Schlüssel sind die betroffenen Felder (`signal_name`, +`update_name`, `query_name`, `search_attributes`, `memo` usw.). Ablehnungen wegen +der Payload-Größe verwenden `reason: "payload_too_large"` und Statuscode `413`. + +### Größe eines Workflow-Task-Abschlusses {#workflow-task-completion-size} + +Auf nativem Server 3.6.0 und neuer darf eine Anfrage, die einen Workflow-Task mit Befehlen abschließt (`POST /api/worker/workflow-tasks/{id}/complete` und `POST /api/worker/activity-tasks/{id}/continuation/complete`), bis zum 16-Fachen von `max_payload_bytes` groß sein: 32 MiB beim Standardwert von 2 MiB. Sie folgt `DW_MAX_PAYLOAD_BYTES` und hat keine eigene Einstellung. Die Argumente jedes Befehls müssen innerhalb des Abschlusses weiterhin die Grenze pro Payload einhalten. PHP-Server 2.x und frühere native Versionen begrenzen einen Abschluss wie jede andere Anfrage auf eine Payload-Grenze. + +Ein größerer Abschluss wird mit `413 payload_too_large` und `limit_kind: workflow_task_completion_bytes` abgelehnt, bevor etwas aufgezeichnet wird. Eine erneute Ausführung des Tasks erzeugt dieselben Befehle, daher führt erneutes Senden zur selben Ablehnung. Erhält PHP SDK 3.17.0 oder neuer diese typisierte Ablehnung, sendet es die Completion nicht erneut: Der Worker lässt den Lauf einmal mit einem `fail_workflow`-Befehl fehlschlagen, dessen Nachricht mit `Structural limit exceeded: workflow_task_completion_bytes:` beginnt und beide Größen nennt, und der Server zeichnet den Fehler mit `failure_category = structural_limit` auf. + +Python SDK 2.17 und Rust SDK 4.15 behandeln die typisierte Ablehnung. Bei +Server 3.8.0 kann eine zu große Completion bereits beim Transport scheitern, +bevor der Worker HTTP 413 erhält. Im Test mit dem veröffentlichten Python-SDK +ließ `httpx.ReadError` den Workflow ausstehend, statt ihn strukturell scheitern +zu lassen. Die Qualifikation übergroßer Anfragen am veröffentlichten Server ist +unter der [Korrektur der Server-Antwort](https://github.com/durable-workflow/.github/issues/228#issuecomment-6848969678) +weiter offen. Verkleinern Sie die Completions, bis dieser Pfad qualifiziert ist. + +So bleibt ein Abschluss innerhalb der Grenze: + +- Teilen Sie ein großes Fan-out in kleinere Stapel über mehrere Workflow-Tasks auf. +- Verlagern Sie Arbeit in Child-Workflows, oder verwenden Sie Continue-as-New. +- Speichern Sie große Argumente im externen Payload-Speicher, sodass der Abschluss Referenzen statt der Payloads enthält. + +#### Rust-Befehlsplanung {#rust-completion-planning} + +Rust SDK 4.15.0 verwendet die gewöhnliche Grenze je Payload weiterhin als +Gesamtgrenze für die Befehlsplanung (standardmäßig 2 MiB), bevor die höhere +Completion-Grenze des Servers greift. Ohne externen Payload-Speicher im +Namespace wird der veröffentlichte Fan-out mit 300 × 10 KB mit +`external_payload_unavailable` abgelehnt. Der Worker beendet sich und der Lauf +bleibt ausstehend. Verwenden Sie kleinere Befehlsbatches, solange die +[Korrektur des SDK-Gesamtplaners](https://github.com/durable-workflow/sdk-rust/issues/254) +aussteht. Dieser SDK-Pfad unterstützt die höhere Server-Grenze noch nicht. + ## Docker-Initialisierung und Herkunft {#docker-bootstrap-and-provenance} | Variable | Standardwert | Zweck | Alter Alias | diff --git a/i18n/de/source-hashes.json b/i18n/de/source-hashes.json index 4ec35cae6fb..ca19adf3f36 100644 --- a/i18n/de/source-hashes.json +++ b/i18n/de/source-hashes.json @@ -17,7 +17,7 @@ "constraints/execution-guarantees.md": "c24aaff70bfcf50366459ec698ced67adff1e02c1b0ca23c8178a13873037f5a", "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", - "constraints/structural-limits.md": "ad498fae9ec7722aaca2990635027a4f52b4ac6dbd4b145c1aba1a03c6000b1b", + "constraints/structural-limits.md": "b9c2d515fce3b56a03ac654dab65edbe67e13903386412dba8aa1ea77a1d9657", "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", @@ -70,8 +70,8 @@ "polyglot/avro-value-protocol.md": "602e66c6288c1dd69d2b400c64e4739ad3a0493b5be269cee40f7848b11f260a", "polyglot/cancellation.md": "f676cd3ddb39246a0f580a1e16c83bc36d2ed9458b9e6009af4cc192d299ac62", "polyglot/cli-python-parity.md": "acf1acbf15ca9cdf069154699c5fbf8c1d1fd3241a32d201ac10b8ec76c038be", - "polyglot/cli-reference.md": "dc3802b01887f01e702b7989b54c06ba98e8e19326c17db7b32af4e5230e76ee", - "polyglot/cli.mdx": "5b4fdd5c283b3f45691324433d96e6c84e2e898d58fbb7536992ca1dc4503d54", + "polyglot/cli-reference.md": "665c65192f9bfd41610f2aca54a66c2a3aa125e2d2b637d744d9c5f4243bee24", + "polyglot/cli.mdx": "9dac7bb6b711737c9f16916ef462d85c642539f4b6e4a1bdac59320a09632c1f", "polyglot/cloud-control-plane.md": "bb375e598dd1afa3207171047fb81b0cb82c382ce535ab415cb09dc10f6d748e", "polyglot/database-support.md": "518f679ae723ae4d39db7cac78008bc8edb84a6cfba2e6c668d8f2be5d378d03", "polyglot/deployment-modes.md": "7b508db4be86c92de76cfd8dfd946d93941c8a6f0a601a161d4d3fd1711bf97f", @@ -84,12 +84,12 @@ "polyglot/polling-patterns.md": "30875099a23731c6c471b481a771378acc6ff57eed2fda4405a509057534c989", "polyglot/portable-worker-affinity.md": "40973c6a31a76845b4f95e9a505e68ad76abd5174bbdccf37993cdebc8904959", "polyglot/prerelease-history-migration.md": "a57f05f492228a8a67791f9152648a1e5f80856325b78777cf63b6ef49b7413c", - "polyglot/python.md": "1229182acdbe6ddf7f4d875a28c7db67c83931e4055b137b8ce35d4775e3a7b1", + "polyglot/python.md": "7e31563bf15d1f7f1bd1647b70644ef5e72b2c912c566e72e9b1cc4a7fe19d89", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "e9ebec32026199c861409f6fbba0a45f2e360638a68ac75387ad09fd09c6a420", + "polyglot/rust.md": "e768d43c38be76b22440910aa97d61897b392321f106dd2fe7461399a13a99c9", "polyglot/server-api-reference.md": "8bac825f11f7aa3f2a335cf3d1dcdc951219f11d6702e9fe3502d3803fd1e2a5", - "polyglot/server-config-reference.md": "02da3d03e49af3171de9268033c01273cb28fc7eaac665fcaa8aff1252be9055", + "polyglot/server-config-reference.md": "636e4aa05bcc56569a3d001bc80ad2853f95372b051aebcf2bdd0061d2e50b6b", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "2c03845c0979f62bc7ab3208cf09820844b224e548f10fb7d1656852e3428445", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", diff --git a/i18n/es/docusaurus-plugin-content-docs/current/constraints/structural-limits.md b/i18n/es/docusaurus-plugin-content-docs/current/constraints/structural-limits.md index e267415c2b0..b0c279c9d66 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/constraints/structural-limits.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/constraints/structural-limits.md @@ -261,53 +261,10 @@ El contrato completo está disponible en la sección `structural_limits` de la r Waterline muestra los fallos por límites estructurales en la tabla de excepciones con la categoría de fallo `structural_limit`. Los detalles del fallo en la línea de tiempo incluyen el tipo de límite, el valor actual y el máximo configurado. -## Límites de Server en la recepción de solicitudes {#server-request-boundary-limits} +## Límites del modo de servicio {#server-request-boundary-limits} -Al utilizar el servidor independiente, se aplica otro conjunto de máximos en el límite de entrada de solicitudes HTTP, antes de que una tarea de workflow, señal, actualización o consulta llegue al plano de control. Estos límites rechazan de inmediato con una respuesta `422 validation_failed` (o `413 payload_too_large` para comprobaciones de todo el cuerpo), de modo que los clientes conocen el motivo sin que el servidor escriba ninguna fila en la base de datos. - -| Límite | Valor predeterminado | Clave de configuración | Qué limita | -|---|---|---|---| -| Tamaño del cuerpo | 2 MiB | `server.limits.max_payload_bytes` | Total de bytes del cuerpo de la solicitud HTTP, salvo una finalización de tarea de workflow en el Server nativo 3.6.0 o posterior (fila siguiente) | -| Tamaño de finalización de tarea de workflow | 32 MiB (16 × tamaño del cuerpo) | derivado de `server.limits.max_payload_bytes` | Server nativo 3.6.0 o posterior: una solicitud que finaliza una tarea de workflow con comandos. Los argumentos de cada comando siguen respetando el límite por carga útil | -| Tamaño de memo | 256 KiB | `server.limits.max_memo_bytes` | Memo serializado en `POST /workflows` y `POST /schedules` | -| Número de atributos de búsqueda | 100 | `server.limits.max_search_attributes` | Atributos de búsqueda personalizados registrados por namespace | -| Longitud de clave de atributo de búsqueda | 128 bytes | `server.limits.max_search_attribute_key_length` | Longitud de una clave de atributo de búsqueda al iniciar | -| Tamaño de valor de atributo de búsqueda | 2 KiB | `server.limits.max_search_attribute_value_bytes` | Cada valor de cadena (y cada elemento de un valor de matriz) al iniciar | -| Nombre de señal, actualización o consulta | 256 bytes | `server.limits.max_operation_name_length` | Segmento de ruta URL para los nombres de señales, actualizaciones y consultas | -| Longitud de `workflow_id` | 128 caracteres | Validador del controlador | ID del workflow en `POST /workflows` | -| `workflow_type` / `task_queue` / `business_key` | 255 caracteres | Validador del controlador | Campos de cadena en `POST /workflows` | -| `request_id` | 255 caracteres | Validador del controlador | Token de deduplicación en señales, actualizaciones, cancelación y terminación | -| `reason` | 1,000 caracteres | Validador del controlador | Texto del motivo en cancelación, terminación y archivado | - -Cada límite se puede configurar por separado mediante variables de entorno `DW_*` (consulta el contrato completo en `config/dw-contract.php`). Establecer un valor de `0` desactiva la comprobación de ese límite concreto, pero mantiene las demás. - -Los valores configurados actualmente se publican bajo `limits` en la respuesta de `GET /api/cluster/info`, de modo que los clientes pueden descubrirlos durante la ejecución: - -```json -{ - "limits": { - "max_payload_bytes": 2097152, - "max_memo_bytes": 262144, - "max_search_attributes": 100, - "max_search_attribute_key_length": 128, - "max_search_attribute_value_bytes": 2048, - "max_operation_name_length": 256, - "max_pending_activities": 2000, - "max_pending_children": 2000 - } -} -``` - -Los errores de validación se devuelven en el sobre de error estándar del plano de control con `reason: "validation_failed"` y un mapa `validation_errors` cuyas claves corresponden al campo que causa el error (`signal_name`, `update_name`, `query_name`, `search_attributes`, `memo`, etc.). Los rechazos por tamaño de carga útil utilizan `reason: "payload_too_large"` y el código de estado `413`. +Los límites HTTP de Server y Cloud son distintos de estos controles de Laravel embebido. Consulte la [referencia de solicitudes del Server](../polyglot/server-config-reference.md#server-request-boundary-limits). ### Tamaño de finalización de tarea de workflow {#workflow-task-completion-size} -En el Server nativo 3.6.0 y posteriores, una solicitud que finaliza una tarea de workflow con comandos (`POST /api/worker/workflow-tasks/{id}/complete` y `POST /api/worker/activity-tasks/{id}/continuation/complete`) puede ocupar hasta 16 veces `max_payload_bytes`: 32 MiB con el valor predeterminado de 2 MiB. Sigue a `DW_MAX_PAYLOAD_BYTES` y no tiene un ajuste propio. Los argumentos de cada comando siguen respetando el límite por carga útil dentro de la finalización. El Server PHP 2.x y las versiones nativas anteriores limitan una finalización a un límite de carga útil, como cualquier otra solicitud. - -Una finalización mayor se rechaza con `413 payload_too_large` y `limit_kind: workflow_task_completion_bytes` antes de registrar nada. Reproducir la tarea genera los mismos comandos, así que reenviar la finalización recibe el mismo rechazo. PHP SDK 3.17.0 y posteriores nunca la reenvían: el worker hace fallar la ejecución una sola vez con un comando `fail_workflow` cuyo mensaje empieza por `Structural limit exceeded: workflow_task_completion_bytes:` e indica ambos tamaños, y el Server registra el fallo con `failure_category = structural_limit`. Los SDK de Python y Rust harán lo mismo en sus próximas versiones. - -Para mantener una finalización dentro del límite: - -- Divida un fan-out grande en lotes más pequeños repartidos entre tareas de workflow. -- Mueva trabajo a workflows hijos, o use continue-as-new. -- Guarde los argumentos grandes en el almacenamiento externo de cargas útiles, para que la finalización lleve referencias en lugar de las cargas útiles. +Los límites de finalización y el manejo de rechazos de los SDK en modo de servicio se describen en la [referencia del Server](../polyglot/server-config-reference.md#workflow-task-completion-size). diff --git a/i18n/es/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md b/i18n/es/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md index a1ca2c9461b..c3141a02a3b 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md @@ -152,6 +152,7 @@ Prefiere `--token-env=NAME` en producción para mantener secretos en el entorno | `dw workflow:signal ` | Enviar una señal. | `--run-id`, opciones de entrada, `--json` | | `dw workflow:query ` | Ejecutar una consulta de solo lectura. | `--run-id`, opciones de entrada, `--json` | | `dw workflow:update ` | Enviar o ejecutar una actualización. | `--wait=accepted\|completed`, `--run-id`, opciones de entrada, `--json` | +| `dw workflow:update-outcome ` | Leer el resultado guardado de una actualización sin volver a enviarla. | `--wait=accepted\|completed`, `--wait-timeout`, `--json` | | `dw workflow:cancel [workflow-id]` | Cerrar un workflow o lote seleccionado como cancelado; no ejecuta limpieza del código. | `--reason`, `--run-id`, `--all-matching`, `--type`, `--status`, `--limit`, `--yes`, `--json` | | `dw workflow:terminate ` | Terminar un workflow por la fuerza. | `--reason`, `--run-id`, `--json` | | `dw workflow:repair ` | Solicitar reparación de una ejecución atascada o reintentable. | `--json` | @@ -174,6 +175,30 @@ dw workflow:cancel --all-matching='WorkflowType = "ImportJob"' --limit=25 --yes `workflow:start`, `workflow:signal`, `workflow:query` y `workflow:update` validan campos canónicos contra el contrato publicado por el servidor. Los alias heredados no canónicos se rechazan antes de enviar la solicitud. +### Leer el resultado de una actualización {#read-update-outcome} + +CLI 2.8 y posteriores pueden leer una actualización aceptada mediante su +`update_id` cuando el Server anuncia `capabilities.update_outcome_reads` +(nativo 3.6.0 o posterior). Use el ID del recibo de aceptación: + +```bash +dw workflow:update-outcome order-123 "$UPDATE_ID" +dw workflow:update-outcome order-123 "$UPDATE_ID" --wait=completed --wait-timeout=30 +``` + +El valor predeterminado `--wait=accepted` responde de inmediato. Una +actualización aceptada que no ha terminado sigue pendiente, incluso si vence +la espera. Una actualización completada puede tener un resultado null. +`--json` devuelve el recibo validado. Use su `update_status` para distinguir +estos casos. Cada invocación realiza una lectura y nunca vuelve a enviar la +actualización. + +`--wait-timeout` requiere `--wait=completed` y un entero de al menos un segundo. +Una actualización fallida sale con código 2. Un ID desconocido o eliminado +sale con 5, lo que no demuestra que la actualización nunca fuera aceptada. +Un Server sin la capacidad, incluido PHP Server 2.x, produce el código 8 antes +de enviar una solicitud de resultado. + ## Inspección de llamadas a servicios {#service-call-inspection} Utiliza `dw service-call:describe ` para inspeccionar una llamada Nexus duradera en el espacio del endpoint. Por ejemplo, `dw service-call:describe billing invoices create call-42 --namespace=shared --json` devuelve la respuesta completa de Server. diff --git a/i18n/es/docusaurus-plugin-content-docs/current/polyglot/cli.mdx b/i18n/es/docusaurus-plugin-content-docs/current/polyglot/cli.mdx index 91ca108ffd5..732812d3c9f 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/polyglot/cli.mdx +++ b/i18n/es/docusaurus-plugin-content-docs/current/polyglot/cli.mdx @@ -229,6 +229,11 @@ dw workflow:history # Show run history Todos los comandos que aceptan cargas del usuario comparten la misma entrada: `--input` para valores en línea, `--input-file` para una ruta o `-` para stdin y `--input-encoding=json|raw|base64`. JSON es el valor predeterminado; las entradas raw y base64 se pasan como un argumento posicional de workflow. +Use `dw workflow:update-outcome` para leer más tarde una actualización aceptada +sin volver a enviarla. Pendiente y completada con resultado null son estados +distintos. Consulte [leer el resultado de una actualización](./cli-reference.md#read-update-outcome) +para conocer la capacidad requerida del Server y las opciones de espera. + ### Adaptadores puente {#bridge-adapters} ```bash diff --git a/i18n/es/docusaurus-plugin-content-docs/current/polyglot/python.md b/i18n/es/docusaurus-plugin-content-docs/current/polyglot/python.md index cdb055b81f8..ba28bc95aa0 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/polyglot/python.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/polyglot/python.md @@ -121,6 +121,16 @@ Python SDK 2.15 y 2.16 añaden: Consulte el [registro de cambios de 2.16.0](https://github.com/durable-workflow/sdk-python/blob/2.16.0/CHANGELOG.md) para ver la lista completa. +Python SDK 2.17 añade `Client.update_outcome` y +`Client.update_outcome_receipt` para leer más tarde una actualización aceptada +sin volver a enviarla. Requieren `capabilities.update_outcome_reads` (Server +nativo 3.6.0 o posterior). `update_outcome` espera la finalización de forma +predeterminada y lanza `UpdateStillPending` si sigue pendiente. Un `None` +devuelto es un resultado null completado. `update_outcome_receipt` usa la etapa +de aceptación de forma predeterminada y conserva el `update_status` explícito. +Consulte la [guía del SDK de Python](https://python.durable-workflow.com/reference/client/#read-an-update-outcome) +para ver ejemplos específicos del lenguaje. + ## Inicio rápido {#quickstart} Este programa completo define un workflow con una actividad, lo inicia contra @@ -403,13 +413,20 @@ Los equivalentes CLI son `dw task-queue:build-ids`, `dw task-queue:drain` y | `await client.export_history(workflow_id, run_id)` | carga de historial para archivo decodificada | `WorkflowNotFound`, errores de autenticación/servidor | | `await client.signal_workflow(workflow_id, signal_name, args=None)` | `None` | `WorkflowNotFound`, `InvalidArgument`, errores de autenticación/servidor | | `await client.query_workflow(workflow_id, query_name, args=None)` | resultado de consulta decodificado | `QueryFailed`, `WorkflowNotFound`, errores de autenticación/servidor | -| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | resultado de actualización decodificado | `UpdateRejected`, `WorkflowNotFound`, errores de autenticación/servidor | +| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | recibo de actualización (`dict`) | `UpdateRejected`, `UpdateValidationFailed`, `UpdateFailed`, `WorkflowNotFound`, errores de autenticación/servidor | | `await client.cancel_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, errores de autenticación/servidor | | `await client.terminate_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, errores de autenticación/servidor | | `await client.repair_workflow(workflow_id)` | `WorkflowCommandResult` | `WorkflowNotFound`, errores de autenticación/servidor | | `await client.archive_workflow(workflow_id, reason=None)` | `WorkflowCommandResult` | `WorkflowNotFound`, errores de autenticación/servidor | | `await client.get_result(handle, poll_interval=0.5, timeout=30.0)` | salida de workflow decodificada | `WorkflowFailed`, `WorkflowCancelled`, `WorkflowTerminated`, `TimeoutError` | +`update_workflow` usa `wait_for="accepted"` de forma predeterminada. Su recibo +puede contener `update_status="accepted"` y `result=None`. Con +`wait_for="completed"`, `wait_timeout_seconds` limita la espera. Al vencer, +el recibo sigue aceptado y establece `wait_timed_out=True`. Solo +`update_status="completed"` identifica un resultado terminado, incluido `None`. +Conserve `update_id` para [leer el resultado más tarde](https://python.durable-workflow.com/reference/client/#read-an-update-outcome). + `start_workflow` acepta `workflow_type`, `task_queue`, `workflow_id` e `input` opcionales, `duplicate_policy`, `memo`, `search_attributes`, `business_key`, `execution_timeout_seconds` y `run_timeout_seconds`. Todas las cargas se envuelven 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 a25302d52aa..b7204bb57c4 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/polyglot/rust.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/polyglot/rust.md @@ -79,6 +79,21 @@ La negociación rechaza las incompatibilidades. Se rechaza una cabecera ausente Consulte el [registro de cambios de 4.13.0](https://github.com/durable-workflow/sdk-rust/blob/4.13.0/CHANGELOG.md). +## Leer resultados de actualizaciones guardados {#read-update-outcome} + +Rust SDK 4.15 añade `Client::update_outcome` y +`Client::update_outcome_receipt` para leer una actualización aceptada por ID +sin volver a enviarla. Requieren `capabilities.update_outcome_reads` (Server +nativo 3.6.0 o posterior). `update_outcome` devuelve `Error::UpdateStillPending` +si la actualización no ha terminado. Un resultado null completado es +`Ok(Value::Null)`. Los recibos conservan el `update_status` explícito. Consulte +la [API de Client](https://rust.durable-workflow.com/durable_workflow/struct.Client.html#method.update_outcome) +para conocer la interfaz de Rust. + +Rust SDK 4.15.0 aún aplica el límite habitual de carga a todo el lote de +comandos. Consulte el [límite conocido del planificador](./server-config-reference.md#rust-completion-planning) +antes de ejecutar un fan-out grande sin almacenamiento externo de cargas. + ## Plazos de espera de condiciones y actualización de workers {#condition-wait-deadlines} El SDK Rust 4.11.2 mide el timeout de un `wait_condition` fuera de un grupo diff --git a/i18n/es/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md b/i18n/es/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md index 309b1df4643..8aa7a9a30be 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md @@ -262,6 +262,81 @@ Estas opciones controlan los límites de las solicitudes y el crecimiento acotad | `DW_MAX_NEXUS_OPERATIONS_PER_CALLER` | `200` | Máximo de operaciones Nexus devueltas por llamador en el historial antes de exigir paginación. | `WORKFLOW_MAX_NEXUS_OPERATIONS_PER_CALLER` | | `DW_COMPRESSION_ENABLED` | `true` | Activa la compresión de respuestas JSON que superan el tamaño mínimo. | `WORKFLOW_SERVER_COMPRESSION_ENABLED` | +## Límites de Server en la recepción de solicitudes {#server-request-boundary-limits} + +Al utilizar el servidor independiente, se aplica otro conjunto de máximos en el límite de entrada de solicitudes HTTP, antes de que una tarea de workflow, señal, actualización o consulta llegue al plano de control. Estos límites rechazan de inmediato con una respuesta `422 validation_failed` (o `413 payload_too_large` para comprobaciones de todo el cuerpo), de modo que los clientes conocen el motivo sin que el servidor escriba ninguna fila en la base de datos. + +| Límite | Valor predeterminado | Clave de configuración | Qué limita | +|---|---|---|---| +| Tamaño del cuerpo | 2 MiB | `server.limits.max_payload_bytes` | Total de bytes del cuerpo de la solicitud HTTP, salvo una finalización de tarea de workflow en el Server nativo 3.6.0 o posterior (fila siguiente) | +| Tamaño de finalización de tarea de workflow | 32 MiB (16 × tamaño del cuerpo) | derivado de `server.limits.max_payload_bytes` | Server nativo 3.6.0 o posterior: una solicitud que finaliza una tarea de workflow con comandos. Los argumentos de cada comando siguen respetando el límite por carga útil | +| Tamaño de memo | 256 KiB | `server.limits.max_memo_bytes` | Memo serializado en `POST /workflows` y `POST /schedules` | +| Número de atributos de búsqueda | 100 | `server.limits.max_search_attributes` | Atributos de búsqueda personalizados registrados por namespace | +| Longitud de clave de atributo de búsqueda | 128 bytes | `server.limits.max_search_attribute_key_length` | Longitud de una clave de atributo de búsqueda al iniciar | +| Tamaño de valor de atributo de búsqueda | 2 KiB | `server.limits.max_search_attribute_value_bytes` | Cada valor de cadena (y cada elemento de un valor de matriz) al iniciar | +| Nombre de señal, actualización o consulta | 256 bytes | `server.limits.max_operation_name_length` | Segmento de ruta URL para los nombres de señales, actualizaciones y consultas | +| Longitud de `workflow_id` | 128 caracteres | Validador del controlador | ID del workflow en `POST /workflows` | +| `workflow_type` / `task_queue` / `business_key` | 255 caracteres | Validador del controlador | Campos de cadena en `POST /workflows` | +| `request_id` | 255 caracteres | Validador del controlador | Token de deduplicación en señales, actualizaciones, cancelación y terminación | +| `reason` | 1,000 caracteres | Validador del controlador | Texto del motivo en cancelación, terminación y archivado | + +Use las opciones `DW_*` documentadas para los límites configurables de PHP +Server 2.x. Los límites de validación del controlador son fijos. Native Server +3.x admite las opciones de sus [notas de implementación](#native-server-3x). +En native 3.8.0, `DW_MAX_PAYLOAD_BYTES=0` establece un techo de cero bytes para +solicitudes normales y finalizaciones de tareas de workflow, rechazando +cuerpos no vacíos. El límite de nombres de operación es fijo: 256 bytes. + +Los valores configurados actualmente se publican bajo `limits` en la respuesta de `GET /api/cluster/info`, de modo que los clientes pueden descubrirlos durante la ejecución: + +```json +{ + "limits": { + "max_payload_bytes": 2097152, + "max_memo_bytes": 262144, + "max_search_attributes": 100, + "max_search_attribute_key_length": 128, + "max_search_attribute_value_bytes": 2048, + "max_operation_name_length": 256, + "max_pending_activities": 2000, + "max_pending_children": 2000 + } +} +``` + +Los errores de validación se devuelven en el sobre de error estándar del plano de control con `reason: "validation_failed"` y un mapa `validation_errors` cuyas claves corresponden al campo que causa el error (`signal_name`, `update_name`, `query_name`, `search_attributes`, `memo`, etc.). Los rechazos por tamaño de carga útil utilizan `reason: "payload_too_large"` y el código de estado `413`. + +### Tamaño de finalización de tarea de workflow {#workflow-task-completion-size} + +En el Server nativo 3.6.0 y posteriores, una solicitud que finaliza una tarea de workflow con comandos (`POST /api/worker/workflow-tasks/{id}/complete` y `POST /api/worker/activity-tasks/{id}/continuation/complete`) puede ocupar hasta 16 veces `max_payload_bytes`: 32 MiB con el valor predeterminado de 2 MiB. Sigue a `DW_MAX_PAYLOAD_BYTES` y no tiene un ajuste propio. Los argumentos de cada comando siguen respetando el límite por carga útil dentro de la finalización. El Server PHP 2.x y las versiones nativas anteriores limitan una finalización a un límite de carga útil, como cualquier otra solicitud. + +Una finalización mayor se rechaza con `413 payload_too_large` y `limit_kind: workflow_task_completion_bytes` antes de registrar nada. Reproducir la tarea genera los mismos comandos, así que reenviar la finalización recibe el mismo rechazo. Cuando PHP SDK 3.17.0 o posterior recibe este rechazo tipado, no reenvía la finalización: el worker hace fallar la ejecución una sola vez con un comando `fail_workflow` cuyo mensaje empieza por `Structural limit exceeded: workflow_task_completion_bytes:` e indica ambos tamaños, y el Server registra el fallo con `failure_category = structural_limit`. + +Python SDK 2.17 y Rust SDK 4.15 gestionan el rechazo tipado. En Server 3.8.0, +una finalización demasiado grande puede fallar en el transporte antes de que el +worker reciba HTTP 413. En la prueba con el SDK de Python publicado, +`httpx.ReadError` dejó el workflow pendiente en lugar de fallar por un límite +estructural. La aceptación de solicitudes sobredimensionadas en el Server +publicado sigue abierta en la [corrección de la respuesta del Server](https://github.com/durable-workflow/.github/issues/228#issuecomment-6848969678). +Reduzca las finalizaciones hasta que esa ruta esté cualificada. + +Para mantener una finalización dentro del límite: + +- Divida un fan-out grande en lotes más pequeños repartidos entre tareas de workflow. +- Mueva trabajo a workflows hijos, o use continue-as-new. +- Guarde los argumentos grandes en el almacenamiento externo de cargas útiles, para que la finalización lleve referencias en lugar de las cargas útiles. + +#### Planificación de comandos en Rust {#rust-completion-planning} + +Rust SDK 4.15.0 sigue usando el límite habitual por carga como techo agregado +de planificación de comandos (2 MiB por defecto), antes de la mayor capacidad +de finalización del Server. Sin almacenamiento externo de cargas en el +namespace, el fan-out publicado de 300 × 10 KB se rechaza con +`external_payload_unavailable`. El worker sale y la ejecución sigue pendiente. +Use lotes de comandos más pequeños mientras esté pendiente la +[corrección del planificador agregado del SDK](https://github.com/durable-workflow/sdk-rust/issues/254). +Esta ruta del SDK aún no implementa la mayor capacidad del Server. + ## Inicialización de Docker y procedencia {#docker-bootstrap-and-provenance} | Variable | Valor predeterminado | Propósito | Alias antiguo | diff --git a/i18n/es/source-hashes.json b/i18n/es/source-hashes.json index 4ec35cae6fb..ca19adf3f36 100644 --- a/i18n/es/source-hashes.json +++ b/i18n/es/source-hashes.json @@ -17,7 +17,7 @@ "constraints/execution-guarantees.md": "c24aaff70bfcf50366459ec698ced67adff1e02c1b0ca23c8178a13873037f5a", "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", - "constraints/structural-limits.md": "ad498fae9ec7722aaca2990635027a4f52b4ac6dbd4b145c1aba1a03c6000b1b", + "constraints/structural-limits.md": "b9c2d515fce3b56a03ac654dab65edbe67e13903386412dba8aa1ea77a1d9657", "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", @@ -70,8 +70,8 @@ "polyglot/avro-value-protocol.md": "602e66c6288c1dd69d2b400c64e4739ad3a0493b5be269cee40f7848b11f260a", "polyglot/cancellation.md": "f676cd3ddb39246a0f580a1e16c83bc36d2ed9458b9e6009af4cc192d299ac62", "polyglot/cli-python-parity.md": "acf1acbf15ca9cdf069154699c5fbf8c1d1fd3241a32d201ac10b8ec76c038be", - "polyglot/cli-reference.md": "dc3802b01887f01e702b7989b54c06ba98e8e19326c17db7b32af4e5230e76ee", - "polyglot/cli.mdx": "5b4fdd5c283b3f45691324433d96e6c84e2e898d58fbb7536992ca1dc4503d54", + "polyglot/cli-reference.md": "665c65192f9bfd41610f2aca54a66c2a3aa125e2d2b637d744d9c5f4243bee24", + "polyglot/cli.mdx": "9dac7bb6b711737c9f16916ef462d85c642539f4b6e4a1bdac59320a09632c1f", "polyglot/cloud-control-plane.md": "bb375e598dd1afa3207171047fb81b0cb82c382ce535ab415cb09dc10f6d748e", "polyglot/database-support.md": "518f679ae723ae4d39db7cac78008bc8edb84a6cfba2e6c668d8f2be5d378d03", "polyglot/deployment-modes.md": "7b508db4be86c92de76cfd8dfd946d93941c8a6f0a601a161d4d3fd1711bf97f", @@ -84,12 +84,12 @@ "polyglot/polling-patterns.md": "30875099a23731c6c471b481a771378acc6ff57eed2fda4405a509057534c989", "polyglot/portable-worker-affinity.md": "40973c6a31a76845b4f95e9a505e68ad76abd5174bbdccf37993cdebc8904959", "polyglot/prerelease-history-migration.md": "a57f05f492228a8a67791f9152648a1e5f80856325b78777cf63b6ef49b7413c", - "polyglot/python.md": "1229182acdbe6ddf7f4d875a28c7db67c83931e4055b137b8ce35d4775e3a7b1", + "polyglot/python.md": "7e31563bf15d1f7f1bd1647b70644ef5e72b2c912c566e72e9b1cc4a7fe19d89", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "e9ebec32026199c861409f6fbba0a45f2e360638a68ac75387ad09fd09c6a420", + "polyglot/rust.md": "e768d43c38be76b22440910aa97d61897b392321f106dd2fe7461399a13a99c9", "polyglot/server-api-reference.md": "8bac825f11f7aa3f2a335cf3d1dcdc951219f11d6702e9fe3502d3803fd1e2a5", - "polyglot/server-config-reference.md": "02da3d03e49af3171de9268033c01273cb28fc7eaac665fcaa8aff1252be9055", + "polyglot/server-config-reference.md": "636e4aa05bcc56569a3d001bc80ad2853f95372b051aebcf2bdd0061d2e50b6b", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "2c03845c0979f62bc7ab3208cf09820844b224e548f10fb7d1656852e3428445", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/constraints/structural-limits.md b/i18n/fr/docusaurus-plugin-content-docs/current/constraints/structural-limits.md index 69349055516..a1513b6b266 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/constraints/structural-limits.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/constraints/structural-limits.md @@ -260,53 +260,10 @@ Le contrat complet figure dans la section `structural_limits` de la réponse des Waterline affiche les échecs de limite structurelle dans la table des exceptions avec la catégorie `structural_limit`. Les détails d’échec de la chronologie incluent le type de limite, la valeur courante et le plafond configuré. -## Limites à l’entrée des requêtes Server {#server-request-boundary-limits} +## Limites du mode service {#server-request-boundary-limits} -Avec le serveur autonome, un ensemble distinct de limites s’applique à l’entrée des requêtes HTTP, avant qu’une tâche de workflow, un signal, une mise à jour ou une requête de lecture atteigne le plan de contrôle. Ces contrôles renvoient immédiatement `422 validation_failed`, ou `413 payload_too_large` pour la taille du corps entier. Le client connaît ainsi le motif du refus sans qu’aucune ligne soit écrite en base. - -| Limite | Valeur par défaut | Clé de configuration | Ce qu’elle plafonne | -|---|---|---|---| -| Taille du corps | 2 MiB | `server.limits.max_payload_bytes` | Nombre total d’octets du corps HTTP, sauf pour un achèvement de tâche de workflow sur Server natif 3.6.0 ou ultérieur (ligne suivante) | -| Taille d’un achèvement de tâche de workflow | 32 MiB (16 × taille du corps) | dérivée de `server.limits.max_payload_bytes` | Server natif 3.6.0 ou ultérieur : une requête qui achève une tâche de workflow avec des commandes. Les arguments de chaque commande respectent toujours la limite par payload | -| Taille du mémo | 256 KiB | `server.limits.max_memo_bytes` | Mémo sérialisé sur `POST /workflows` et `POST /schedules` | -| Nombre d’attributs de recherche | 100 | `server.limits.max_search_attributes` | Attributs personnalisés enregistrés par espace de noms | -| Longueur de clé d’attribut de recherche | 128 octets | `server.limits.max_search_attribute_key_length` | Longueur d’une clé d’attribut au démarrage | -| Taille de valeur d’attribut de recherche | 2 KiB | `server.limits.max_search_attribute_value_bytes` | Chaque valeur chaîne et chaque élément d’un tableau au démarrage | -| Nom de signal / mise à jour / requête de lecture | 256 octets | `server.limits.max_operation_name_length` | Segment d’URL des noms de signal, mise à jour ou requête de lecture | -| Longueur de `workflow_id` | 128 caractères | validateur du contrôleur | Identifiant du workflow sur `POST /workflows` | -| `workflow_type` / `task_queue` / `business_key` | 255 caractères | validateur du contrôleur | Champs chaîne sur `POST /workflows` | -| `request_id` | 255 caractères | validateur du contrôleur | Jeton de déduplication des signaux/mises à jour/annulations/arrêts forcés | -| `reason` | 1 000 caractères | validateur du contrôleur | Motif des annulations/arrêts forcés/archivages | - -Chaque limite se configure individuellement via des variables d’environnement `DW_*`. Consultez `config/dw-contract.php` pour le contrat complet. La valeur `0` désactive le contrôle de cette limite précise, sans désactiver les autres. - -Les valeurs actuellement configurées sont publiées sous `limits` dans la réponse de `GET /api/cluster/info`, pour permettre leur découverte par les clients : - -```json -{ - "limits": { - "max_payload_bytes": 2097152, - "max_memo_bytes": 262144, - "max_search_attributes": 100, - "max_search_attribute_key_length": 128, - "max_search_attribute_value_bytes": 2048, - "max_operation_name_length": 256, - "max_pending_activities": 2000, - "max_pending_children": 2000 - } -} -``` - -Les erreurs de validation utilisent l’enveloppe d’erreur standard du plan de contrôle avec `reason: "validation_failed"` et une table `validation_errors` indexée par champ en cause (`signal_name`, `update_name`, `query_name`, `search_attributes`, `memo`, etc.). Les refus de taille utilisent `reason: "payload_too_large"` et le code `413`. +Les limites HTTP de Server et Cloud sont distinctes de ces contrôles Laravel embarqués. Consultez la [référence des requêtes du Server](../polyglot/server-config-reference.md#server-request-boundary-limits). ### Taille d’un achèvement de tâche de workflow {#workflow-task-completion-size} -Sur Server natif 3.6.0 et ultérieur, une requête qui achève une tâche de workflow avec des commandes (`POST /api/worker/workflow-tasks/{id}/complete` et `POST /api/worker/activity-tasks/{id}/continuation/complete`) peut atteindre 16 fois `max_payload_bytes` : 32 MiB avec la valeur par défaut de 2 MiB. Elle suit `DW_MAX_PAYLOAD_BYTES` et n’a pas de réglage propre. Les arguments de chaque commande respectent toujours la limite par payload à l’intérieur de l’achèvement. Server PHP 2.x et les versions natives antérieures limitent un achèvement à une limite de payload, comme toute autre requête. - -Un achèvement plus grand est refusé avec `413 payload_too_large` et `limit_kind: workflow_task_completion_bytes` avant tout enregistrement. Rejouer la tâche produit les mêmes commandes : renvoyer l’achèvement obtient donc le même refus. PHP SDK 3.17.0 et ultérieur ne le renvoient jamais : le worker fait échouer l’exécution une seule fois avec une commande `fail_workflow` dont le message commence par `Structural limit exceeded: workflow_task_completion_bytes:` et indique les deux tailles, et le Server enregistre l’échec avec `failure_category = structural_limit`. Les SDK Python et Rust feront de même dans leurs prochaines versions. - -Pour garder un achèvement sous la limite : - -- Découpez un fan-out important en lots plus petits répartis sur plusieurs tâches de workflow. -- Déplacez du travail dans des workflows enfants, ou utilisez continue-as-new. -- Stockez les arguments volumineux dans le stockage externe des payloads, afin que l’achèvement transporte des références au lieu des payloads. +Les limites de complétion et le traitement des refus des SDK en mode service figurent dans la [référence du Server](../polyglot/server-config-reference.md#workflow-task-completion-size). diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md b/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md index c62eee3febd..793f1b1f2bd 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md @@ -240,6 +240,7 @@ l'environnement du runtime plutôt que dans le fichier de profil. | `dw workflow:signal ` | Envoyer un signal. | `--run-id`, options d'entrée, `--json` | | `dw workflow:query ` | Exécuter une requête de lecture de workflow. | `--run-id`, options d'entrée, `--json` | | `dw workflow:update ` | Soumettre ou exécuter une mise à jour de workflow. | `--wait=accepted\|completed`, `--run-id`, options d'entrée, `--json` | +| `dw workflow:update-outcome ` | Lire le résultat conservé d'une mise à jour sans la soumettre de nouveau. | `--wait=accepted\|completed`, `--wait-timeout`, `--json` | | `dw workflow:cancel [workflow-id]` | Fermer un workflow ou un lot sélectionné comme annulé ; aucun nettoyage du code de workflow n'est exécuté. | `--reason`, `--run-id`, `--all-matching`, `--type`, `--status`, `--limit`, `--yes`, `--json` | | `dw workflow:terminate ` | Forcer la terminaison d'un workflow. | `--reason`, `--run-id`, `--json` | | `dw workflow:repair ` | Demander au serveur de réparer une exécution bloquée ou réessayable. | `--json` | @@ -264,6 +265,29 @@ dw workflow:cancel --all-matching='WorkflowType = "ImportJob"' --limit=25 --yes valident les champs canoniques avec le contrat de requête publié par le serveur. Les anciens alias non canoniques sont rejetés avant l'envoi. +### Lire le résultat d'une mise à jour {#read-update-outcome} + +CLI 2.8 et les versions suivantes peuvent lire une mise à jour acceptée par son +`update_id` si le Server annonce `capabilities.update_outcome_reads` (natif +3.6.0 ou ultérieur). Utilisez l'ID de l'accusé d'acceptation : + +```bash +dw workflow:update-outcome order-123 "$UPDATE_ID" +dw workflow:update-outcome order-123 "$UPDATE_ID" --wait=completed --wait-timeout=30 +``` + +La valeur par défaut `--wait=accepted` répond immédiatement. Une mise à jour +acceptée mais inachevée reste en attente, même quand le délai d'attente expire. +Une mise à jour terminée peut avoir un résultat null. `--json` renvoie l'accusé +validé. Utilisez son `update_status` pour distinguer ces cas. Chaque invocation +lit le résultat une fois et ne soumet jamais de nouveau la mise à jour. + +`--wait-timeout` exige `--wait=completed` et un nombre entier d'au moins une +seconde. Une mise à jour échouée se termine avec le code 2. Un ID inconnu ou +supprimé donne le code 5, ce qui ne prouve pas que la mise à jour n'a jamais été +acceptée. Un Server sans cette capacité, dont PHP Server 2.x, donne le code 8 +avant l'envoi d'une requête de résultat. + ## Inspection des appels de service {#service-call-inspection} Utilisez `dw service-call:describe ` diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/cli.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/cli.mdx index dfa9a7f3025..9a12c583751 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/cli.mdx +++ b/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/cli.mdx @@ -289,6 +289,11 @@ de fichier ou `-` pour stdin, et `--input-encoding=json|raw|base64`. JSON est la valeur par défaut ; les entrées raw et base64 sont transmises comme un seul argument positionnel de workflow. +Utilisez `dw workflow:update-outcome` pour lire plus tard une mise à jour +acceptée sans la soumettre de nouveau. En attente et terminé avec un résultat +null sont des états distincts. Consultez [lire le résultat d'une mise à jour](./cli-reference.md#read-update-outcome) +pour la capacité requise du Server et les options d'attente. + ### Adaptateurs de passerelle {#bridge-adapters} ```bash diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/python.md b/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/python.md index f9bf87ee092..9cad8311bb8 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/python.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/python.md @@ -123,6 +123,17 @@ Les versions 2.15 et 2.16 du SDK Python ajoutent : Voir le [journal des modifications 2.16.0](https://github.com/durable-workflow/sdk-python/blob/2.16.0/CHANGELOG.md) pour la liste complète. +Python SDK 2.17 ajoute `Client.update_outcome` et +`Client.update_outcome_receipt` pour lire plus tard une mise à jour acceptée +sans la soumettre de nouveau. Ces méthodes exigent +`capabilities.update_outcome_reads` (Server natif 3.6.0 ou ultérieur). +`update_outcome` attend la fin par défaut et lève `UpdateStillPending` si la mise +à jour n'est pas terminée. Un `None` renvoyé est un résultat null terminé. +`update_outcome_receipt` utilise par défaut l'étape d'acceptation et conserve +le `update_status` explicite. Consultez le +[guide du SDK Python](https://python.durable-workflow.com/reference/client/#read-an-update-outcome) +pour les exemples propres au langage. + ## Démarrage rapide {#quickstart} Ce programme Python complet définit un workflow avec une activité, le démarre @@ -408,13 +419,20 @@ parcours complet. Les équivalents CLI sont `dw task-queue:build-ids`, | `await client.export_history(workflow_id, run_id)` | historique d'archivage décodé | `WorkflowNotFound`, erreurs d'authentification/serveur | | `await client.signal_workflow(workflow_id, signal_name, args=None)` | `None` | `WorkflowNotFound`, `InvalidArgument`, erreurs d'authentification/serveur | | `await client.query_workflow(workflow_id, query_name, args=None)` | résultat de requête décodé | `QueryFailed`, `WorkflowNotFound`, erreurs d'authentification/serveur | -| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | résultat de mise à jour décodé | `UpdateRejected`, `WorkflowNotFound`, erreurs d'authentification/serveur | +| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | accusé de mise à jour (`dict`) | `UpdateRejected`, `UpdateValidationFailed`, `UpdateFailed`, `WorkflowNotFound`, erreurs d'authentification/serveur | | `await client.cancel_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, erreurs d'authentification/serveur | | `await client.terminate_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, erreurs d'authentification/serveur | | `await client.repair_workflow(workflow_id)` | `WorkflowCommandResult` | `WorkflowNotFound`, erreurs d'authentification/serveur | | `await client.archive_workflow(workflow_id, reason=None)` | `WorkflowCommandResult` | `WorkflowNotFound`, erreurs d'authentification/serveur | | `await client.get_result(handle, poll_interval=0.5, timeout=30.0)` | sortie de workflow décodée | `WorkflowFailed`, `WorkflowCancelled`, `WorkflowTerminated`, `TimeoutError` | +`update_workflow` utilise `wait_for="accepted"` par défaut. Son accusé peut +contenir `update_status="accepted"` et `result=None`. Avec +`wait_for="completed"`, `wait_timeout_seconds` borne l'attente. À son expiration, +l'accusé reste accepté et définit `wait_timed_out=True`. Seul +`update_status="completed"` identifie un résultat terminé, y compris `None`. +Conservez `update_id` pour [lire le résultat plus tard](https://python.durable-workflow.com/reference/client/#read-an-update-outcome). + `start_workflow` accepte `workflow_type`, `task_queue`, `workflow_id` facultatif, `input` facultatif, `duplicate_policy`, `memo`, `search_attributes`, `business_key`, `execution_timeout_seconds` et `run_timeout_seconds`. Toutes les données de 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 85a4f13650e..938eddfe7c6 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/rust.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/rust.md @@ -136,6 +136,21 @@ déterminent la compatibilité. Voir le [journal des modifications 4.13.0](https://github.com/durable-workflow/sdk-rust/blob/4.13.0/CHANGELOG.md). +## Lire les résultats conservés des mises à jour {#read-update-outcome} + +Rust SDK 4.15 ajoute `Client::update_outcome` et +`Client::update_outcome_receipt` pour lire une mise à jour acceptée par son ID +sans la soumettre de nouveau. Ces méthodes exigent +`capabilities.update_outcome_reads` (Server natif 3.6.0 ou ultérieur). +`update_outcome` renvoie `Error::UpdateStillPending` pour une mise à jour +inachevée. Un résultat null terminé est `Ok(Value::Null)`. Les accusés conservent +le `update_status` explicite. Consultez l'[API de Client](https://rust.durable-workflow.com/durable_workflow/struct.Client.html#method.update_outcome) +pour l'interface Rust. + +Rust SDK 4.15.0 applique encore le plafond ordinaire de charge utile au lot +entier de commandes. Consultez la [limite connue du planificateur](./server-config-reference.md#rust-completion-planning) +avant un grand fan-out sans stockage externe des charges utiles. + ## Échéances des attentes de condition et mise à niveau des workers {#condition-wait-deadlines} Le SDK Rust 4.11.2 mesure le délai d’un `wait_condition` hors groupe depuis diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md b/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md index 9f3579166bd..1e54f97e5d0 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md @@ -262,6 +262,81 @@ Ces paramètres limitent les requêtes et la croissance de l’état. Si une app | `DW_MAX_NEXUS_OPERATIONS_PER_CALLER` | `200` | Nombre maximal d’opérations Nexus renvoyées par appelant dans l’historique des opérations avant la pagination obligatoire. | `WORKFLOW_MAX_NEXUS_OPERATIONS_PER_CALLER` | | `DW_COMPRESSION_ENABLED` | `true` | Active la compression des réponses JSON au-dessus du seuil minimal. | `WORKFLOW_SERVER_COMPRESSION_ENABLED` | +## Limites à l’entrée des requêtes Server {#server-request-boundary-limits} + +Avec le serveur autonome, un ensemble distinct de limites s’applique à l’entrée des requêtes HTTP, avant qu’une tâche de workflow, un signal, une mise à jour ou une requête de lecture atteigne le plan de contrôle. Ces contrôles renvoient immédiatement `422 validation_failed`, ou `413 payload_too_large` pour la taille du corps entier. Le client connaît ainsi le motif du refus sans qu’aucune ligne soit écrite en base. + +| Limite | Valeur par défaut | Clé de configuration | Ce qu’elle plafonne | +|---|---|---|---| +| Taille du corps | 2 MiB | `server.limits.max_payload_bytes` | Nombre total d’octets du corps HTTP, sauf pour un achèvement de tâche de workflow sur Server natif 3.6.0 ou ultérieur (ligne suivante) | +| Taille d’un achèvement de tâche de workflow | 32 MiB (16 × taille du corps) | dérivée de `server.limits.max_payload_bytes` | Server natif 3.6.0 ou ultérieur : une requête qui achève une tâche de workflow avec des commandes. Les arguments de chaque commande respectent toujours la limite par payload | +| Taille du mémo | 256 KiB | `server.limits.max_memo_bytes` | Mémo sérialisé sur `POST /workflows` et `POST /schedules` | +| Nombre d’attributs de recherche | 100 | `server.limits.max_search_attributes` | Attributs personnalisés enregistrés par espace de noms | +| Longueur de clé d’attribut de recherche | 128 octets | `server.limits.max_search_attribute_key_length` | Longueur d’une clé d’attribut au démarrage | +| Taille de valeur d’attribut de recherche | 2 KiB | `server.limits.max_search_attribute_value_bytes` | Chaque valeur chaîne et chaque élément d’un tableau au démarrage | +| Nom de signal / mise à jour / requête de lecture | 256 octets | `server.limits.max_operation_name_length` | Segment d’URL des noms de signal, mise à jour ou requête de lecture | +| Longueur de `workflow_id` | 128 caractères | validateur du contrôleur | Identifiant du workflow sur `POST /workflows` | +| `workflow_type` / `task_queue` / `business_key` | 255 caractères | validateur du contrôleur | Champs chaîne sur `POST /workflows` | +| `request_id` | 255 caractères | validateur du contrôleur | Jeton de déduplication des signaux/mises à jour/annulations/arrêts forcés | +| `reason` | 1 000 caractères | validateur du contrôleur | Motif des annulations/arrêts forcés/archivages | + +Utilisez les paramètres `DW_*` documentés pour les limites configurables de +PHP Server 2.x. Les bornes de validation du contrôleur sont fixes. Native +Server 3.x prend en charge les paramètres de ses [notes d'implémentation](#native-server-3x). +Sur native 3.8.0, `DW_MAX_PAYLOAD_BYTES=0` fixe un plafond de zéro octet pour +les requêtes ordinaires et les complétions de tâches de workflow, refusant les +corps non vides. Le plafond des noms d'opérations est fixé à 256 octets. + +Les valeurs actuellement configurées sont publiées sous `limits` dans la réponse de `GET /api/cluster/info`, pour permettre leur découverte par les clients : + +```json +{ + "limits": { + "max_payload_bytes": 2097152, + "max_memo_bytes": 262144, + "max_search_attributes": 100, + "max_search_attribute_key_length": 128, + "max_search_attribute_value_bytes": 2048, + "max_operation_name_length": 256, + "max_pending_activities": 2000, + "max_pending_children": 2000 + } +} +``` + +Les erreurs de validation utilisent l’enveloppe d’erreur standard du plan de contrôle avec `reason: "validation_failed"` et une table `validation_errors` indexée par champ en cause (`signal_name`, `update_name`, `query_name`, `search_attributes`, `memo`, etc.). Les refus de taille utilisent `reason: "payload_too_large"` et le code `413`. + +### Taille d’un achèvement de tâche de workflow {#workflow-task-completion-size} + +Sur Server natif 3.6.0 et ultérieur, une requête qui achève une tâche de workflow avec des commandes (`POST /api/worker/workflow-tasks/{id}/complete` et `POST /api/worker/activity-tasks/{id}/continuation/complete`) peut atteindre 16 fois `max_payload_bytes` : 32 MiB avec la valeur par défaut de 2 MiB. Elle suit `DW_MAX_PAYLOAD_BYTES` et n’a pas de réglage propre. Les arguments de chaque commande respectent toujours la limite par payload à l’intérieur de l’achèvement. Server PHP 2.x et les versions natives antérieures limitent un achèvement à une limite de payload, comme toute autre requête. + +Un achèvement plus grand est refusé avec `413 payload_too_large` et `limit_kind: workflow_task_completion_bytes` avant tout enregistrement. Rejouer la tâche produit les mêmes commandes : renvoyer l’achèvement obtient donc le même refus. Lorsque PHP SDK 3.17.0 ou ultérieur reçoit ce refus typé, il ne renvoie pas cet achèvement : le worker fait échouer l’exécution une seule fois avec une commande `fail_workflow` dont le message commence par `Structural limit exceeded: workflow_task_completion_bytes:` et indique les deux tailles, et le Server enregistre l’échec avec `failure_category = structural_limit`. + +Python SDK 2.17 et Rust SDK 4.15 gèrent le refus typé. Sur Server 3.8.0, une +complétion trop volumineuse peut échouer au niveau du transport avant que le +worker reçoive HTTP 413. Dans le test avec le SDK Python publié, +`httpx.ReadError` a laissé le workflow en attente au lieu d'un échec pour limite +structurelle. La qualification des requêtes surdimensionnées sur le Server +publié reste ouverte dans la [correction de la réponse du Server](https://github.com/durable-workflow/.github/issues/228#issuecomment-6848969678). +Réduisez les complétions jusqu'à la qualification de ce chemin. + +Pour garder un achèvement sous la limite : + +- Découpez un fan-out important en lots plus petits répartis sur plusieurs tâches de workflow. +- Déplacez du travail dans des workflows enfants, ou utilisez continue-as-new. +- Stockez les arguments volumineux dans le stockage externe des payloads, afin que l’achèvement transporte des références au lieu des payloads. + +#### Planification des commandes Rust {#rust-completion-planning} + +Rust SDK 4.15.0 utilise encore la limite ordinaire par charge utile comme +plafond agrégé de planification des commandes (2 MiB par défaut), avant la +capacité de complétion supérieure du Server. Sans stockage externe des charges +utiles dans l'espace de noms, le fan-out publié de 300 × 10 KB est refusé avec +`external_payload_unavailable`. Le worker s'arrête et l'exécution reste en +attente. Utilisez des lots plus petits en attendant la +[correction du planificateur agrégé du SDK](https://github.com/durable-workflow/sdk-rust/issues/254). +Ce chemin du SDK ne fournit pas encore la capacité supérieure du Server. + ## Initialisation Docker et provenance {#docker-bootstrap-and-provenance} | Variable | Valeur par défaut | Rôle | Ancien alias | diff --git a/i18n/fr/source-hashes.json b/i18n/fr/source-hashes.json index 4ec35cae6fb..ca19adf3f36 100644 --- a/i18n/fr/source-hashes.json +++ b/i18n/fr/source-hashes.json @@ -17,7 +17,7 @@ "constraints/execution-guarantees.md": "c24aaff70bfcf50366459ec698ced67adff1e02c1b0ca23c8178a13873037f5a", "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", - "constraints/structural-limits.md": "ad498fae9ec7722aaca2990635027a4f52b4ac6dbd4b145c1aba1a03c6000b1b", + "constraints/structural-limits.md": "b9c2d515fce3b56a03ac654dab65edbe67e13903386412dba8aa1ea77a1d9657", "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", @@ -70,8 +70,8 @@ "polyglot/avro-value-protocol.md": "602e66c6288c1dd69d2b400c64e4739ad3a0493b5be269cee40f7848b11f260a", "polyglot/cancellation.md": "f676cd3ddb39246a0f580a1e16c83bc36d2ed9458b9e6009af4cc192d299ac62", "polyglot/cli-python-parity.md": "acf1acbf15ca9cdf069154699c5fbf8c1d1fd3241a32d201ac10b8ec76c038be", - "polyglot/cli-reference.md": "dc3802b01887f01e702b7989b54c06ba98e8e19326c17db7b32af4e5230e76ee", - "polyglot/cli.mdx": "5b4fdd5c283b3f45691324433d96e6c84e2e898d58fbb7536992ca1dc4503d54", + "polyglot/cli-reference.md": "665c65192f9bfd41610f2aca54a66c2a3aa125e2d2b637d744d9c5f4243bee24", + "polyglot/cli.mdx": "9dac7bb6b711737c9f16916ef462d85c642539f4b6e4a1bdac59320a09632c1f", "polyglot/cloud-control-plane.md": "bb375e598dd1afa3207171047fb81b0cb82c382ce535ab415cb09dc10f6d748e", "polyglot/database-support.md": "518f679ae723ae4d39db7cac78008bc8edb84a6cfba2e6c668d8f2be5d378d03", "polyglot/deployment-modes.md": "7b508db4be86c92de76cfd8dfd946d93941c8a6f0a601a161d4d3fd1711bf97f", @@ -84,12 +84,12 @@ "polyglot/polling-patterns.md": "30875099a23731c6c471b481a771378acc6ff57eed2fda4405a509057534c989", "polyglot/portable-worker-affinity.md": "40973c6a31a76845b4f95e9a505e68ad76abd5174bbdccf37993cdebc8904959", "polyglot/prerelease-history-migration.md": "a57f05f492228a8a67791f9152648a1e5f80856325b78777cf63b6ef49b7413c", - "polyglot/python.md": "1229182acdbe6ddf7f4d875a28c7db67c83931e4055b137b8ce35d4775e3a7b1", + "polyglot/python.md": "7e31563bf15d1f7f1bd1647b70644ef5e72b2c912c566e72e9b1cc4a7fe19d89", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "e9ebec32026199c861409f6fbba0a45f2e360638a68ac75387ad09fd09c6a420", + "polyglot/rust.md": "e768d43c38be76b22440910aa97d61897b392321f106dd2fe7461399a13a99c9", "polyglot/server-api-reference.md": "8bac825f11f7aa3f2a335cf3d1dcdc951219f11d6702e9fe3502d3803fd1e2a5", - "polyglot/server-config-reference.md": "02da3d03e49af3171de9268033c01273cb28fc7eaac665fcaa8aff1252be9055", + "polyglot/server-config-reference.md": "636e4aa05bcc56569a3d001bc80ad2853f95372b051aebcf2bdd0061d2e50b6b", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "2c03845c0979f62bc7ab3208cf09820844b224e548f10fb7d1656852e3428445", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/constraints/structural-limits.md b/i18n/ja/docusaurus-plugin-content-docs/current/constraints/structural-limits.md index 14fcffd163a..c5327c2b503 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/constraints/structural-limits.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/constraints/structural-limits.md @@ -246,53 +246,10 @@ v2 のヘルススナップショットの `structural_limits` に現在の設 例外テーブルに失敗分類 `structural_limit` を表示します。タイムラインの詳細は制限種別、現在値、設定上限を含みます。 -## Server のリクエスト境界の制限 {#server-request-boundary-limits} +## Service Mode の上限 {#server-request-boundary-limits} -独立 Server は、タスク、シグナル、更新、クエリがコントロールプレーンに達する前に HTTP 境界で別の上限を適用します。データベース行を書かずに `422 validation_failed`(本文全体は `413 payload_too_large`)で直ちに拒否し、原因を知らせます。 - -| 制限 | 既定値 | 設定キー | 制限するもの | -|---|---|---|---| -| 本文サイズ | 2 MiB | `server.limits.max_payload_bytes` | HTTP 本文の総バイト数。ただし native Server 3.6.0 以降のワークフロータスク完了を除く(次の行) | -| ワークフロータスク完了サイズ | 32 MiB(本文サイズの 16 倍) | `server.limits.max_payload_bytes` から算出 | native Server 3.6.0 以降:コマンド付きでワークフロータスクを完了するリクエスト。各コマンドの引数には引き続きペイロードごとの上限が適用される | -| メモサイズ | 256 KiB | `server.limits.max_memo_bytes` | `POST /workflows` と `POST /schedules` のシリアライズ済みメモ | -| 検索属性数 | 100 | `server.limits.max_search_attributes` | 名前空間の登録済みカスタム属性数 | -| 検索属性キー長 | 128バイト | `server.limits.max_search_attribute_key_length` | 開始時の単一 SA キー長 | -| 検索属性値サイズ | 2 KiB | `server.limits.max_search_attribute_value_bytes` | 開始時の各文字列(配列は各要素) | -| シグナル・更新・クエリ名 | 256バイト | `server.limits.max_operation_name_length` | 名前の URL パスセグメント | -| `workflow_id` 長 | 128文字 | コントローラーの検証 | `POST /workflows` の ID | -| `workflow_type` / `task_queue` / `business_key` | 255文字 | コントローラーの検証 | `POST /workflows` の文字列 | -| `request_id` | 255文字 | コントローラーの検証 | シグナル・更新・キャンセル・強制終了の重複排除トークン | -| `reason` | 1,000文字 | コントローラーの検証 | キャンセル・強制終了・アーカイブの理由 | - -各上限は `DW_*` 環境変数で個別に設定できます(全契約は `config/dw-contract.php`)。`0` はその制限のみ無効にし、他は維持します。 - -`GET /api/cluster/info` の `limits` に現在値を公開し、クライアントが実行時に確認できます。 - -```json -{ - "limits": { - "max_payload_bytes": 2097152, - "max_memo_bytes": 262144, - "max_search_attributes": 100, - "max_search_attribute_key_length": 128, - "max_search_attribute_value_bytes": 2048, - "max_operation_name_length": 256, - "max_pending_activities": 2000, - "max_pending_children": 2000 - } -} -``` - -検証エラーは標準形式で `reason: "validation_failed"` と、該当フィールド(`signal_name`、`update_name`、`query_name`、`search_attributes`、`memo` など)をキーにした `validation_errors` を返します。サイズ拒否は `reason: "payload_too_large"` と `413` です。 +Server と Cloud の HTTP リクエスト上限は、ここで説明する組み込み Laravel の制御とは別です。[Server のリクエストリファレンス](../polyglot/server-config-reference.md#server-request-boundary-limits)を参照してください。 ### ワークフロータスク完了サイズ {#workflow-task-completion-size} -native Server 3.6.0 以降では、コマンド付きでワークフロータスクを完了するリクエスト(`POST /api/worker/workflow-tasks/{id}/complete` と `POST /api/worker/activity-tasks/{id}/continuation/complete`)は `max_payload_bytes` の 16 倍まで許可されます。既定の 2 MiB なら 32 MiB です。この上限は `DW_MAX_PAYLOAD_BYTES` に従い、専用の設定はありません。完了の中でも、各コマンドの引数には引き続きペイロードごとの上限が適用されます。PHP Server 2.x と以前の native リリースは、他のリクエストと同じく完了を 1 ペイロード分の上限に制限します。 - -それより大きい完了は、何も記録される前に `413 payload_too_large` と `limit_kind: workflow_task_completion_bytes` で拒否されます。タスクをリプレイしても同じコマンドが生成されるため、完了を再送しても同じ拒否になります。PHP SDK 3.17.0 以降はこれを再送しません。Worker は `Structural limit exceeded: workflow_task_completion_bytes:` で始まり両方のサイズを示すメッセージの `fail_workflow` コマンドで実行を一度だけ失敗させ、Server はその失敗を `failure_category = structural_limit` として記録します。Python と Rust の SDK も次のリリースで同じ動作になります。 - -完了を上限内に収めるには: - -- 大きなファンアウトを、複数のワークフロータスクにまたがる小さなバッチに分割します。 -- 処理を子ワークフローに移すか、continue-as-new を使います。 -- 大きな引数は外部ペイロードストレージに保存し、完了にはペイロードではなく参照を含めます。 +Service Mode の完了上限と SDK による拒否処理は、[Server リファレンス](../polyglot/server-config-reference.md#workflow-task-completion-size)で説明しています。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md b/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md index 09842e43c8f..242991f2b9a 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md @@ -152,6 +152,7 @@ dw server:info --output=json \ | `dw workflow:signal ` | シグナルを送信。 | `--run-id`、入力オプション、`--json` | | `dw workflow:query ` | 読み取り専用クエリを実行。 | `--run-id`、入力オプション、`--json` | | `dw workflow:update ` | 更新を送信または実行。 | `--wait=accepted\|completed`, `--run-id`、入力オプション、`--json` | +| `dw workflow:update-outcome ` | 更新を再送信せずに、保持された更新結果を読み取ります。 | `--wait=accepted\|completed`, `--wait-timeout`, `--json` | | `dw workflow:cancel [workflow-id]` | 1ワークフローまたは選択したバッチをキャンセルとして閉じる。コードのクリーンアップは動かない。 | `--reason`, `--run-id`, `--all-matching`, `--type`, `--status`, `--limit`, `--yes`, `--json` | | `dw workflow:terminate ` | ワークフローを強制終了。 | `--reason`, `--run-id`, `--json` | | `dw workflow:repair ` | 停滞または再試行可能な実行の修復を Server に要求。 | `--json` | @@ -174,6 +175,19 @@ dw workflow:cancel --all-matching='WorkflowType = "ImportJob"' --limit=25 --yes `workflow:start`、`workflow:signal`、`workflow:query`、`workflow:update` は、Server が公開する要求契約に照らして正規フィールドを検証します。正規でない旧別名は要求送信前に拒否します。 +### 更新の結果を読み取る {#read-update-outcome} + +CLI 2.8 以降では、Server が `capabilities.update_outcome_reads` を公開している場合(native 3.6.0 以降)、受け付け済みの更新を `update_id` で読み取れます。受け付け時のレシートにある ID を使ってください。 + +```bash +dw workflow:update-outcome order-123 "$UPDATE_ID" +dw workflow:update-outcome order-123 "$UPDATE_ID" --wait=completed --wait-timeout=30 +``` + +既定の `--wait=accepted` はすぐに応答します。受け付け済みでも完了していない更新は、完了待ちがタイムアウトした場合も保留中です。完了した更新の結果が null の場合もあります。`--json` は検証済みのレシートを返すので、`update_status` で区別してください。各実行は結果を一度読み取るだけで、更新を再送信しません。 + +`--wait-timeout` には `--wait=completed` と 1 秒以上の整数が必要です。失敗した更新は終了コード 2 を返します。不明または削除済みの更新 ID は 5 を返しますが、更新が一度も受け付けられなかったことを意味しません。PHP Server 2.x など、この機能を持たない Server では、結果のリクエストを送る前に 8 で終了します。 + ## サービス呼び出しの検査 {#service-call-inspection} エンドポイントの名前空間の永続 Nexus 呼び出しを1件検査するには `dw service-call:describe ` を使います。たとえば `dw service-call:describe billing invoices create call-42 --namespace=shared --json` は完全な Server レスポンスを返します。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/cli.mdx b/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/cli.mdx index 0b114fed2ac..bef8f438173 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/cli.mdx +++ b/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/cli.mdx @@ -226,6 +226,8 @@ dw workflow:history # Show run history 呼び出し元のペイロードを受け取る全コマンドは同じ入力形式を使います。インライン値は `--input`、ファイルパスまたは標準入力を示す `-` は `--input-file`、エンコードは `--input-encoding=json|raw|base64` です。既定は JSON で、raw と base64 の入力は一つの位置引数としてワークフローに渡します。 +`dw workflow:update-outcome` を使うと、受け付け済みの更新を再送信せずに後から読み取れます。保留中と、null の結果で完了した状態は異なります。必要な Server の機能と待機オプションは、[更新結果の読み取り](./cli-reference.md#read-update-outcome)を参照してください。 + ### ブリッジアダプター {#bridge-adapters} ```bash diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/python.md b/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/python.md index 74415ea62d7..19a5d4ab366 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/python.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/python.md @@ -89,6 +89,8 @@ Python SDK 2.15 と 2.16 では次が追加されています。 完全な一覧は [2.16.0 の変更履歴](https://github.com/durable-workflow/sdk-python/blob/2.16.0/CHANGELOG.md) を参照してください。 +Python SDK 2.17 では、受け付け済みの更新を再送信せずに後から読み取る `Client.update_outcome` と `Client.update_outcome_receipt` が追加されました。これらには `capabilities.update_outcome_reads`(native Server 3.6.0 以降)が必要です。`update_outcome` は既定で完了を待ち、未完了なら `UpdateStillPending` を送出します。返された `None` は、完了した null の結果です。`update_outcome_receipt` は既定で受け付け段階を使い、明示的な `update_status` を保持します。言語固有の例は [Python SDK のガイド](https://python.durable-workflow.com/reference/client/#read-an-update-outcome)を参照してください。 + ## クイックスタート {#quickstart} 次は、アクティビティを1つ持つワークフローを定義し、ローカルの Durable Workflow Server に対して開始して結果を待つ完全な Python プログラムです。 @@ -343,13 +345,15 @@ driver = external_storage_driver_from_policy( | `await client.export_history(workflow_id, run_id)` | デコード済みアーカイブ履歴ペイロード | `WorkflowNotFound`、認証・Server エラー | | `await client.signal_workflow(workflow_id, signal_name, args=None)` | `None` | `WorkflowNotFound`、`InvalidArgument`、認証・Server エラー | | `await client.query_workflow(workflow_id, query_name, args=None)` | デコード済みクエリ結果 | `QueryFailed`、`WorkflowNotFound`、認証・Server エラー | -| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | デコード済み更新結果 | `UpdateRejected`、`WorkflowNotFound`、認証・Server エラー | +| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | 更新レシート(`dict`) | `UpdateRejected`, `UpdateValidationFailed`, `UpdateFailed`、`WorkflowNotFound`、認証・Server エラー | | `await client.cancel_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`、認証・Server エラー | | `await client.terminate_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`、認証・Server エラー | | `await client.repair_workflow(workflow_id)` | `WorkflowCommandResult` | `WorkflowNotFound`、認証・Server エラー | | `await client.archive_workflow(workflow_id, reason=None)` | `WorkflowCommandResult` | `WorkflowNotFound`、認証・Server エラー | | `await client.get_result(handle, poll_interval=0.5, timeout=30.0)` | デコード済みワークフロー出力 | `WorkflowFailed`、`WorkflowCancelled`、`WorkflowTerminated`、`TimeoutError` | +`update_workflow` の既定は `wait_for="accepted"` です。レシートは `update_status="accepted"` と `result=None` を含む場合があります。`wait_for="completed"` では、`wait_timeout_seconds` が待機時間を制限します。期限が切れると、レシートは受け付け済みのまま `wait_timed_out=True` を設定します。`None` を含む完了した結果は、`update_status="completed"` でのみ識別できます。`update_id` を保持し、[後から結果を読み取ってください](https://python.durable-workflow.com/reference/client/#read-an-update-outcome)。 + `start_workflow` は `workflow_type`、`task_queue`、任意の `workflow_id`、`input`、`duplicate_policy`、`memo`、`search_attributes`、`business_key`、`execution_timeout_seconds`、`run_timeout_seconds` を受け入れます。呼び出し元のすべてのペイロードは HTTP 境界を越える前に Avro エンベロープ化します。 スクリプトがワークフロー ID を知っていてハンドル形式のメソッドを使いたい場合、`client.get_workflow_handle(workflow_id, run_id=None, workflow_type="")` を使います。 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 b7123c64340..1bf5ecccde3 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/rust.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/rust.md @@ -79,6 +79,12 @@ Server はメジャー `1` 内で Worker プロトコルヘッダーをネゴシ [4.13.0 の変更履歴](https://github.com/durable-workflow/sdk-rust/blob/4.13.0/CHANGELOG.md) を参照してください。 +## 保持された更新結果を読み取る {#read-update-outcome} + +Rust SDK 4.15 では、受け付け済みの更新を ID で読み取り、再送信を避ける `Client::update_outcome` と `Client::update_outcome_receipt` が追加されました。これらには `capabilities.update_outcome_reads`(native Server 3.6.0 以降)が必要です。`update_outcome` は未完了の更新に対して `Error::UpdateStillPending` を返します。完了した null の結果は `Ok(Value::Null)` です。レシートは明示的な `update_status` を保持します。Rust のインターフェースは [Client API](https://rust.durable-workflow.com/durable_workflow/struct.Client.html#method.update_outcome) を参照してください。 + +Rust SDK 4.15.0 は、通常のペイロード上限をコマンドバッチ全体に適用します。外部ペイロードストレージなしで大きなファンアウトを実行する前に、[既知の計画上限](./server-config-reference.md#rust-completion-planning)を確認してください。 + ## 条件待機の期限と Worker のアップグレード {#condition-wait-deadlines} Rust SDK 4.11.2 は、グループに含まれない `wait_condition` のタイムアウトを diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md b/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md index 3f1e013cb1d..4930453b48c 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md @@ -262,6 +262,63 @@ Sticky 実行には Server イメージ専用の環境変数はありません | `DW_MAX_NEXUS_OPERATIONS_PER_CALLER` | `200` | クライアントにページングが必要になる前に、操作履歴から呼び出し元ごとに返す Nexus 操作数の上限。 | `WORKFLOW_MAX_NEXUS_OPERATIONS_PER_CALLER` | | `DW_COMPRESSION_ENABLED` | `true` | 最低サイズを超える JSON レスポンスの圧縮を有効にします。 | `WORKFLOW_SERVER_COMPRESSION_ENABLED` | +## Server のリクエスト境界の制限 {#server-request-boundary-limits} + +独立 Server は、タスク、シグナル、更新、クエリがコントロールプレーンに達する前に HTTP 境界で別の上限を適用します。データベース行を書かずに `422 validation_failed`(本文全体は `413 payload_too_large`)で直ちに拒否し、原因を知らせます。 + +| 制限 | 既定値 | 設定キー | 制限するもの | +|---|---|---|---| +| 本文サイズ | 2 MiB | `server.limits.max_payload_bytes` | HTTP 本文の総バイト数。ただし native Server 3.6.0 以降のワークフロータスク完了を除く(次の行) | +| ワークフロータスク完了サイズ | 32 MiB(本文サイズの 16 倍) | `server.limits.max_payload_bytes` から算出 | native Server 3.6.0 以降:コマンド付きでワークフロータスクを完了するリクエスト。各コマンドの引数には引き続きペイロードごとの上限が適用される | +| メモサイズ | 256 KiB | `server.limits.max_memo_bytes` | `POST /workflows` と `POST /schedules` のシリアライズ済みメモ | +| 検索属性数 | 100 | `server.limits.max_search_attributes` | 名前空間の登録済みカスタム属性数 | +| 検索属性キー長 | 128バイト | `server.limits.max_search_attribute_key_length` | 開始時の単一 SA キー長 | +| 検索属性値サイズ | 2 KiB | `server.limits.max_search_attribute_value_bytes` | 開始時の各文字列(配列は各要素) | +| シグナル・更新・クエリ名 | 256バイト | `server.limits.max_operation_name_length` | 名前の URL パスセグメント | +| `workflow_id` 長 | 128文字 | コントローラーの検証 | `POST /workflows` の ID | +| `workflow_type` / `task_queue` / `business_key` | 255文字 | コントローラーの検証 | `POST /workflows` の文字列 | +| `request_id` | 255文字 | コントローラーの検証 | シグナル・更新・キャンセル・強制終了の重複排除トークン | +| `reason` | 1,000文字 | コントローラーの検証 | キャンセル・強制終了・アーカイブの理由 | + +PHP Server 2.x の設定可能な上限には、文書化された `DW_*` 設定を使ってください。コントローラーの検証上限は固定です。Native Server 3.x が対応する設定は、[実装上の注意](#native-server-3x)に記載されています。native 3.8.0 の `DW_MAX_PAYLOAD_BYTES=0` は、通常のリクエストとワークフロータスクの完了に対して 0 バイトの上限を設定し、空でないボディーを拒否します。操作名の上限は 256 バイトに固定されています。 + +`GET /api/cluster/info` の `limits` に現在値を公開し、クライアントが実行時に確認できます。 + +```json +{ + "limits": { + "max_payload_bytes": 2097152, + "max_memo_bytes": 262144, + "max_search_attributes": 100, + "max_search_attribute_key_length": 128, + "max_search_attribute_value_bytes": 2048, + "max_operation_name_length": 256, + "max_pending_activities": 2000, + "max_pending_children": 2000 + } +} +``` + +検証エラーは標準形式で `reason: "validation_failed"` と、該当フィールド(`signal_name`、`update_name`、`query_name`、`search_attributes`、`memo` など)をキーにした `validation_errors` を返します。サイズ拒否は `reason: "payload_too_large"` と `413` です。 + +### ワークフロータスク完了サイズ {#workflow-task-completion-size} + +native Server 3.6.0 以降では、コマンド付きでワークフロータスクを完了するリクエスト(`POST /api/worker/workflow-tasks/{id}/complete` と `POST /api/worker/activity-tasks/{id}/continuation/complete`)は `max_payload_bytes` の 16 倍まで許可されます。既定の 2 MiB なら 32 MiB です。この上限は `DW_MAX_PAYLOAD_BYTES` に従い、専用の設定はありません。完了の中でも、各コマンドの引数には引き続きペイロードごとの上限が適用されます。PHP Server 2.x と以前の native リリースは、他のリクエストと同じく完了を 1 ペイロード分の上限に制限します。 + +それより大きい完了は、何も記録される前に `413 payload_too_large` と `limit_kind: workflow_task_completion_bytes` で拒否されます。タスクをリプレイしても同じコマンドが生成されるため、完了を再送しても同じ拒否になります。PHP SDK 3.17.0 以降は、この型付き拒否を受信した場合、完了リクエストを再送しません。Worker は `Structural limit exceeded: workflow_task_completion_bytes:` で始まり両方のサイズを示すメッセージの `fail_workflow` コマンドで実行を一度だけ失敗させ、Server はその失敗を `failure_category = structural_limit` として記録します。 + +Python SDK 2.17 と Rust SDK 4.15 は型付き拒否の処理に対応しています。Server 3.8.0 では、大きすぎる完了リクエストが、Worker に HTTP 413 が届く前にトランスポート層で失敗することがあります。公開済み Python SDK のテストでは、`httpx.ReadError` により、ワークフローは構造上限による失敗にならず、保留中のままでした。公開済み Server での上限超過リクエストの受け入れ検証は、[Server の応答修正](https://github.com/durable-workflow/.github/issues/228#issuecomment-6848969678)で引き続き対応中です。この経路の適格性が確認されるまでは、完了リクエストを小さくしてください。 + +完了を上限内に収めるには: + +- 大きなファンアウトを、複数のワークフロータスクにまたがる小さなバッチに分割します。 +- 処理を子ワークフローに移すか、continue-as-new を使います。 +- 大きな引数は外部ペイロードストレージに保存し、完了にはペイロードではなく参照を含めます。 + +#### Rust のコマンド計画 {#rust-completion-planning} + +Rust SDK 4.15.0 は、Server のより大きな完了上限より先に、通常のペイロード上限をコマンド計画全体の上限として適用します(既定は 2 MiB)。名前空間に外部ペイロードストレージがない場合、公開済みの 300 × 10 KB ファンアウトは `external_payload_unavailable` で拒否され、Worker が終了し、実行は保留中のままになります。[SDK の集約計画の修正](https://github.com/durable-workflow/sdk-rust/issues/254)が完了するまでは、小さなコマンドバッチを使ってください。この SDK の経路は、Server のより大きな上限にはまだ対応していません。 + ## Docker の初期化と出所情報 {#docker-bootstrap-and-provenance} | 変数 | 既定値 | 用途 | 従来の別名 | diff --git a/i18n/ja/source-hashes.json b/i18n/ja/source-hashes.json index 4ec35cae6fb..ca19adf3f36 100644 --- a/i18n/ja/source-hashes.json +++ b/i18n/ja/source-hashes.json @@ -17,7 +17,7 @@ "constraints/execution-guarantees.md": "c24aaff70bfcf50366459ec698ced67adff1e02c1b0ca23c8178a13873037f5a", "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", - "constraints/structural-limits.md": "ad498fae9ec7722aaca2990635027a4f52b4ac6dbd4b145c1aba1a03c6000b1b", + "constraints/structural-limits.md": "b9c2d515fce3b56a03ac654dab65edbe67e13903386412dba8aa1ea77a1d9657", "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", @@ -70,8 +70,8 @@ "polyglot/avro-value-protocol.md": "602e66c6288c1dd69d2b400c64e4739ad3a0493b5be269cee40f7848b11f260a", "polyglot/cancellation.md": "f676cd3ddb39246a0f580a1e16c83bc36d2ed9458b9e6009af4cc192d299ac62", "polyglot/cli-python-parity.md": "acf1acbf15ca9cdf069154699c5fbf8c1d1fd3241a32d201ac10b8ec76c038be", - "polyglot/cli-reference.md": "dc3802b01887f01e702b7989b54c06ba98e8e19326c17db7b32af4e5230e76ee", - "polyglot/cli.mdx": "5b4fdd5c283b3f45691324433d96e6c84e2e898d58fbb7536992ca1dc4503d54", + "polyglot/cli-reference.md": "665c65192f9bfd41610f2aca54a66c2a3aa125e2d2b637d744d9c5f4243bee24", + "polyglot/cli.mdx": "9dac7bb6b711737c9f16916ef462d85c642539f4b6e4a1bdac59320a09632c1f", "polyglot/cloud-control-plane.md": "bb375e598dd1afa3207171047fb81b0cb82c382ce535ab415cb09dc10f6d748e", "polyglot/database-support.md": "518f679ae723ae4d39db7cac78008bc8edb84a6cfba2e6c668d8f2be5d378d03", "polyglot/deployment-modes.md": "7b508db4be86c92de76cfd8dfd946d93941c8a6f0a601a161d4d3fd1711bf97f", @@ -84,12 +84,12 @@ "polyglot/polling-patterns.md": "30875099a23731c6c471b481a771378acc6ff57eed2fda4405a509057534c989", "polyglot/portable-worker-affinity.md": "40973c6a31a76845b4f95e9a505e68ad76abd5174bbdccf37993cdebc8904959", "polyglot/prerelease-history-migration.md": "a57f05f492228a8a67791f9152648a1e5f80856325b78777cf63b6ef49b7413c", - "polyglot/python.md": "1229182acdbe6ddf7f4d875a28c7db67c83931e4055b137b8ce35d4775e3a7b1", + "polyglot/python.md": "7e31563bf15d1f7f1bd1647b70644ef5e72b2c912c566e72e9b1cc4a7fe19d89", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "e9ebec32026199c861409f6fbba0a45f2e360638a68ac75387ad09fd09c6a420", + "polyglot/rust.md": "e768d43c38be76b22440910aa97d61897b392321f106dd2fe7461399a13a99c9", "polyglot/server-api-reference.md": "8bac825f11f7aa3f2a335cf3d1dcdc951219f11d6702e9fe3502d3803fd1e2a5", - "polyglot/server-config-reference.md": "02da3d03e49af3171de9268033c01273cb28fc7eaac665fcaa8aff1252be9055", + "polyglot/server-config-reference.md": "636e4aa05bcc56569a3d001bc80ad2853f95372b051aebcf2bdd0061d2e50b6b", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "2c03845c0979f62bc7ab3208cf09820844b224e548f10fb7d1656852e3428445", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/constraints/structural-limits.md b/i18n/pt-BR/docusaurus-plugin-content-docs/current/constraints/structural-limits.md index 2b8a604f3a8..632905cf6c0 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/constraints/structural-limits.md +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/constraints/structural-limits.md @@ -260,53 +260,10 @@ O contrato completo está disponível na seção `structural_limits` da resposta O Waterline exibe falhas de limites estruturais na tabela de exceções com a categoria de falha `structural_limit`. Os detalhes da falha na linha do tempo incluem o tipo de limite, o valor atual e o teto configurado. -## Limites na fronteira de requisições do Server {#server-request-boundary-limits} +## Limites do modo de serviço {#server-request-boundary-limits} -Ao usar o servidor independente, um conjunto separado de tetos é aplicado na fronteira de requisições HTTP, antes que uma tarefa de workflow, sinal, atualização ou consulta chegue ao plano de controle. Esses limites falham imediatamente com uma resposta `422 validation_failed` (ou `413 payload_too_large` nas verificações do corpo inteiro), para que clientes saibam o motivo da rejeição sem que o servidor grave qualquer registro no banco de dados. - -| Limite | Padrão | Chave de configuração | O que restringe | -|---|---|---|---| -| Tamanho do corpo | 2 MiB | `server.limits.max_payload_bytes` | Total de bytes do corpo da requisição HTTP, exceto uma conclusão de tarefa de workflow no Server nativo 3.6.0 ou posterior (próxima linha) | -| Tamanho da conclusão de tarefa de workflow | 32 MiB (16 × tamanho do corpo) | derivado de `server.limits.max_payload_bytes` | Server nativo 3.6.0 ou posterior: uma requisição que conclui uma tarefa de workflow com comandos. Os argumentos de cada comando continuam respeitando o limite por payload | -| Tamanho do memo | 256 KiB | `server.limits.max_memo_bytes` | Memo serializado em `POST /workflows` e `POST /schedules` | -| Contagem de atributos de busca | 100 | `server.limits.max_search_attributes` | Atributos de busca personalizados registrados por namespace | -| Comprimento da chave de atributo de busca | 128 bytes | `server.limits.max_search_attribute_key_length` | Comprimento de uma única chave de atributo de busca no início | -| Tamanho do valor de atributo de busca | 2 KiB | `server.limits.max_search_attribute_value_bytes` | Cada valor de string (e cada elemento de um valor de array) no início | -| Nome de sinal / atualização / consulta | 256 bytes | `server.limits.max_operation_name_length` | Segmento do caminho da URL para nomes de sinal/atualização/consulta | -| Comprimento de `workflow_id` | 128 caracteres | validador do controlador | ID do workflow em `POST /workflows` | -| `workflow_type` / `task_queue` / `business_key` | 255 caracteres | validador do controlador | Campos de string em `POST /workflows` | -| `request_id` | 255 caracteres | validador do controlador | Token de deduplicação em sinais/atualizações/cancelamento/término | -| `reason` | 1.000 caracteres | validador do controlador | Texto do motivo em cancelamento/término/arquivamento | - -Cada limite pode ser configurado individualmente por variáveis de ambiente `DW_*` (consulte `config/dw-contract.php` para o contrato completo). Definir o valor `0` desativa a verificação daquele limite específico, mas mantém os demais em vigor. - -Os valores configurados atualmente são publicados em `limits` na resposta de `GET /api/cluster/info`, para que clientes possam descobri-los em tempo de execução: - -```json -{ - "limits": { - "max_payload_bytes": 2097152, - "max_memo_bytes": 262144, - "max_search_attributes": 100, - "max_search_attribute_key_length": 128, - "max_search_attribute_value_bytes": 2048, - "max_operation_name_length": 256, - "max_pending_activities": 2000, - "max_pending_children": 2000 - } -} -``` - -Erros de validação são retornados no envelope padrão de erro do plano de controle, com `reason: "validation_failed"` e um mapa `validation_errors` cujas chaves são os campos inválidos (`signal_name`, `update_name`, `query_name`, `search_attributes`, `memo` e assim por diante). Rejeições por tamanho de payload usam `reason: "payload_too_large"` e o código de status `413`. +Os limites HTTP de Server e Cloud são separados destes controles do Laravel embutido. Veja a [referência de requisições do Server](../polyglot/server-config-reference.md#server-request-boundary-limits). ### Tamanho da conclusão de tarefa de workflow {#workflow-task-completion-size} -No Server nativo 3.6.0 e posteriores, uma requisição que conclui uma tarefa de workflow com comandos (`POST /api/worker/workflow-tasks/{id}/complete` e `POST /api/worker/activity-tasks/{id}/continuation/complete`) pode ter até 16 vezes `max_payload_bytes`: 32 MiB com o padrão de 2 MiB. Ela segue `DW_MAX_PAYLOAD_BYTES` e não tem configuração própria. Os argumentos de cada comando continuam respeitando o limite por payload dentro da conclusão. O Server PHP 2.x e versões nativas anteriores limitam uma conclusão a um limite de payload, como qualquer outra requisição. - -Uma conclusão maior é recusada com `413 payload_too_large` e `limit_kind: workflow_task_completion_bytes` antes que algo seja registrado. Reexecutar a tarefa produz os mesmos comandos, então reenviar a conclusão recebe a mesma recusa. O PHP SDK 3.17.0 e posteriores nunca a reenviam: o worker falha a execução uma única vez com um comando `fail_workflow` cuja mensagem começa com `Structural limit exceeded: workflow_task_completion_bytes:` e informa os dois tamanhos, e o Server registra a falha com `failure_category = structural_limit`. Os SDKs Python e Rust farão o mesmo nas próximas versões. - -Para manter uma conclusão dentro do limite: - -- Divida um fan-out grande em lotes menores distribuídos entre tarefas de workflow. -- Mova trabalho para workflows filhos, ou use continue-as-new. -- Guarde argumentos grandes no armazenamento externo de payloads, para que a conclusão leve referências em vez dos payloads. +Os limites de conclusão e o tratamento de recusas pelos SDKs no modo de serviço estão na [referência do Server](../polyglot/server-config-reference.md#workflow-task-completion-size). diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md b/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md index 7a7c4e860ee..90479a51a4c 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md @@ -229,6 +229,7 @@ runtime, não no arquivo de perfil. | `dw workflow:signal ` | Envia um sinal. | `--run-id`, opções de entrada, `--json` | | `dw workflow:query ` | Executa consulta de workflow somente leitura. | `--run-id`, opções de entrada, `--json` | | `dw workflow:update ` | Envia ou executa uma atualização. | `--wait=accepted\|completed`, `--run-id`, opções de entrada, `--json` | +| `dw workflow:update-outcome ` | Ler o resultado retido de uma atualização sem enviá-la novamente. | `--wait=accepted\|completed`, `--wait-timeout`, `--json` | | `dw workflow:cancel [workflow-id]` | Fecha um workflow ou lote selecionado como cancelado; não executa limpeza no código do workflow. | `--reason`, `--run-id`, `--all-matching`, `--type`, `--status`, `--limit`, `--yes`, `--json` | | `dw workflow:terminate ` | Força a terminação de um workflow. | `--reason`, `--run-id`, `--json` | | `dw workflow:repair ` | Pede ao servidor para reparar uma execução presa ou retentável. | `--json` | @@ -253,6 +254,29 @@ dw workflow:cancel --all-matching='WorkflowType = "ImportJob"' --limit=25 --yes validam campos canônicos pelo contrato de requisições publicado pelo servidor. Aliases legados não canônicos são rejeitados antes de enviar a requisição. +### Ler o resultado de uma atualização {#read-update-outcome} + +A CLI 2.8 e versões posteriores podem ler uma atualização aceita pelo seu +`update_id` quando o Server anuncia `capabilities.update_outcome_reads` +(nativo 3.6.0 ou posterior). Use o ID do recibo de aceitação: + +```bash +dw workflow:update-outcome order-123 "$UPDATE_ID" +dw workflow:update-outcome order-123 "$UPDATE_ID" --wait=completed --wait-timeout=30 +``` + +O padrão `--wait=accepted` responde imediatamente. Uma atualização aceita que +ainda não terminou continua pendente, inclusive quando a espera expira. Uma +atualização concluída pode ter um resultado null. `--json` retorna o recibo +validado. Use seu `update_status` para distinguir esses casos. Cada invocação +faz uma leitura do resultado e nunca envia a atualização novamente. + +`--wait-timeout` exige `--wait=completed` e um inteiro de pelo menos um segundo. +Uma atualização que falhou sai com código 2. Um ID desconhecido ou removido sai +com 5, o que não prova que a atualização nunca foi aceita. Um Server sem a +capacidade, incluindo PHP Server 2.x, sai com 8 antes de enviar uma requisição +de resultado. + ## Inspeção de chamadas de serviço {#service-call-inspection} Use `dw service-call:describe ` para diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/cli.mdx b/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/cli.mdx index 88c889cf29b..cd8033d3bff 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/cli.mdx +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/cli.mdx @@ -282,6 +282,11 @@ Todo comando que aceita payloads do chamador usa o mesmo formato de entrada: `-` para stdin e `--input-encoding=json|raw|base64`. JSON é o padrão; entradas raw e base64 são passadas como um argumento posicional do workflow. +Use `dw workflow:update-outcome` para ler mais tarde uma atualização aceita +sem enviá-la novamente. Pendente é diferente de concluída com resultado null. +Veja [ler o resultado de uma atualização](./cli-reference.md#read-update-outcome) +para a capacidade exigida do Server e as opções de espera. + ### Adaptadores de ponte {#bridge-adapters} ```bash diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/python.md b/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/python.md index cf4f4249c29..9b303713eef 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/python.md +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/python.md @@ -122,6 +122,16 @@ O SDK Python 2.15 e 2.16 adicionam: Veja o [changelog da 2.16.0](https://github.com/durable-workflow/sdk-python/blob/2.16.0/CHANGELOG.md) para a lista completa. +O Python SDK 2.17 adiciona `Client.update_outcome` e +`Client.update_outcome_receipt` para ler mais tarde uma atualização aceita sem +enviá-la novamente. Esses métodos exigem `capabilities.update_outcome_reads` +(Server nativo 3.6.0 ou posterior). `update_outcome` espera a conclusão por +padrão e lança `UpdateStillPending` se a atualização ainda não terminou. Um +`None` retornado é um resultado null concluído. `update_outcome_receipt` usa +por padrão a etapa de aceitação e preserva o `update_status` explícito. Veja o +[guia do SDK de Python](https://python.durable-workflow.com/reference/client/#read-an-update-outcome) +para exemplos específicos da linguagem. + ## Início rápido {#quickstart} Este é um programa Python completo que define um workflow com uma atividade, @@ -408,13 +418,20 @@ o procedimento completo; os equivalentes CLI são `dw task-queue:build-ids`, | `await client.export_history(workflow_id, run_id)` | payload de histórico de arquivo decodificado | `WorkflowNotFound`, erros de autenticação/servidor | | `await client.signal_workflow(workflow_id, signal_name, args=None)` | `None` | `WorkflowNotFound`, `InvalidArgument`, erros de autenticação/servidor | | `await client.query_workflow(workflow_id, query_name, args=None)` | resultado de consulta decodificado | `QueryFailed`, `WorkflowNotFound`, erros de autenticação/servidor | -| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | resultado de atualização decodificado | `UpdateRejected`, `WorkflowNotFound`, erros de autenticação/servidor | +| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | recibo de atualização (`dict`) | `UpdateRejected`, `UpdateValidationFailed`, `UpdateFailed`, `WorkflowNotFound`, erros de autenticação/servidor | | `await client.cancel_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, erros de autenticação/servidor | | `await client.terminate_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, erros de autenticação/servidor | | `await client.repair_workflow(workflow_id)` | `WorkflowCommandResult` | `WorkflowNotFound`, erros de autenticação/servidor | | `await client.archive_workflow(workflow_id, reason=None)` | `WorkflowCommandResult` | `WorkflowNotFound`, erros de autenticação/servidor | | `await client.get_result(handle, poll_interval=0.5, timeout=30.0)` | saída decodificada do workflow | `WorkflowFailed`, `WorkflowCancelled`, `WorkflowTerminated`, `TimeoutError` | +`update_workflow` usa `wait_for="accepted"` por padrão. Seu recibo pode conter +`update_status="accepted"` e `result=None`. Com `wait_for="completed"`, +`wait_timeout_seconds` limita a espera. Quando ela expira, o recibo continua +aceito e define `wait_timed_out=True`. Somente `update_status="completed"` +identifica um resultado concluído, inclusive `None`. Guarde `update_id` para +[ler o resultado mais tarde](https://python.durable-workflow.com/reference/client/#read-an-update-outcome). + `start_workflow` aceita `workflow_type`, `task_queue`, `workflow_id` opcional, `input` opcional, `duplicate_policy`, `memo`, `search_attributes`, `business_key`, `execution_timeout_seconds` e `run_timeout_seconds`. Todos os 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 72fb5430a89..34aab6678d6 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 @@ -130,6 +130,21 @@ independentemente. Seus manifestos de protocolo em runtime determinam a compatib Veja o [changelog da 4.13.0](https://github.com/durable-workflow/sdk-rust/blob/4.13.0/CHANGELOG.md). +## Ler resultados retidos de atualizações {#read-update-outcome} + +O Rust SDK 4.15 adiciona `Client::update_outcome` e +`Client::update_outcome_receipt` para ler uma atualização aceita pelo ID sem +enviá-la novamente. Esses métodos exigem `capabilities.update_outcome_reads` +(Server nativo 3.6.0 ou posterior). `update_outcome` retorna +`Error::UpdateStillPending` para uma atualização ainda não concluída. Um +resultado null concluído é `Ok(Value::Null)`. Os recibos preservam o +`update_status` explícito. Veja a [API de Client](https://rust.durable-workflow.com/durable_workflow/struct.Client.html#method.update_outcome) +para a interface de Rust. + +O Rust SDK 4.15.0 ainda aplica o teto comum de payload ao lote inteiro de +comandos. Veja o [limite conhecido do planejador](./server-config-reference.md#rust-completion-planning) +antes de um fan-out grande sem armazenamento externo de payloads. + ## Prazos de espera de condições e atualização de workers {#condition-wait-deadlines} O SDK Rust 4.11.2 mede o timeout de um `wait_condition` fora de um grupo diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md b/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md index 53de435328b..998f5cca0da 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md @@ -262,6 +262,81 @@ Essas opções controlam os limites das requisições e o crescimento limitado. | `DW_MAX_NEXUS_OPERATIONS_PER_CALLER` | `200` | Máximo de operações Nexus retornadas por chamador no histórico antes de exigir paginação. | `WORKFLOW_MAX_NEXUS_OPERATIONS_PER_CALLER` | | `DW_COMPRESSION_ENABLED` | `true` | Ativa a compactação de respostas JSON que ultrapassam o tamanho mínimo. | `WORKFLOW_SERVER_COMPRESSION_ENABLED` | +## Limites na fronteira de requisições do Server {#server-request-boundary-limits} + +Ao usar o servidor independente, um conjunto separado de tetos é aplicado na fronteira de requisições HTTP, antes que uma tarefa de workflow, sinal, atualização ou consulta chegue ao plano de controle. Esses limites falham imediatamente com uma resposta `422 validation_failed` (ou `413 payload_too_large` nas verificações do corpo inteiro), para que clientes saibam o motivo da rejeição sem que o servidor grave qualquer registro no banco de dados. + +| Limite | Padrão | Chave de configuração | O que restringe | +|---|---|---|---| +| Tamanho do corpo | 2 MiB | `server.limits.max_payload_bytes` | Total de bytes do corpo da requisição HTTP, exceto uma conclusão de tarefa de workflow no Server nativo 3.6.0 ou posterior (próxima linha) | +| Tamanho da conclusão de tarefa de workflow | 32 MiB (16 × tamanho do corpo) | derivado de `server.limits.max_payload_bytes` | Server nativo 3.6.0 ou posterior: uma requisição que conclui uma tarefa de workflow com comandos. Os argumentos de cada comando continuam respeitando o limite por payload | +| Tamanho do memo | 256 KiB | `server.limits.max_memo_bytes` | Memo serializado em `POST /workflows` e `POST /schedules` | +| Contagem de atributos de busca | 100 | `server.limits.max_search_attributes` | Atributos de busca personalizados registrados por namespace | +| Comprimento da chave de atributo de busca | 128 bytes | `server.limits.max_search_attribute_key_length` | Comprimento de uma única chave de atributo de busca no início | +| Tamanho do valor de atributo de busca | 2 KiB | `server.limits.max_search_attribute_value_bytes` | Cada valor de string (e cada elemento de um valor de array) no início | +| Nome de sinal / atualização / consulta | 256 bytes | `server.limits.max_operation_name_length` | Segmento do caminho da URL para nomes de sinal/atualização/consulta | +| Comprimento de `workflow_id` | 128 caracteres | validador do controlador | ID do workflow em `POST /workflows` | +| `workflow_type` / `task_queue` / `business_key` | 255 caracteres | validador do controlador | Campos de string em `POST /workflows` | +| `request_id` | 255 caracteres | validador do controlador | Token de deduplicação em sinais/atualizações/cancelamento/término | +| `reason` | 1.000 caracteres | validador do controlador | Texto do motivo em cancelamento/término/arquivamento | + +Use as opções `DW_*` documentadas para os limites configuráveis do PHP +Server 2.x. Os limites de validação do controlador são fixos. O Native Server +3.x aceita as opções de suas [notas de implementação](#native-server-3x). +No native 3.8.0, `DW_MAX_PAYLOAD_BYTES=0` define um teto de zero bytes para +requisições comuns e conclusões de tarefas de workflow, recusando corpos não +vazios. O teto para nomes de operações é fixo em 256 bytes. + +Os valores configurados atualmente são publicados em `limits` na resposta de `GET /api/cluster/info`, para que clientes possam descobri-los em tempo de execução: + +```json +{ + "limits": { + "max_payload_bytes": 2097152, + "max_memo_bytes": 262144, + "max_search_attributes": 100, + "max_search_attribute_key_length": 128, + "max_search_attribute_value_bytes": 2048, + "max_operation_name_length": 256, + "max_pending_activities": 2000, + "max_pending_children": 2000 + } +} +``` + +Erros de validação são retornados no envelope padrão de erro do plano de controle, com `reason: "validation_failed"` e um mapa `validation_errors` cujas chaves são os campos inválidos (`signal_name`, `update_name`, `query_name`, `search_attributes`, `memo` e assim por diante). Rejeições por tamanho de payload usam `reason: "payload_too_large"` e o código de status `413`. + +### Tamanho da conclusão de tarefa de workflow {#workflow-task-completion-size} + +No Server nativo 3.6.0 e posteriores, uma requisição que conclui uma tarefa de workflow com comandos (`POST /api/worker/workflow-tasks/{id}/complete` e `POST /api/worker/activity-tasks/{id}/continuation/complete`) pode ter até 16 vezes `max_payload_bytes`: 32 MiB com o padrão de 2 MiB. Ela segue `DW_MAX_PAYLOAD_BYTES` e não tem configuração própria. Os argumentos de cada comando continuam respeitando o limite por payload dentro da conclusão. O Server PHP 2.x e versões nativas anteriores limitam uma conclusão a um limite de payload, como qualquer outra requisição. + +Uma conclusão maior é recusada com `413 payload_too_large` e `limit_kind: workflow_task_completion_bytes` antes que algo seja registrado. Reexecutar a tarefa produz os mesmos comandos, então reenviar a conclusão recebe a mesma recusa. Quando o PHP SDK 3.17.0 ou posterior recebe essa recusa tipada, não reenvia a conclusão: o worker falha a execução uma única vez com um comando `fail_workflow` cuja mensagem começa com `Structural limit exceeded: workflow_task_completion_bytes:` e informa os dois tamanhos, e o Server registra a falha com `failure_category = structural_limit`. + +O Python SDK 2.17 e o Rust SDK 4.15 tratam a recusa tipada. No Server 3.8.0, +uma conclusão grande demais pode falhar no transporte antes que o worker +receba HTTP 413. No teste com o SDK de Python publicado, `httpx.ReadError` +deixou o workflow pendente em vez de falhar por um limite estrutural. A +aceitação de requisições acima do limite no Server publicado continua aberta +na [correção da resposta do Server](https://github.com/durable-workflow/.github/issues/228#issuecomment-6848969678). +Reduza as conclusões até que esse caminho seja qualificado. + +Para manter uma conclusão dentro do limite: + +- Divida um fan-out grande em lotes menores distribuídos entre tarefas de workflow. +- Mova trabalho para workflows filhos, ou use continue-as-new. +- Guarde argumentos grandes no armazenamento externo de payloads, para que a conclusão leve referências em vez dos payloads. + +#### Planejamento de comandos em Rust {#rust-completion-planning} + +O Rust SDK 4.15.0 ainda usa o limite comum por payload como teto agregado do +planejamento de comandos (2 MiB por padrão), antes da capacidade maior de +conclusão do Server. Sem armazenamento externo de payloads no namespace, o +fan-out publicado de 300 × 10 KB é recusado com `external_payload_unavailable`. +O worker encerra e a execução continua pendente. Use lotes menores enquanto a +[correção do planejador agregado do SDK](https://github.com/durable-workflow/sdk-rust/issues/254) +estiver pendente. Esse caminho do SDK ainda não implementa a capacidade maior +do Server. + ## Inicialização do Docker e procedência {#docker-bootstrap-and-provenance} | Variável | Valor padrão | Finalidade | Alias antigo | diff --git a/i18n/pt-BR/source-hashes.json b/i18n/pt-BR/source-hashes.json index 4ec35cae6fb..ca19adf3f36 100644 --- a/i18n/pt-BR/source-hashes.json +++ b/i18n/pt-BR/source-hashes.json @@ -17,7 +17,7 @@ "constraints/execution-guarantees.md": "c24aaff70bfcf50366459ec698ced67adff1e02c1b0ca23c8178a13873037f5a", "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", - "constraints/structural-limits.md": "ad498fae9ec7722aaca2990635027a4f52b4ac6dbd4b145c1aba1a03c6000b1b", + "constraints/structural-limits.md": "b9c2d515fce3b56a03ac654dab65edbe67e13903386412dba8aa1ea77a1d9657", "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", @@ -70,8 +70,8 @@ "polyglot/avro-value-protocol.md": "602e66c6288c1dd69d2b400c64e4739ad3a0493b5be269cee40f7848b11f260a", "polyglot/cancellation.md": "f676cd3ddb39246a0f580a1e16c83bc36d2ed9458b9e6009af4cc192d299ac62", "polyglot/cli-python-parity.md": "acf1acbf15ca9cdf069154699c5fbf8c1d1fd3241a32d201ac10b8ec76c038be", - "polyglot/cli-reference.md": "dc3802b01887f01e702b7989b54c06ba98e8e19326c17db7b32af4e5230e76ee", - "polyglot/cli.mdx": "5b4fdd5c283b3f45691324433d96e6c84e2e898d58fbb7536992ca1dc4503d54", + "polyglot/cli-reference.md": "665c65192f9bfd41610f2aca54a66c2a3aa125e2d2b637d744d9c5f4243bee24", + "polyglot/cli.mdx": "9dac7bb6b711737c9f16916ef462d85c642539f4b6e4a1bdac59320a09632c1f", "polyglot/cloud-control-plane.md": "bb375e598dd1afa3207171047fb81b0cb82c382ce535ab415cb09dc10f6d748e", "polyglot/database-support.md": "518f679ae723ae4d39db7cac78008bc8edb84a6cfba2e6c668d8f2be5d378d03", "polyglot/deployment-modes.md": "7b508db4be86c92de76cfd8dfd946d93941c8a6f0a601a161d4d3fd1711bf97f", @@ -84,12 +84,12 @@ "polyglot/polling-patterns.md": "30875099a23731c6c471b481a771378acc6ff57eed2fda4405a509057534c989", "polyglot/portable-worker-affinity.md": "40973c6a31a76845b4f95e9a505e68ad76abd5174bbdccf37993cdebc8904959", "polyglot/prerelease-history-migration.md": "a57f05f492228a8a67791f9152648a1e5f80856325b78777cf63b6ef49b7413c", - "polyglot/python.md": "1229182acdbe6ddf7f4d875a28c7db67c83931e4055b137b8ce35d4775e3a7b1", + "polyglot/python.md": "7e31563bf15d1f7f1bd1647b70644ef5e72b2c912c566e72e9b1cc4a7fe19d89", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "e9ebec32026199c861409f6fbba0a45f2e360638a68ac75387ad09fd09c6a420", + "polyglot/rust.md": "e768d43c38be76b22440910aa97d61897b392321f106dd2fe7461399a13a99c9", "polyglot/server-api-reference.md": "8bac825f11f7aa3f2a335cf3d1dcdc951219f11d6702e9fe3502d3803fd1e2a5", - "polyglot/server-config-reference.md": "02da3d03e49af3171de9268033c01273cb28fc7eaac665fcaa8aff1252be9055", + "polyglot/server-config-reference.md": "636e4aa05bcc56569a3d001bc80ad2853f95372b051aebcf2bdd0061d2e50b6b", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "2c03845c0979f62bc7ab3208cf09820844b224e548f10fb7d1656852e3428445", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/constraints/structural-limits.md b/i18n/uk/docusaurus-plugin-content-docs/current/constraints/structural-limits.md index f92050fa6b8..4b3e928c4b5 100644 --- a/i18n/uk/docusaurus-plugin-content-docs/current/constraints/structural-limits.md +++ b/i18n/uk/docusaurus-plugin-content-docs/current/constraints/structural-limits.md @@ -318,64 +318,10 @@ Waterline показує помилки структурних обмежень `structural_limit`. Деталі помилки на часовій шкалі містять вид обмеження, поточне значення та налаштовану верхню межу. -## Обмеження на межі запиту Server {#server-request-boundary-limits} - -Під час використання окремого Server інший набір меж застосовується на межі -HTTP-запиту до того, як завдання workflow, signal, update чи query потрапляє -до площини керування. Ці межі одразу повертають `422 validation_failed` або -`413 payload_too_large` для перевірки всього тіла. Клієнти дізнаються причину -відхилення без запису сервером будь-якого рядка до бази даних. - -| Обмеження | Типове значення | Ключ налаштування | Що обмежує | -|---|---|---|---| -| Розмір тіла | 2 MiB | `server.limits.max_payload_bytes` | Загальна кількість байтів тіла HTTP-запиту, крім завершення завдання workflow у нативному Server 3.6.0 або новішому (наступний рядок) | -| Розмір завершення завдання workflow | 32 MiB (16 × розмір тіла) | похідне від `server.limits.max_payload_bytes` | Нативний Server 3.6.0 або новіший: запит, що завершує завдання workflow з командами. Аргументи кожної команди й далі мають вкладатися в ліміт на один payload | -| Розмір memo | 256 KiB | `server.limits.max_memo_bytes` | Серіалізоване memo в `POST /workflows` та `POST /schedules` | -| Кількість атрибутів пошуку | 100 | `server.limits.max_search_attributes` | Зареєстровані власні атрибути пошуку на простір імен | -| Довжина ключа атрибута пошуку | 128 байтів | `server.limits.max_search_attribute_key_length` | Довжина одного ключа атрибута пошуку під час запуску | -| Розмір значення атрибута пошуку | 2 KiB | `server.limits.max_search_attribute_value_bytes` | Кожне рядкове значення та кожен елемент масиву під час запуску | -| Назва signal / update / query | 256 байтів | `server.limits.max_operation_name_length` | Сегмент шляху URL для назв signal/update/query | -| Довжина `workflow_id` | 128 символів | валідатор контролера | ID workflow в `POST /workflows` | -| `workflow_type` / `task_queue` / `business_key` | 255 символів | валідатор контролера | Рядкові поля в `POST /workflows` | -| `request_id` | 255 символів | валідатор контролера | Токен усунення дублікатів для signal/update/cancel/terminate | -| `reason` | 1,000 символів | валідатор контролера | Текст причини для cancel/terminate/archive | - -Кожна межа окремо налаштовується через змінні середовища `DW_*`. Повний контракт -наведено в `config/dw-contract.php`. Значення `0` вимикає перевірку конкретної -межі, залишаючи решту чинними. - -Поточні значення публікуються під `limits` у відповіді `GET /api/cluster/info`, -тому клієнти можуть дізнатися їх під час виконання: +## Обмеження Service Mode {#server-request-boundary-limits} -```json -{ - "limits": { - "max_payload_bytes": 2097152, - "max_memo_bytes": 262144, - "max_search_attributes": 100, - "max_search_attribute_key_length": 128, - "max_search_attribute_value_bytes": 2048, - "max_operation_name_length": 256, - "max_pending_activities": 2000, - "max_pending_children": 2000 - } -} -``` - -Помилки валідації повертаються в стандартній оболонці помилок площини керування -з `reason: "validation_failed"` та мапою `validation_errors`, ключами якої є -проблемні поля (`signal_name`, `update_name`, `query_name`, `search_attributes`, -`memo` тощо). Відхилення через розмір даних використовують -`reason: "payload_too_large"` та код стану `413`. +HTTP-обмеження Server і Cloud відрізняються від цих вбудованих обмежень Laravel. Див. [довідник запитів Server](../polyglot/server-config-reference.md#server-request-boundary-limits). ### Розмір завершення завдання workflow {#workflow-task-completion-size} -У нативному Server 3.6.0 і новіших запит, що завершує завдання workflow з командами (`POST /api/worker/workflow-tasks/{id}/complete` і `POST /api/worker/activity-tasks/{id}/continuation/complete`), може мати розмір до 16 × `max_payload_bytes`: 32 MiB за типового значення 2 MiB. Ліміт іде за `DW_MAX_PAYLOAD_BYTES` і не має власного параметра. Аргументи кожної команди всередині завершення й далі мають вкладатися в ліміт на один payload. PHP Server 2.x і попередні нативні випуски обмежують завершення одним лімітом payload, як і будь-який інший запит. - -Більше завершення відхиляється з `413 payload_too_large` і `limit_kind: workflow_task_completion_bytes` ще до того, як щось буде записано. Повторне відтворення завдання дає ті самі команди, тож повторне надсилання завершення отримає ту саму відмову. PHP SDK 3.17.0 і новіші ніколи не надсилають його повторно: worker один раз завершує запуск помилкою через команду `fail_workflow`, повідомлення якої починається з `Structural limit exceeded: workflow_task_completion_bytes:` і називає обидва розміри, а Server записує помилку з `failure_category = structural_limit`. SDK для Python і Rust робитимуть те саме в наступних випусках. - -Щоб завершення вкладалося в ліміт: - -- Розділіть великий fan-out на менші пакети в кількох завданнях workflow. -- Перенесіть роботу в дочірні workflow або використайте continue-as-new. -- Зберігайте великі аргументи в зовнішньому сховищі payload, щоб завершення містило посилання замість самих payload. +Обмеження запитів завершення та обробка відмов SDK у Service Mode описані в [довіднику Server](../polyglot/server-config-reference.md#workflow-task-completion-size). diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md b/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md index ae38899050e..cc150a984b0 100644 --- a/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md +++ b/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md @@ -228,6 +228,7 @@ JSON містить стабільне поле `status` для автомати | `dw workflow:signal ` | Надіслати signal. | `--run-id`, параметри вводу, `--json` | | `dw workflow:query ` | Виконати query workflow лише для читання. | `--run-id`, параметри вводу, `--json` | | `dw workflow:update ` | Подати чи виконати update workflow. | `--wait=accepted\|completed`, `--run-id`, параметри вводу, `--json` | +| `dw workflow:update-outcome ` | Прочитати збережений результат update без повторного надсилання. | `--wait=accepted\|completed`, `--wait-timeout`, `--json` | | `dw workflow:cancel [workflow-id]` | Закрити один workflow чи вибрану групу як скасовані без очищення в коді workflow. | `--reason`, `--run-id`, `--all-matching`, `--type`, `--status`, `--limit`, `--yes`, `--json` | | `dw workflow:terminate ` | Примусово завершити workflow. | `--reason`, `--run-id`, `--json` | | `dw workflow:repair ` | Попросити сервер відновити застрягле виконання чи виконання, що допускає повторну спробу. | `--json` | @@ -252,6 +253,29 @@ dw workflow:cancel --all-matching='WorkflowType = "ImportJob"' --limit=25 --yes перевіряють канонічні поля запиту за контрактом, опублікованим сервером. Неканонічні застарілі псевдоніми відхиляються до надсилання запиту. +### Прочитати результат update {#read-update-outcome} + +CLI 2.8 і новіші версії можуть читати прийнятий update за його `update_id`, +якщо Server оголошує `capabilities.update_outcome_reads` (native 3.6.0 або +новіший). Використайте ID із підтвердження прийняття: + +```bash +dw workflow:update-outcome order-123 "$UPDATE_ID" +dw workflow:update-outcome order-123 "$UPDATE_ID" --wait=completed --wait-timeout=30 +``` + +Типове значення `--wait=accepted` повертає відповідь одразу. Прийнятий update, +який ще не завершився, залишається в очікуванні, зокрема після завершення часу +очікування. Завершений update може мати результат null. `--json` повертає +перевірене підтвердження. Розрізняйте ці випадки за `update_status`. Кожен +виклик читає результат один раз і ніколи не надсилає update повторно. + +`--wait-timeout` потребує `--wait=completed` і цілого числа не менше однієї +секунди. Невдалий update завершується з кодом 2. Невідомий або видалений ID +update дає код 5, що не доводить, ніби update ніколи не приймався. Server без +цієї можливості, зокрема PHP Server 2.x, дає код 8 до надсилання запиту +результату. + ## Перегляд викликів сервісів {#service-call-inspection} Використовуйте `dw service-call:describe ` diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/cli.mdx b/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/cli.mdx index 8ed11ccb8bf..dbc066e9226 100644 --- a/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/cli.mdx +++ b/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/cli.mdx @@ -285,6 +285,11 @@ dw workflow:history # Show run history Стандартно JSON. Raw та base64 input передаються як один позиційний аргумент workflow. +Використовуйте `dw workflow:update-outcome`, щоб пізніше прочитати прийнятий +update без повторного надсилання. Очікування відрізняється від завершення з +результатом null. Див. [читання результату update](./cli-reference.md#read-update-outcome) +щодо потрібної можливості Server і параметрів очікування. + ### Адаптери інтеграцій {#bridge-adapters} ```bash diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/python.md b/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/python.md index 4fefd2c31e4..c744e03cdaa 100644 --- a/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/python.md +++ b/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/python.md @@ -120,6 +120,15 @@ Python SDK 2.15 і 2.16 додають: Повний перелік див. у [журналі змін 2.16.0](https://github.com/durable-workflow/sdk-python/blob/2.16.0/CHANGELOG.md). +Python SDK 2.17 додає `Client.update_outcome` і +`Client.update_outcome_receipt`, щоб читати прийнятий update пізніше без +повторного надсилання. Ці методи потребують `capabilities.update_outcome_reads` +(native Server 3.6.0 або новіший). `update_outcome` за замовчуванням чекає +завершення й піднімає `UpdateStillPending`, якщо update ще не завершився. +Повернене `None` є завершеним результатом null. `update_outcome_receipt` за +замовчуванням використовує етап прийняття й зберігає явний `update_status`. +Приклади для цієї мови наведено в [посібнику Python SDK](https://python.durable-workflow.com/reference/client/#read-an-update-outcome). + ## Швидкий початок {#quickstart} Ця повна програма Python визначає workflow з однією activity, @@ -403,13 +412,21 @@ Namespace є межею орендарів workflow, schedule, атрибуті | `await client.export_history(workflow_id, run_id)` | декодований архівний payload історії | `WorkflowNotFound`, помилки автентифікації/Server | | `await client.signal_workflow(workflow_id, signal_name, args=None)` | `None` | `WorkflowNotFound`, `InvalidArgument`, помилки автентифікації/Server | | `await client.query_workflow(workflow_id, query_name, args=None)` | декодований результат query | `QueryFailed`, `WorkflowNotFound`, помилки автентифікації/Server | -| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | декодований результат update | `UpdateRejected`, `WorkflowNotFound`, помилки автентифікації/Server | +| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | підтвердження update (`dict`) | `UpdateRejected`, `UpdateValidationFailed`, `UpdateFailed`, `WorkflowNotFound`, помилки автентифікації/Server | | `await client.cancel_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, помилки автентифікації/Server | | `await client.terminate_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, помилки автентифікації/Server | | `await client.repair_workflow(workflow_id)` | `WorkflowCommandResult` | `WorkflowNotFound`, помилки автентифікації/Server | | `await client.archive_workflow(workflow_id, reason=None)` | `WorkflowCommandResult` | `WorkflowNotFound`, помилки автентифікації/Server | | `await client.get_result(handle, poll_interval=0.5, timeout=30.0)` | декодований результат workflow | `WorkflowFailed`, `WorkflowCancelled`, `WorkflowTerminated`, `TimeoutError` | +`update_workflow` за замовчуванням використовує `wait_for="accepted"`. +Підтвердження може містити `update_status="accepted"` і `result=None`. З +`wait_for="completed"` параметр `wait_timeout_seconds` обмежує час очікування. +Після його спливу підтвердження залишається прийнятим і встановлює +`wait_timed_out=True`. Лише `update_status="completed"` означає завершений +результат, зокрема `None`. Збережіть `update_id`, щоб +[прочитати результат пізніше](https://python.durable-workflow.com/reference/client/#read-an-update-outcome). + `start_workflow` приймає `workflow_type`, `task_queue`, необов'язкові `workflow_id`, `input`, `duplicate_policy`, `memo`, `search_attributes`, `business_key`, `execution_timeout_seconds`, `run_timeout_seconds`. 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 3453963e89b..4409fa03654 100644 --- a/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/rust.md +++ b/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/rust.md @@ -131,6 +131,20 @@ Rust SDK 3.5.0 за замовчуванням надсилає Див. [журнал змін 4.13.0](https://github.com/durable-workflow/sdk-rust/blob/4.13.0/CHANGELOG.md). +## Читати збережені результати update {#read-update-outcome} + +Rust SDK 4.15 додає `Client::update_outcome` і +`Client::update_outcome_receipt`, щоб читати прийнятий update за ID без +повторного надсилання. Ці методи потребують `capabilities.update_outcome_reads` +(native Server 3.6.0 або новіший). `update_outcome` повертає +`Error::UpdateStillPending`, якщо update ще не завершився. Завершений результат +null має вигляд `Ok(Value::Null)`. Підтвердження зберігають явний `update_status`. +Інтерфейс Rust описано в [API Client](https://rust.durable-workflow.com/durable_workflow/struct.Client.html#method.update_outcome). + +Rust SDK 4.15.0 ще застосовує звичайну межу payload до всього пакета команд. +Див. [відоме обмеження планувальника](./server-config-reference.md#rust-completion-planning) +перед великим fan-out без зовнішнього сховища payload. + ## Строки очікування умови та оновлення worker {#condition-wait-deadlines} Rust SDK 4.11.2 відлічує тайм-аут для `wait_condition` поза групою від першого diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md b/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md index e36e49e4b91..d8c289346ca 100644 --- a/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md +++ b/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md @@ -353,6 +353,89 @@ Sticky execution не має окремих змінних середовища | `DW_MAX_NEXUS_OPERATIONS_PER_CALLER` | `200` | Максимальна кількість Nexus operations на ініціатора в історії операцій перед обов'язковою пагінацією клієнта. | `WORKFLOW_MAX_NEXUS_OPERATIONS_PER_CALLER` | | `DW_COMPRESSION_ENABLED` | `true` | Увімкнення стиснення JSON-відповіді після перевищення мінімального порогу розміру. | `WORKFLOW_SERVER_COMPRESSION_ENABLED` | +## Обмеження на межі запиту Server {#server-request-boundary-limits} + +Під час використання окремого Server інший набір меж застосовується на межі +HTTP-запиту до того, як завдання workflow, signal, update чи query потрапляє +до площини керування. Ці межі одразу повертають `422 validation_failed` або +`413 payload_too_large` для перевірки всього тіла. Клієнти дізнаються причину +відхилення без запису сервером будь-якого рядка до бази даних. + +| Обмеження | Типове значення | Ключ налаштування | Що обмежує | +|---|---|---|---| +| Розмір тіла | 2 MiB | `server.limits.max_payload_bytes` | Загальна кількість байтів тіла HTTP-запиту, крім завершення завдання workflow у нативному Server 3.6.0 або новішому (наступний рядок) | +| Розмір завершення завдання workflow | 32 MiB (16 × розмір тіла) | похідне від `server.limits.max_payload_bytes` | Нативний Server 3.6.0 або новіший: запит, що завершує завдання workflow з командами. Аргументи кожної команди й далі мають вкладатися в ліміт на один payload | +| Розмір memo | 256 KiB | `server.limits.max_memo_bytes` | Серіалізоване memo в `POST /workflows` та `POST /schedules` | +| Кількість атрибутів пошуку | 100 | `server.limits.max_search_attributes` | Зареєстровані власні атрибути пошуку на простір імен | +| Довжина ключа атрибута пошуку | 128 байтів | `server.limits.max_search_attribute_key_length` | Довжина одного ключа атрибута пошуку під час запуску | +| Розмір значення атрибута пошуку | 2 KiB | `server.limits.max_search_attribute_value_bytes` | Кожне рядкове значення та кожен елемент масиву під час запуску | +| Назва signal / update / query | 256 байтів | `server.limits.max_operation_name_length` | Сегмент шляху URL для назв signal/update/query | +| Довжина `workflow_id` | 128 символів | валідатор контролера | ID workflow в `POST /workflows` | +| `workflow_type` / `task_queue` / `business_key` | 255 символів | валідатор контролера | Рядкові поля в `POST /workflows` | +| `request_id` | 255 символів | валідатор контролера | Токен усунення дублікатів для signal/update/cancel/terminate | +| `reason` | 1,000 символів | валідатор контролера | Текст причини для cancel/terminate/archive | + +Використовуйте задокументовані параметри `DW_*` для налаштовуваних обмежень +PHP Server 2.x. Межі перевірок контролера фіксовані. Native Server 3.x підтримує +параметри зі своїх [приміток щодо реалізації](#native-server-3x). У native 3.8.0 +`DW_MAX_PAYLOAD_BYTES=0` задає нульову межу байтів для звичайних запитів і +завершень workflow task, тому непорожні тіла відхиляються. Межа назв операцій +фіксована й становить 256 байтів. + +Поточні значення публікуються під `limits` у відповіді `GET /api/cluster/info`, +тому клієнти можуть дізнатися їх під час виконання: + +```json +{ + "limits": { + "max_payload_bytes": 2097152, + "max_memo_bytes": 262144, + "max_search_attributes": 100, + "max_search_attribute_key_length": 128, + "max_search_attribute_value_bytes": 2048, + "max_operation_name_length": 256, + "max_pending_activities": 2000, + "max_pending_children": 2000 + } +} +``` + +Помилки валідації повертаються в стандартній оболонці помилок площини керування +з `reason: "validation_failed"` та мапою `validation_errors`, ключами якої є +проблемні поля (`signal_name`, `update_name`, `query_name`, `search_attributes`, +`memo` тощо). Відхилення через розмір даних використовують +`reason: "payload_too_large"` та код стану `413`. + +### Розмір завершення завдання workflow {#workflow-task-completion-size} + +У нативному Server 3.6.0 і новіших запит, що завершує завдання workflow з командами (`POST /api/worker/workflow-tasks/{id}/complete` і `POST /api/worker/activity-tasks/{id}/continuation/complete`), може мати розмір до 16 × `max_payload_bytes`: 32 MiB за типового значення 2 MiB. Ліміт іде за `DW_MAX_PAYLOAD_BYTES` і не має власного параметра. Аргументи кожної команди всередині завершення й далі мають вкладатися в ліміт на один payload. PHP Server 2.x і попередні нативні випуски обмежують завершення одним лімітом payload, як і будь-який інший запит. + +Більше завершення відхиляється з `413 payload_too_large` і `limit_kind: workflow_task_completion_bytes` ще до того, як щось буде записано. Повторне відтворення завдання дає ті самі команди, тож повторне надсилання завершення отримає ту саму відмову. Коли PHP SDK 3.17.0 або новіший отримує цю типізовану відмову, він не надсилає запит завершення повторно: worker один раз завершує запуск помилкою через команду `fail_workflow`, повідомлення якої починається з `Structural limit exceeded: workflow_task_completion_bytes:` і називає обидва розміри, а Server записує помилку з `failure_category = structural_limit`. + +Python SDK 2.17 і Rust SDK 4.15 обробляють типізовану відмову. На Server +3.8.0 завеликий запит завершення може дати збій транспорту до отримання worker +відповіді HTTP 413. У тесті з опублікованим Python SDK помилка +`httpx.ReadError` залишила workflow в очікуванні замість структурної помилки. +Перевірка завеликих запитів на опублікованому Server ще не завершена в межах +[виправлення відповіді Server](https://github.com/durable-workflow/.github/issues/228#issuecomment-6848969678). +Зменшуйте запити завершення, доки цей шлях не пройде кваліфікацію. + +Щоб завершення вкладалося в ліміт: + +- Розділіть великий fan-out на менші пакети в кількох завданнях workflow. +- Перенесіть роботу в дочірні workflow або використайте continue-as-new. +- Зберігайте великі аргументи в зовнішньому сховищі payload, щоб завершення містило посилання замість самих payload. + +#### Планування команд Rust {#rust-completion-planning} + +Rust SDK 4.15.0 ще використовує звичайне обмеження одного payload як сумарну +межу планування команд (типово 2 MiB), до вищої межі запитів завершення Server. +Без зовнішнього сховища payload у namespace опублікований fan-out із +300 × 10 KB відхиляється з `external_payload_unavailable`. Worker завершує +роботу, а запуск залишається в очікуванні. Використовуйте менші пакети команд, +поки очікується [виправлення сумарного планувальника SDK](https://github.com/durable-workflow/sdk-rust/issues/254). +Цей шлях SDK ще не реалізує вищу межу Server. + ## Docker bootstrap та походження пакета {#docker-bootstrap-and-provenance} | Змінна | Стандартне значення | Призначення | Застарілий alias | diff --git a/i18n/uk/source-hashes.json b/i18n/uk/source-hashes.json index 4ec35cae6fb..ca19adf3f36 100644 --- a/i18n/uk/source-hashes.json +++ b/i18n/uk/source-hashes.json @@ -17,7 +17,7 @@ "constraints/execution-guarantees.md": "c24aaff70bfcf50366459ec698ced67adff1e02c1b0ca23c8178a13873037f5a", "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", - "constraints/structural-limits.md": "ad498fae9ec7722aaca2990635027a4f52b4ac6dbd4b145c1aba1a03c6000b1b", + "constraints/structural-limits.md": "b9c2d515fce3b56a03ac654dab65edbe67e13903386412dba8aa1ea77a1d9657", "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", @@ -70,8 +70,8 @@ "polyglot/avro-value-protocol.md": "602e66c6288c1dd69d2b400c64e4739ad3a0493b5be269cee40f7848b11f260a", "polyglot/cancellation.md": "f676cd3ddb39246a0f580a1e16c83bc36d2ed9458b9e6009af4cc192d299ac62", "polyglot/cli-python-parity.md": "acf1acbf15ca9cdf069154699c5fbf8c1d1fd3241a32d201ac10b8ec76c038be", - "polyglot/cli-reference.md": "dc3802b01887f01e702b7989b54c06ba98e8e19326c17db7b32af4e5230e76ee", - "polyglot/cli.mdx": "5b4fdd5c283b3f45691324433d96e6c84e2e898d58fbb7536992ca1dc4503d54", + "polyglot/cli-reference.md": "665c65192f9bfd41610f2aca54a66c2a3aa125e2d2b637d744d9c5f4243bee24", + "polyglot/cli.mdx": "9dac7bb6b711737c9f16916ef462d85c642539f4b6e4a1bdac59320a09632c1f", "polyglot/cloud-control-plane.md": "bb375e598dd1afa3207171047fb81b0cb82c382ce535ab415cb09dc10f6d748e", "polyglot/database-support.md": "518f679ae723ae4d39db7cac78008bc8edb84a6cfba2e6c668d8f2be5d378d03", "polyglot/deployment-modes.md": "7b508db4be86c92de76cfd8dfd946d93941c8a6f0a601a161d4d3fd1711bf97f", @@ -84,12 +84,12 @@ "polyglot/polling-patterns.md": "30875099a23731c6c471b481a771378acc6ff57eed2fda4405a509057534c989", "polyglot/portable-worker-affinity.md": "40973c6a31a76845b4f95e9a505e68ad76abd5174bbdccf37993cdebc8904959", "polyglot/prerelease-history-migration.md": "a57f05f492228a8a67791f9152648a1e5f80856325b78777cf63b6ef49b7413c", - "polyglot/python.md": "1229182acdbe6ddf7f4d875a28c7db67c83931e4055b137b8ce35d4775e3a7b1", + "polyglot/python.md": "7e31563bf15d1f7f1bd1647b70644ef5e72b2c912c566e72e9b1cc4a7fe19d89", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "e9ebec32026199c861409f6fbba0a45f2e360638a68ac75387ad09fd09c6a420", + "polyglot/rust.md": "e768d43c38be76b22440910aa97d61897b392321f106dd2fe7461399a13a99c9", "polyglot/server-api-reference.md": "8bac825f11f7aa3f2a335cf3d1dcdc951219f11d6702e9fe3502d3803fd1e2a5", - "polyglot/server-config-reference.md": "02da3d03e49af3171de9268033c01273cb28fc7eaac665fcaa8aff1252be9055", + "polyglot/server-config-reference.md": "636e4aa05bcc56569a3d001bc80ad2853f95372b051aebcf2bdd0061d2e50b6b", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "2c03845c0979f62bc7ab3208cf09820844b224e548f10fb7d1656852e3428445", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", diff --git a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/constraints/structural-limits.md b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/constraints/structural-limits.md index d40705b3bc5..1a99976da98 100644 --- a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/constraints/structural-limits.md +++ b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/constraints/structural-limits.md @@ -246,53 +246,10 @@ v2 健康检查快照的 `structural_limits` 包含当前结构限制配置, Waterline 在异常表中以 `structural_limit` 故障类别展示结构限制故障。时间线的故障详情包括限制类型、当前值和配置的上限。 -## Server 请求边界限制 {#server-request-boundary-limits} +## Service Mode 限制 {#server-request-boundary-limits} -使用独立 Server 时,在工作流任务、信号、更新或查询到达控制平面之前,HTTP 请求边界会应用另一组上限。超限请求会快速返回 `422 validation_failed`(整个请求体检查则返回 `413 payload_too_large`),使客户端获知拒绝原因,而 Server 不会向数据库写入任何行。 - -| 限制 | 默认值 | 配置键 | 约束对象 | -|---|---|---|---| -| 请求体大小 | 2 MiB | `server.limits.max_payload_bytes` | HTTP 请求体的总字节数;原生 Server 3.6.0 及以上的工作流任务完成请求除外(见下一行) | -| 工作流任务完成大小 | 32 MiB(请求体大小的 16 倍) | 由 `server.limits.max_payload_bytes` 推导 | 原生 Server 3.6.0 及以上:带命令完成工作流任务的请求。每个命令的参数仍须符合单个载荷上限 | -| memo 大小 | 256 KiB | `server.limits.max_memo_bytes` | `POST /workflows` 和 `POST /schedules` 中序列化的 memo | -| 搜索属性数量 | 100 | `server.limits.max_search_attributes` | 每个命名空间注册的自定义搜索属性数 | -| 搜索属性键长度 | 128 字节 | `server.limits.max_search_attribute_key_length` | 启动时单个搜索属性键的长度 | -| 搜索属性值大小 | 2 KiB | `server.limits.max_search_attribute_value_bytes` | 启动时的每个字符串值(以及数组值的每个元素) | -| 信号/更新/查询名称 | 256 字节 | `server.limits.max_operation_name_length` | 信号/更新/查询名称的 URL 路径段 | -| `workflow_id` 长度 | 128 字符 | 控制器验证器 | `POST /workflows` 中的工作流 ID | -| `workflow_type` / `task_queue` / `business_key` | 255 字符 | 控制器验证器 | `POST /workflows` 中的字符串字段 | -| `request_id` | 255 字符 | 控制器验证器 | 信号/更新/取消/终止操作的去重令牌 | -| `reason` | 1,000 字符 | 控制器验证器 | 取消/终止/归档操作的原因文本 | - -每个限制均可通过 `DW_*` 环境变量单独配置(完整契约见 `config/dw-contract.php`)。值为 `0` 时,仅禁用该项限制,其他限制仍然生效。 - -当前配置值发布在 `GET /api/cluster/info` 响应的 `limits` 下,客户端可在运行时发现这些限制: - -```json -{ - "limits": { - "max_payload_bytes": 2097152, - "max_memo_bytes": 262144, - "max_search_attributes": 100, - "max_search_attribute_key_length": 128, - "max_search_attribute_value_bytes": 2048, - "max_operation_name_length": 256, - "max_pending_activities": 2000, - "max_pending_children": 2000 - } -} -``` - -验证错误通过标准控制平面错误信封返回,包含 `reason: "validation_failed"` 和以出错字段(`signal_name`、`update_name`、`query_name`、`search_attributes`、`memo` 等)为键的 `validation_errors` 映射。载荷大小超限使用 `reason: "payload_too_large"` 和 `413` 状态码。 +Server 和 Cloud 的 HTTP 请求限制独立于这些嵌入式 Laravel 控制。请参阅 [Server 请求参考](../polyglot/server-config-reference.md#server-request-boundary-limits)。 ### 工作流任务完成大小 {#workflow-task-completion-size} -在原生 Server 3.6.0 及以上,带命令完成工作流任务的请求(`POST /api/worker/workflow-tasks/{id}/complete` 和 `POST /api/worker/activity-tasks/{id}/continuation/complete`)最多可达 `max_payload_bytes` 的 16 倍:默认 2 MiB 时为 32 MiB。该上限跟随 `DW_MAX_PAYLOAD_BYTES`,没有单独的设置。完成请求中每个命令的参数仍须符合单个载荷上限。PHP Server 2.x 和更早的原生版本与其他请求一样,将完成请求限制为一个载荷上限。 - -更大的完成请求会在记录任何内容之前以 `413 payload_too_large` 和 `limit_kind: workflow_task_completion_bytes` 被拒绝。重放该任务会生成相同的命令,因此重新发送完成请求会得到同样的拒绝。PHP SDK 3.17.0 及以上从不重新发送:Worker 用一条 `fail_workflow` 命令让运行失败一次,其消息以 `Structural limit exceeded: workflow_task_completion_bytes:` 开头并给出两个大小,Server 以 `failure_category = structural_limit` 记录该失败。Python 和 Rust SDK 将在下一个版本中采取相同做法。 - -要让完成请求保持在上限之内: - -- 将大型扇出拆分为分布在多个工作流任务中的较小批次。 -- 将工作移到子工作流中,或使用 continue-as-new。 -- 将大型参数存入外部载荷存储,使完成请求携带引用而不是载荷本身。 +Service Mode 的完成请求上限和 SDK 拒绝处理见 [Server 参考](../polyglot/server-config-reference.md#workflow-task-completion-size)。 diff --git a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md index bc4fcce0115..abececbced9 100644 --- a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md +++ b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/cli-reference.md @@ -152,6 +152,7 @@ dw server:info --output=json \ | `dw workflow:signal ` | 发送信号。 | `--run-id`, 输入选项, `--json` | | `dw workflow:query ` | 执行只读工作流查询。 | `--run-id`, 输入选项, `--json` | | `dw workflow:update ` | 提交或执行工作流更新。 | `--wait=accepted\|completed`, `--run-id`, 输入选项, `--json` | +| `dw workflow:update-outcome ` | 读取保留的更新结果,不重新提交更新。 | `--wait=accepted\|completed`, `--wait-timeout`, `--json` | | `dw workflow:cancel [workflow-id]` | 将单个工作流或选定批次关闭为已取消;不运行工作流代码清理。 | `--reason`, `--run-id`, `--all-matching`, `--type`, `--status`, `--limit`, `--yes`, `--json` | | `dw workflow:terminate ` | 强制终止工作流。 | `--reason`, `--run-id`, `--json` | | `dw workflow:repair ` | 请求 Server 修复卡住或可重试运行。 | `--json` | @@ -174,6 +175,19 @@ dw workflow:cancel --all-matching='WorkflowType = "ImportJob"' --limit=25 --yes `workflow:start`、`workflow:signal`、`workflow:query` 和 `workflow:update` 根据 Server 公布的请求契约验证规范请求字段。非规范的旧别名在请求发送前即被拒绝。 +### 读取更新结果 {#read-update-outcome} + +CLI 2.8 及更高版本可以通过 `update_id` 读取已接受的更新,前提是 Server 公布 `capabilities.update_outcome_reads`(native 3.6.0 及更高版本)。请使用接受回执中的 ID: + +```bash +dw workflow:update-outcome order-123 "$UPDATE_ID" +dw workflow:update-outcome order-123 "$UPDATE_ID" --wait=completed --wait-timeout=30 +``` + +默认的 `--wait=accepted` 会立即返回。已接受但尚未完成的更新仍处于待完成状态,完成等待超时后也一样。已完成的更新可以返回 null。`--json` 返回经过校验的回执,请用其中的 `update_status` 区分这些情况。每次调用只读取一次结果,绝不重新提交更新。 + +`--wait-timeout` 要求使用 `--wait=completed`,且值为至少一秒的整数。更新失败时退出码为 2。未知或已清理的更新 ID 对应退出码 5,但这不能证明该更新从未被接受。如果 Server 不支持此能力(包括 PHP Server 2.x),命令会在发送结果请求前以 8 退出。 + ## 服务调用检查 {#service-call-inspection} 用 `dw service-call:describe ` 检查端点命名空间中的一个持久 Nexus 调用。例如,`dw service-call:describe billing invoices create call-42 --namespace=shared --json` 返回完整 Server 响应。 diff --git a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/cli.mdx b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/cli.mdx index 7d23a83af19..fa76683f3a6 100644 --- a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/cli.mdx +++ b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/cli.mdx @@ -226,6 +226,8 @@ dw workflow:history # Show run history 所有接受调用方负载的命令使用同一输入形式:`--input` 传入内联值,`--input-file` 指定文件路径或用 `-` 读取标准输入,`--input-encoding=json|raw|base64` 指定编码。默认 JSON;raw 和 base64 输入作为一个位置工作流参数传入。 +使用 `dw workflow:update-outcome` 可以稍后读取已接受的更新,而不重新提交。待完成与已完成且结果为 null 是不同的状态。所需的 Server 能力和等待选项见[读取更新结果](./cli-reference.md#read-update-outcome)。 + ### 桥接适配器 {#bridge-adapters} ```bash diff --git a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/python.md b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/python.md index 1fe94b55923..11942716ec1 100644 --- a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/python.md +++ b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/python.md @@ -86,6 +86,8 @@ Python SDK 2.15 和 2.16 新增: 完整列表请参见 [2.16.0 变更日志](https://github.com/durable-workflow/sdk-python/blob/2.16.0/CHANGELOG.md)。 +Python SDK 2.17 新增 `Client.update_outcome` 和 `Client.update_outcome_receipt`,用于稍后读取已接受的更新,不重新提交。这些方法要求 `capabilities.update_outcome_reads`(native Server 3.6.0 及更高版本)。`update_outcome` 默认等待完成,如果更新尚未完成则抛出 `UpdateStillPending`。返回的 `None` 表示已完成的 null 结果。`update_outcome_receipt` 默认使用接受阶段,并保留明确的 `update_status`。语言专用示例见 [Python SDK 指南](https://python.durable-workflow.com/reference/client/#read-an-update-outcome)。 + ## 快速入门 {#quickstart} 下面的完整 Python 程序定义带一个活动的工作流,在本地 Durable Workflow Server 上启动并等待结果: @@ -340,13 +342,15 @@ driver = external_storage_driver_from_policy( | `await client.export_history(workflow_id, run_id)` | 已解码归档历史负载 | `WorkflowNotFound`, 认证/Server 错误 | | `await client.signal_workflow(workflow_id, signal_name, args=None)` | `None` | `WorkflowNotFound`, `InvalidArgument`, 认证/Server 错误 | | `await client.query_workflow(workflow_id, query_name, args=None)` | 已解码查询结果 | `QueryFailed`, `WorkflowNotFound`, 认证/Server 错误 | -| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | 已解码更新结果 | `UpdateRejected`, `WorkflowNotFound`, 认证/Server 错误 | +| `await client.update_workflow(workflow_id, update_name, args=None, ...)` | 更新回执(`dict`) | `UpdateRejected`, `UpdateValidationFailed`, `UpdateFailed`, `WorkflowNotFound`, 认证/Server 错误 | | `await client.cancel_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, 认证/Server 错误 | | `await client.terminate_workflow(workflow_id, reason=None)` | `None` | `WorkflowNotFound`, 认证/Server 错误 | | `await client.repair_workflow(workflow_id)` | `WorkflowCommandResult` | `WorkflowNotFound`, 认证/Server 错误 | | `await client.archive_workflow(workflow_id, reason=None)` | `WorkflowCommandResult` | `WorkflowNotFound`, 认证/Server 错误 | | `await client.get_result(handle, poll_interval=0.5, timeout=30.0)` | 已解码工作流输出 | `WorkflowFailed`, `WorkflowCancelled`, `WorkflowTerminated`, `TimeoutError` | +`update_workflow` 默认为 `wait_for="accepted"`。其回执可能包含 `update_status="accepted"` 和 `result=None`。使用 `wait_for="completed"` 时,`wait_timeout_seconds` 限制等待时间。等待到期后,回执仍为已接受,并设置 `wait_timed_out=True`。只有 `update_status="completed"` 才表示结果已完成,包括 `None`。请保留 `update_id`,以便[稍后读取结果](https://python.durable-workflow.com/reference/client/#read-an-update-outcome)。 + `start_workflow` 接受 `workflow_type`、`task_queue`、可选 `workflow_id`、可选 `input`、`duplicate_policy`、`memo`、`search_attributes`、`business_key`、`execution_timeout_seconds` 和 `run_timeout_seconds`。所有调用方负载在越过 HTTP 边界前都进行 Avro 封装。 脚本已知工作流 ID 且需要句柄风格方法时,使用 `client.get_workflow_handle(workflow_id, run_id=None, workflow_type="")`。 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 aebde9b5749..52f56dbf41e 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 @@ -77,6 +77,12 @@ Server 在主版本 `1` 内协商 Worker 协议头:公布 `1.N` 的 Server 仅 参见 [4.13.0 变更日志](https://github.com/durable-workflow/sdk-rust/blob/4.13.0/CHANGELOG.md)。 +## 读取保留的更新结果 {#read-update-outcome} + +Rust SDK 4.15 新增 `Client::update_outcome` 和 `Client::update_outcome_receipt`,用于按 ID 读取已接受的更新,不重新提交。这些方法要求 `capabilities.update_outcome_reads`(native Server 3.6.0 及更高版本)。`update_outcome` 对尚未完成的更新返回 `Error::UpdateStillPending`。已完成的 null 结果为 `Ok(Value::Null)`。回执保留明确的 `update_status`。Rust 接口见 [Client API](https://rust.durable-workflow.com/durable_workflow/struct.Client.html#method.update_outcome)。 + +Rust SDK 4.15.0 仍对整个命令批次应用普通载荷上限。在没有外部载荷存储时执行较大的扇出之前,请查看[已知规划器上限](./server-config-reference.md#rust-completion-planning)。 + ## 条件等待期限与 Worker 升级 {#condition-wait-deadlines} Rust SDK 4.11.2 从未分组的 `wait_condition` 首次打开时开始计算超时。 diff --git a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md index 068fd55a08c..f6a0561f9b7 100644 --- a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md +++ b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md @@ -262,6 +262,63 @@ Sticky 执行没有独立的 Server 镜像环境变量。关于 sticky 缓存生 | `DW_MAX_NEXUS_OPERATIONS_PER_CALLER` | `200` | 操作历史接口向每个调用方返回的 Nexus 操作上限,之后客户端需分页。 | `WORKFLOW_MAX_NEXUS_OPERATIONS_PER_CALLER` | | `DW_COMPRESSION_ENABLED` | `true` | 对超过最小大小阈值的 JSON 响应启用压缩。 | `WORKFLOW_SERVER_COMPRESSION_ENABLED` | +## Server 请求边界限制 {#server-request-boundary-limits} + +使用独立 Server 时,在工作流任务、信号、更新或查询到达控制平面之前,HTTP 请求边界会应用另一组上限。超限请求会快速返回 `422 validation_failed`(整个请求体检查则返回 `413 payload_too_large`),使客户端获知拒绝原因,而 Server 不会向数据库写入任何行。 + +| 限制 | 默认值 | 配置键 | 约束对象 | +|---|---|---|---| +| 请求体大小 | 2 MiB | `server.limits.max_payload_bytes` | HTTP 请求体的总字节数;原生 Server 3.6.0 及以上的工作流任务完成请求除外(见下一行) | +| 工作流任务完成大小 | 32 MiB(请求体大小的 16 倍) | 由 `server.limits.max_payload_bytes` 推导 | 原生 Server 3.6.0 及以上:带命令完成工作流任务的请求。每个命令的参数仍须符合单个载荷上限 | +| memo 大小 | 256 KiB | `server.limits.max_memo_bytes` | `POST /workflows` 和 `POST /schedules` 中序列化的 memo | +| 搜索属性数量 | 100 | `server.limits.max_search_attributes` | 每个命名空间注册的自定义搜索属性数 | +| 搜索属性键长度 | 128 字节 | `server.limits.max_search_attribute_key_length` | 启动时单个搜索属性键的长度 | +| 搜索属性值大小 | 2 KiB | `server.limits.max_search_attribute_value_bytes` | 启动时的每个字符串值(以及数组值的每个元素) | +| 信号/更新/查询名称 | 256 字节 | `server.limits.max_operation_name_length` | 信号/更新/查询名称的 URL 路径段 | +| `workflow_id` 长度 | 128 字符 | 控制器验证器 | `POST /workflows` 中的工作流 ID | +| `workflow_type` / `task_queue` / `business_key` | 255 字符 | 控制器验证器 | `POST /workflows` 中的字符串字段 | +| `request_id` | 255 字符 | 控制器验证器 | 信号/更新/取消/终止操作的去重令牌 | +| `reason` | 1,000 字符 | 控制器验证器 | 取消/终止/归档操作的原因文本 | + +PHP Server 2.x 的可配置限制请使用已记录的 `DW_*` 设置。控制器校验上限是固定的。Native Server 3.x 支持的设置见其[实现说明](#native-server-3x)。在 native 3.8.0 中,`DW_MAX_PAYLOAD_BYTES=0` 会将普通请求和工作流任务完成请求的上限设为零字节,拒绝非空请求体。操作名上限固定为 256 字节。 + +当前配置值发布在 `GET /api/cluster/info` 响应的 `limits` 下,客户端可在运行时发现这些限制: + +```json +{ + "limits": { + "max_payload_bytes": 2097152, + "max_memo_bytes": 262144, + "max_search_attributes": 100, + "max_search_attribute_key_length": 128, + "max_search_attribute_value_bytes": 2048, + "max_operation_name_length": 256, + "max_pending_activities": 2000, + "max_pending_children": 2000 + } +} +``` + +验证错误通过标准控制平面错误信封返回,包含 `reason: "validation_failed"` 和以出错字段(`signal_name`、`update_name`、`query_name`、`search_attributes`、`memo` 等)为键的 `validation_errors` 映射。载荷大小超限使用 `reason: "payload_too_large"` 和 `413` 状态码。 + +### 工作流任务完成大小 {#workflow-task-completion-size} + +在原生 Server 3.6.0 及以上,带命令完成工作流任务的请求(`POST /api/worker/workflow-tasks/{id}/complete` 和 `POST /api/worker/activity-tasks/{id}/continuation/complete`)最多可达 `max_payload_bytes` 的 16 倍:默认 2 MiB 时为 32 MiB。该上限跟随 `DW_MAX_PAYLOAD_BYTES`,没有单独的设置。完成请求中每个命令的参数仍须符合单个载荷上限。PHP Server 2.x 和更早的原生版本与其他请求一样,将完成请求限制为一个载荷上限。 + +更大的完成请求会在记录任何内容之前以 `413 payload_too_large` 和 `limit_kind: workflow_task_completion_bytes` 被拒绝。重放该任务会生成相同的命令,因此重新发送完成请求会得到同样的拒绝。PHP SDK 3.17.0 及以上在收到这种类型化拒绝后不会重新发送完成请求:Worker 用一条 `fail_workflow` 命令让运行失败一次,其消息以 `Structural limit exceeded: workflow_task_completion_bytes:` 开头并给出两个大小,Server 以 `failure_category = structural_limit` 记录该失败。 + +Python SDK 2.17 和 Rust SDK 4.15 包含对类型化拒绝的处理。在 Server 3.8.0 上,过大的完成请求可能在 Worker 收到 HTTP 413 之前就在传输层失败。在已发布 Python SDK 的测试中,`httpx.ReadError` 使工作流保持待处理状态,而没有因结构限制失败。已发布 Server 的超限请求验收仍由 [Server 响应修复](https://github.com/durable-workflow/.github/issues/228#issuecomment-6848969678)跟进。在该路径通过资格验证之前,请减小完成请求。 + +要让完成请求保持在上限之内: + +- 将大型扇出拆分为分布在多个工作流任务中的较小批次。 +- 将工作移到子工作流中,或使用 continue-as-new。 +- 将大型参数存入外部载荷存储,使完成请求携带引用而不是载荷本身。 + +#### Rust 命令规划 {#rust-completion-planning} + +Rust SDK 4.15.0 仍将普通单个载荷上限作为命令规划的总上限(默认为 2 MiB),先于 Server 更大的完成请求上限生效。如果命名空间没有外部载荷存储,已发布的 300 × 10 KB 扇出会以 `external_payload_unavailable` 被拒绝,Worker 退出,运行保持待处理状态。在 [SDK 总量规划器修复](https://github.com/durable-workflow/sdk-rust/issues/254)完成之前,请使用更小的命令批次。此 SDK 路径尚未实现 Server 更大的上限。 + ## Docker 初始化与来源信息 {#docker-bootstrap-and-provenance} | 变量 | 默认值 | 用途 | 旧版别名 | diff --git a/i18n/zh-Hans/source-hashes.json b/i18n/zh-Hans/source-hashes.json index 4ec35cae6fb..ca19adf3f36 100644 --- a/i18n/zh-Hans/source-hashes.json +++ b/i18n/zh-Hans/source-hashes.json @@ -17,7 +17,7 @@ "constraints/execution-guarantees.md": "c24aaff70bfcf50366459ec698ced67adff1e02c1b0ca23c8178a13873037f5a", "constraints/idempotent-vs-deterministic.md": "f7396f01a4111ce187e751b009c1efb96f5538e8a602006eed24f7b1d8f44adf", "constraints/overview.md": "fd6c842c6c22d6f0df37a52de15ca74b34664f5ecd78af0c08b1e0cdb9a2be1f", - "constraints/structural-limits.md": "ad498fae9ec7722aaca2990635027a4f52b4ac6dbd4b145c1aba1a03c6000b1b", + "constraints/structural-limits.md": "b9c2d515fce3b56a03ac654dab65edbe67e13903386412dba8aa1ea77a1d9657", "constraints/workflow-constraints.md": "2fc7b45646bf459ff31fb27d38b5ae34602e1a64697c8f2d2378421a7f8a6ef5", "contribute-a-sample.md": "d250d8c63d448e32d3160ff7a2900e7a270dcbd9cda22cf3af46cdf219395ea3", "conversational-workflows.md": "d155b4af3d83293802cfa765bb28de7b3fc52345509f4f3d02e16318d825a675", @@ -70,8 +70,8 @@ "polyglot/avro-value-protocol.md": "602e66c6288c1dd69d2b400c64e4739ad3a0493b5be269cee40f7848b11f260a", "polyglot/cancellation.md": "f676cd3ddb39246a0f580a1e16c83bc36d2ed9458b9e6009af4cc192d299ac62", "polyglot/cli-python-parity.md": "acf1acbf15ca9cdf069154699c5fbf8c1d1fd3241a32d201ac10b8ec76c038be", - "polyglot/cli-reference.md": "dc3802b01887f01e702b7989b54c06ba98e8e19326c17db7b32af4e5230e76ee", - "polyglot/cli.mdx": "5b4fdd5c283b3f45691324433d96e6c84e2e898d58fbb7536992ca1dc4503d54", + "polyglot/cli-reference.md": "665c65192f9bfd41610f2aca54a66c2a3aa125e2d2b637d744d9c5f4243bee24", + "polyglot/cli.mdx": "9dac7bb6b711737c9f16916ef462d85c642539f4b6e4a1bdac59320a09632c1f", "polyglot/cloud-control-plane.md": "bb375e598dd1afa3207171047fb81b0cb82c382ce535ab415cb09dc10f6d748e", "polyglot/database-support.md": "518f679ae723ae4d39db7cac78008bc8edb84a6cfba2e6c668d8f2be5d378d03", "polyglot/deployment-modes.md": "7b508db4be86c92de76cfd8dfd946d93941c8a6f0a601a161d4d3fd1711bf97f", @@ -84,12 +84,12 @@ "polyglot/polling-patterns.md": "30875099a23731c6c471b481a771378acc6ff57eed2fda4405a509057534c989", "polyglot/portable-worker-affinity.md": "40973c6a31a76845b4f95e9a505e68ad76abd5174bbdccf37993cdebc8904959", "polyglot/prerelease-history-migration.md": "a57f05f492228a8a67791f9152648a1e5f80856325b78777cf63b6ef49b7413c", - "polyglot/python.md": "1229182acdbe6ddf7f4d875a28c7db67c83931e4055b137b8ce35d4775e3a7b1", + "polyglot/python.md": "7e31563bf15d1f7f1bd1647b70644ef5e72b2c912c566e72e9b1cc4a7fe19d89", "polyglot/runtime-migration.md": "5a78713bb8cb74aea58f6d5d826400d968a405f69c6ff17fdf2f7decb1d14b71", "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", - "polyglot/rust.md": "e9ebec32026199c861409f6fbba0a45f2e360638a68ac75387ad09fd09c6a420", + "polyglot/rust.md": "e768d43c38be76b22440910aa97d61897b392321f106dd2fe7461399a13a99c9", "polyglot/server-api-reference.md": "8bac825f11f7aa3f2a335cf3d1dcdc951219f11d6702e9fe3502d3803fd1e2a5", - "polyglot/server-config-reference.md": "02da3d03e49af3171de9268033c01273cb28fc7eaac665fcaa8aff1252be9055", + "polyglot/server-config-reference.md": "636e4aa05bcc56569a3d001bc80ad2853f95372b051aebcf2bdd0061d2e50b6b", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "2c03845c0979f62bc7ab3208cf09820844b224e548f10fb7d1656852e3428445", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", diff --git a/static/stable-releases.json b/static/stable-releases.json index 0bc5abdbd0a..76d1ce6ddc5 100644 --- a/static/stable-releases.json +++ b/static/stable-releases.json @@ -3,11 +3,11 @@ "schema_version": 1, "updated_at": "2026-11-13", "artifacts": { - "cli": "2.7.0", + "cli": "2.8.0", "helm-chart": "1.6.0", - "sdk-php": "3.17.0", - "sdk-python": "2.16.0", - "sdk-rust": "4.14.0", + "sdk-php": "3.18.0", + "sdk-python": "2.17.1", + "sdk-rust": "4.15.0", "server": "3.8.0", "waterline": "2.18.0", "workflow": "2.28.0"