diff --git a/docs/polyglot/server-config-reference.md b/docs/polyglot/server-config-reference.md index a9f1a5c50ca..05ec169a332 100644 --- a/docs/polyglot/server-config-reference.md +++ b/docs/polyglot/server-config-reference.md @@ -330,6 +330,74 @@ when you configure `DW_V2_MATCHING_ROLE_QUEUE_WAKE` or a dedicated `workflow:v2:repair-pass --loop` daemon. Those settings change where ready-task discovery runs, not the worker-protocol contract itself. +## Additional published PHP controls {#additional-published-php-controls} + +This reference covers the published **PHP Server 2.11.0** contract, including the controls below. Check the image you actually run: the independently selected installation version can be older. `unset` means no environment value is supplied; its effect depends on the control. Defaults and aliases come from the [published contract](https://github.com/durable-workflow/server/blob/36d16273604755f3dd0743cab331cc7c62e51d8e/config/dw-contract.php). The versioned contract snapshot is checked against every locale during the documentation build. This reference does not change the selected installation tuple. + +### Namespace HTTP admission {#namespace-request-controls} + +| Variable | Default | Purpose | Legacy alias | +| --- | --- | --- | --- | +| `DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | `unset` | Optional per-minute control-plane request cap for each namespace. Unset means unlimited. | `WORKFLOW_SERVER_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_MAX_CONCURRENT_REQUESTS` | `unset` | Optional concurrent control-plane request cap for each namespace. Unset means unlimited. | `WORKFLOW_SERVER_NAMESPACE_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | `unset` | Non-bypassable ceiling for namespace control-plane requests per minute, including namespace overrides. | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | `unset` | Non-bypassable ceiling for concurrent namespace control-plane requests, including namespace overrides. | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_ADMISSION_OVERRIDES` | `{}` | JSON object keyed by namespace with optional request-rate and concurrent-request overrides. | `WORKFLOW_SERVER_NAMESPACE_ADMISSION_OVERRIDES` | + +[Namespace request admission](./task-queue-admission.md#namespace-request-admission). + +### Namespace durable-state quotas {#namespace-durable-controls} + +| Variable | Default | Purpose | Legacy alias | +| --- | --- | --- | --- | +| `DW_NAMESPACE_DURABLE_LIMITS` | `{}` | JSON object of default per-namespace durable row limits across workflow instances, runs, history, tasks, timers, waits, commands, schedules, workers, and streams. Lifetime and pending/open limits are independent; pending workflow tasks count queued ready rows because active leases have separate admission limits. An empty object is unlimited. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_LIMITS` | +| `DW_NAMESPACE_DURABLE_HARD_LIMITS` | `{}` | JSON object of non-bypassable ceilings for the namespace durable row limit fields, including per-namespace overrides. An empty object adds no operator hard ceilings. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_HARD_LIMITS` | +| `DW_NAMESPACE_DURABLE_OVERRIDES` | `{}` | JSON object keyed by namespace with optional namespace durable row limit overrides. Hard limits remain authoritative. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_OVERRIDES` | + +[Namespace durable-state quotas](./task-queue-admission.md#namespace-durable-state). + +### External payload quotas and S3 transport {#external-payload-quotas-and-s3} + +| Variable | Default | Purpose | Legacy alias | +| --- | --- | --- | --- | +| `DW_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | `unset` | Distinct bytes allowed across immutable upload slots for one leased completion; unset uses DW_EXTERNAL_PAYLOAD_MAX_BYTES. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | +| `DW_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | `unset` | Optional cumulative external-payload byte cap for each namespace. Ready and in-progress objects count toward the cap; unset means unlimited. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | Optional external-payload object-count cap for each namespace. Ready and in-progress objects count toward the cap; unset means unlimited. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | `unset` | Non-bypassable cumulative external-payload byte ceiling for each namespace, including namespace overrides. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | Non-bypassable external-payload object-count ceiling for each namespace, including namespace overrides. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | `{}` | JSON object keyed by namespace with optional max_bytes and max_objects external-payload quota overrides. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | +| `DW_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | `unset` | Optional access-key ID for the runtime-managed S3-compatible external-payload disk. May be omitted when workload identity supplies credentials. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | +| `DW_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | `unset` | Optional secret access key for the runtime-managed S3-compatible external-payload disk. Must be set with the access-key ID. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | +| `DW_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | `unset` | Optional session token for temporary credentials on the runtime-managed S3-compatible external-payload disk. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | +| `DW_EXTERNAL_PAYLOAD_S3_REGION` | `us-east-1` | Region used by the runtime-managed S3-compatible external-payload disk. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_REGION` | +| `DW_EXTERNAL_PAYLOAD_S3_BUCKET` | `unset` | Bucket used by the runtime-managed S3-compatible external-payload disk. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_BUCKET` | +| `DW_EXTERNAL_PAYLOAD_S3_ENDPOINT` | `unset` | Optional HTTPS endpoint for an S3-compatible external-payload service. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ENDPOINT` | +| `DW_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | `false` | Use path-style bucket addressing for the runtime-managed S3-compatible external-payload service. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | + +### Caller-namespace service boundaries {#service-caller-namespace-controls} + +| Variable | Default | Purpose | Legacy alias | +| --- | --- | --- | --- | +| `DW_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | `unset` | Optional shared per-minute service-call limit aggregated across each caller namespace. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | `unset` | Optional shared in-flight service-call limit aggregated across each caller namespace. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | `unset` | Non-bypassable per-minute ceiling for service-call boundary and caller-namespace policies. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | `unset` | Non-bypassable in-flight ceiling for service-call boundary and caller-namespace policies. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | `{}` | JSON object of caller-namespace service-call rate and in-flight overrides; hard ceilings still apply. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | + +### Coordination, storage and runtime {#coordination-storage-and-runtime-controls} + +| Variable | Default | Purpose | Legacy alias | +| --- | --- | --- | --- | +| `DW_OBSERVABILITY_CONTEXT_ENABLED` | `false` | Enable optional bounded trace context persistence, delivery and capability discovery when its optional API and schema are installed. | - | +| `DW_OBSERVABILITY_BAGGAGE_ALLOWLIST` | `[]` | JSON list of baggage keys permitted on run origins; default empty. Links never carry baggage. | - | +| `DW_STORAGE_ADMISSION_FILE` | `unset` | Optional read-only local storage-pressure observation file; invalid or stale observations fence writes. | - | +| `DW_STORAGE_ADMISSION_SOURCE` | `unset` | Expected storage resource identity in the admission observation. | - | +| `DW_STORAGE_ADMISSION_MAX_AGE_SECONDS` | `15` | Maximum age of a storage observation in seconds (1-300). | - | +| `DW_RUNTIME_CREDENTIALS_ENABLED` | `false` | Enable durable, database-backed, namespace-bound runtime bearer credentials managed through the admin API. | `WORKFLOW_SERVER_RUNTIME_CREDENTIALS_ENABLED` | +| `DW_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | Optional per-node cap for concurrent held workflow/activity long-poll waits from one namespace. The effective cap cannot exceed the global worker wait cap. Configured namespace isolation fails closed when shared cache authority is unavailable. | `WORKFLOW_SERVER_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | Optional per-node cap for concurrent held query-task long-poll waits from one namespace. The effective cap cannot exceed the global query-task wait cap. Configured namespace isolation fails closed when shared cache authority is unavailable. | `WORKFLOW_SERVER_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_V1_ENABLED` | `false` | Enable legacy embedded v1 migration and queue-drain behavior. Standalone Server defaults to v2-only; enable only when deliberately preserving v1 state. | `WORKFLOW_V1_ENABLED` | + ## Runtime Infrastructure Variables Runtime infrastructure variables are framework and dependency controls. The diff --git a/docs/polyglot/task-queue-admission.md b/docs/polyglot/task-queue-admission.md index e774e3d4fa9..93faed7b0a0 100644 --- a/docs/polyglot/task-queue-admission.md +++ b/docs/polyglot/task-queue-admission.md @@ -92,6 +92,67 @@ An open application breaker raises `NonRetryableError` before the payment call; Keep protected downstream calls in **ordinary queued activities**. Inline local activities create no ordinary activity task, so queue, namespace and budget-group activity dispatch caps do not meter them. A prepared local-activity claim validates execution authority, not this dispatch budget. Embedded Laravel mode has no standalone Server admission; use its own deployment controls. See [local activities](../features/local-activities.md). +## Namespace request admission {#namespace-request-admission} + +The following contract is for published **PHP Server 2.11.0**. Check your actual image and the [versioned configuration reference](./server-config-reference.md#additional-published-php-controls). Namespace HTTP budgets are separate from worker slots, task dispatch, held worker polls and durable-state quotas. The HTTP budget belongs to the request namespace resolved from `Durable-Workflow-Namespace` or `DW_DEFAULT_NAMESPACE`, including namespace-management requests whose path names another namespace. + +Authenticated requests that reach namespace admission count on these control and management route families, including their descendants: `/api/namespaces`, `/api/storage`, `/api/workflows`, `/api/activities`, `/api/bridge-adapters`, `/api/workers`, `/api/worker-sessions`, `/api/task-queues`, `/api/deployments`, `/api/schedules`, `/api/search-attributes`, `/api/service-endpoints`, `/api/service-catalog`. Plural `/api/workers` management requests count. + +Singular `/api/worker/*` registration, polling and outcome routes do not use this HTTP budget. Health/readiness, `/api/cluster/info`, admin `/api/system/*`, runtime credentials and external-payload transport also stay outside this gate; their own authentication, capacity and storage checks still apply. Requests refused earlier by authentication, protocol or namespace resolution never reach this counter. + +Rate admission uses fixed server-clock minute buckets, not a smooth or rolling rate. A budget of N can admit N requests just before a boundary and another N just after it. Requests that fail later still count; rate admission happens before the concurrency check, so a concurrency refusal can consume minute budget. A concurrency slot remains held until the request finishes and cleanup releases it; it does not count running workflows. + +Across API replicas, use the same shared Redis store/key prefix, synchronized clocks and consistent loaded configuration. The shared namespace budget is not multiplied by adding replicas. A local file cache only coordinates processes with compatible writable access to its files; it is not the multi-node baseline. Per-node held worker/query-poll caps remain separate. [Restart affected roles after environment changes](./server-config-reference.md#how-changes-take-effect). + +```dotenv +DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE=100 +DW_NAMESPACE_MAX_CONCURRENT_REQUESTS=8 +DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE=150 +DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS=10 +DW_NAMESPACE_ADMISSION_OVERRIDES='{"payments":{"max_requests_per_minute":200,"max_concurrent_requests":12},"reports":{"max_requests_per_minute":40,"max_concurrent_requests":3}}' +``` + +For existing namespaces, this example resolves `payments` to 150 requests/minute and 10 concurrent requests, `reports` to 40/3, and other namespaces to 100/8. Overrides can raise or lower defaults, but the 150/10 hard caps still apply. This configuration does not create namespaces or reserve throughput. + +For these HTTP controls, unset means no corresponding configured limit; a hard cap alone can still impose a limit. A null override falls back to the default. Values must be positive integers: zero is invalid. PHP implementation ceilings are 10000000 requests/minute and 1024 concurrent requests, independent of the actual HTTP pool capacity. Published PHP 2.11.0 silently treats malformed `DW_NAMESPACE_ADMISSION_OVERRIDES` JSON as an empty override map, falling back to global defaults. Validate the JSON before deployment; if the defaults and hard caps are unset, the intended namespace cap is lost. This [confirmed product gap](https://github.com/durable-workflow/durable-workflow.github.io/issues/335#issuecomment-6369150521) remains separate from the documentation update. + +| Reason | HTTP | Retry hint in seconds | +| --- | --- | --- | +| `namespace_request_rate_exhausted` | `429` | Until the next minute, 1–60 | +| `namespace_request_concurrency_exhausted` | `429` | 1 | +| `namespace_request_admission_unavailable` | `503` | 1 | + +The JSON `retry_after_seconds` and `Retry-After` header agree. Unavailable configured coordination or invalid numeric limits fails closed with 503. Inspect namespace-scoped admin metrics even when ordinary requests are exhausted; `dw_namespace_request_admission_rejections` reports the finite reasons. Apply bounded caller retry/backoff policy and preserve idempotency; an uncertain transport outcome is not permission to resubmit a write automatically. See [timeout budgets](../deployment.md#worker-long-poll-timeout-budgets). + +## Namespace durable-state quotas {#namespace-durable-state} + +`DW_NAMESPACE_DURABLE_LIMITS` sets default retained-row limits, `DW_NAMESPACE_DURABLE_OVERRIDES` changes them per namespace, and `DW_NAMESPACE_DURABLE_HARD_LIMITS` adds non-bypassable ceilings. Empty objects add no limits. Overrides can raise or lower defaults; null falls back to the default. Unlike HTTP admission, a durable limit of zero is valid and prevents new allocations. In this example, existing `payments` can hold 250 open runs, other namespaces 100, under a 500 hard ceiling. + +```dotenv +DW_NAMESPACE_DURABLE_LIMITS='{"max_open_workflow_runs":100,"max_open_workflow_run_waits":200,"max_pending_workflow_timers":200}' +DW_NAMESPACE_DURABLE_HARD_LIMITS='{"max_open_workflow_runs":500}' +DW_NAMESPACE_DURABLE_OVERRIDES='{"payments":{"max_open_workflow_runs":250}}' +``` + +Use `max_` fields for the resources below. Counts belong to the namespace owning each row, or its linked workflow/run. Total retained rows and open/pending subsets are independent limits. Enforcement uses database-authoritative counts while serializing mutations on the namespace row. + +| Resource | What counts | +| --- | --- | +| `workflow_instances`, `workflow_runs` | All retained workflow instance/run rows, including terminal runs. | +| `open_workflow_runs` | Runs with `pending`, `running` or `waiting` status. | +| `workflow_history_events`, `workflow_commands`, `workflow_tasks` | Retained history, command and workflow-task rows. | +| `pending_workflow_tasks` | Queued workflow-task rows with `ready` status; active leases have separate admission controls. | +| `workflow_timers`, `pending_workflow_timers` | All retained timers, and the `pending` subset respectively. | +| `workflow_run_waits`, `open_workflow_run_waits` | All retained run waits, and the `open` subset respectively. | +| `schedules`, `schedule_history_events`, `worker_registrations` | Retained schedules, schedule history and worker-registration rows; stale registrations count until removed. | +| `workflow_streams`, `workflow_stream_items` | Durable and inbound stream rows, and their item rows. | + +A parent waiting for a child or service call still consumes an open run in its own namespace. A child adds its own run; in the same namespace, plan for both open runs and their waits/timers. A service operation that creates a workflow consumes rows in that workflow’s namespace; signal/update operations on an existing run do not automatically create a second run. Service-call boundary and external-payload quotas are separate controls. + +Exhaustion returns 429 `namespace__exhausted`. Read `retryable`: some quotas are nonretryable and provide no retry hint; retryable durable refusals advertise 60 seconds, without promising capacity then. Failure to evaluate a configured quota returns 503 `namespace_durable_state_quota_unavailable` with a one-second hint. Retained-row pressure may require retention or a capacity/configuration change, not a tight retry loop. + +Select the namespace with the request header when reading admin metrics. `dw_namespace_durable_state_usage` and the JSON `limits`, `usage`, `remaining`, `configuration_status` and `measurement_status` expose that scope; namespace is request scope rather than an unbounded metric label. Unavailable measurements are not zero usage or unlimited capacity. See the [complete configuration reference](./server-config-reference.md#namespace-durable-controls). + ## Server Configuration Set global caps when every queue should share the same ceiling: 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 2e315b3e7a6..305c693ba1f 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 @@ -271,6 +271,74 @@ Verwenden Sie `DW_V2_GUARDRAILS_BOOT` in CI und Bereitstellungsmanifesten. Der a Lesen Sie [Aufgabenzuordnung und Zustellung](/docs/polyglot/task-matching-dispatch), wenn Sie `DW_V2_MATCHING_ROLE_QUEUE_WAKE` oder einen eigenen `workflow:v2:repair-pass --loop`-Daemon konfigurieren. Diese Einstellungen ändern den Ort der Erkennung bereiter Aufgaben, nicht den Worker-Protokollvertrag. +## Weitere Einstellungen des veröffentlichten PHP Servers {#additional-published-php-controls} + +Diese Referenz beschreibt den veröffentlichten Vertrag von **PHP Server 2.11.0** einschließlich der folgenden Einstellungen. Prüfen Sie das tatsächlich verwendete Image: Die unabhängig gewählte Installationsversion kann älter sein. `unset` bedeutet, dass kein Umgebungswert gesetzt ist; die Wirkung hängt von der Einstellung ab. Vorgaben und Aliasse stammen aus dem [veröffentlichten Vertrag](https://github.com/durable-workflow/server/blob/36d16273604755f3dd0743cab331cc7c62e51d8e/config/dw-contract.php). Der Build prüft dessen versionierten Snapshot in jeder Sprache. Die ausgewählten Installationsversionen ändern sich dadurch nicht. + +### HTTP-Zulassung pro Namespace {#namespace-request-controls} + +| Variable | Vorgabe | Zweck | Alter Alias | +| --- | --- | --- | --- | +| `DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | `unset` | Optionale Zahl von Control-Plane-Anfragen pro Minute und Namespace; ohne Wert unbegrenzt. | `WORKFLOW_SERVER_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_MAX_CONCURRENT_REQUESTS` | `unset` | Optionale Zahl gleichzeitiger Control-Plane-Anfragen pro Namespace; ohne Wert unbegrenzt. | `WORKFLOW_SERVER_NAMESPACE_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | `unset` | Unübergehbare Obergrenze der Anfragen pro Minute, auch bei Namespace-Overrides. | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | `unset` | Unübergehbare Obergrenze gleichzeitiger Anfragen, auch bei Namespace-Overrides. | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_ADMISSION_OVERRIDES` | `{}` | JSON-Objekt nach Namespace mit Overrides für Anfragerate und Gleichzeitigkeit. | `WORKFLOW_SERVER_NAMESPACE_ADMISSION_OVERRIDES` | + +[Anfragezulassung pro Namespace](./task-queue-admission.md#namespace-request-admission). + +### Kontingente für dauerhaften Namespace-Zustand {#namespace-durable-controls} + +| Variable | Vorgabe | Zweck | Alter Alias | +| --- | --- | --- | --- | +| `DW_NAMESPACE_DURABLE_LIMITS` | `{}` | JSON mit Standardkontingenten dauerhafter Zeilen pro Namespace. Gesamt- und Pending/Open-Grenzen gelten unabhängig; ausstehende Tasks sind Ready-Zeilen in der Queue, aktive Leases werden separat begrenzt. Ein leeres Objekt begrenzt nicht. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_LIMITS` | +| `DW_NAMESPACE_DURABLE_HARD_LIMITS` | `{}` | JSON mit unübergehbaren Obergrenzen dauerhafter Zeilen einschließlich Overrides; ein leeres Objekt fügt keine Betreiberobergrenzen hinzu. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_HARD_LIMITS` | +| `DW_NAMESPACE_DURABLE_OVERRIDES` | `{}` | JSON mit Overrides dauerhafter Zeilenkontingente pro Namespace; harte Obergrenzen gelten weiterhin. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_OVERRIDES` | + +[Kontingente für dauerhaften Namespace-Zustand](./task-queue-admission.md#namespace-durable-state). + +### Externe Payload-Kontingente und S3-Transport {#external-payload-quotas-and-s3} + +| Variable | Vorgabe | Zweck | Alter Alias | +| --- | --- | --- | --- | +| `DW_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | `unset` | Unterschiedliche Bytes in unveränderlichen Upload-Slots eines geleasten Completions; ohne Wert gilt `DW_EXTERNAL_PAYLOAD_MAX_BYTES`. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | +| `DW_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | `unset` | Kumulierte Bytes externer Payloads pro Namespace. Fertige und laufende Objekte zählen; ohne Wert unbegrenzt. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | Anzahl externer Payload-Objekte pro Namespace. Fertige und laufende Objekte zählen; ohne Wert unbegrenzt. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | `unset` | Unübergehbare Obergrenze kumulierter externer Payload-Bytes pro Namespace einschließlich Overrides. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | Unübergehbare Obergrenze externer Payload-Objekte pro Namespace einschließlich Overrides. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | `{}` | JSON-Objekt nach Namespace mit Kontingent-Overrides für `max_bytes` und `max_objects`. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | +| `DW_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | `unset` | Optionale Access-Key-ID des laufzeitverwalteten S3-kompatiblen Datenträgers; bei Workload Identity entbehrlich. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | +| `DW_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | `unset` | Optionaler geheimer Schlüssel des verwalteten S3-kompatiblen Datenträgers; zusammen mit der Access-Key-ID setzen. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | +| `DW_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | `unset` | Optionales Session-Token temporärer Zugangsdaten des verwalteten S3-kompatiblen Datenträgers. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | +| `DW_EXTERNAL_PAYLOAD_S3_REGION` | `us-east-1` | Region des laufzeitverwalteten S3-kompatiblen Datenträgers. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_REGION` | +| `DW_EXTERNAL_PAYLOAD_S3_BUCKET` | `unset` | Bucket des laufzeitverwalteten S3-kompatiblen Datenträgers. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_BUCKET` | +| `DW_EXTERNAL_PAYLOAD_S3_ENDPOINT` | `unset` | Optionaler HTTPS-Endpunkt des S3-kompatiblen Dienstes für externe Payloads. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ENDPOINT` | +| `DW_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | `false` | Path-Style-Bucket-Adressierung für den verwalteten S3-kompatiblen Dienst verwenden. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | + +### Service-Grenzen pro aufrufendem Namespace {#service-caller-namespace-controls} + +| Variable | Vorgabe | Zweck | Alter Alias | +| --- | --- | --- | --- | +| `DW_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | `unset` | Optionale gemeinsame Zahl von Service-Aufrufen pro Minute, über den aufrufenden Namespace aggregiert. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | `unset` | Optionale gemeinsame Zahl laufender Service-Aufrufe, über den aufrufenden Namespace aggregiert. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | `unset` | Unübergehbare Minutenobergrenze für Service-Grenz- und Aufrufer-Namespace-Richtlinien. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | `unset` | Unübergehbare Obergrenze laufender Aufrufe für Service-Grenz- und Aufrufer-Namespace-Richtlinien. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | `{}` | JSON mit Raten- und Gleichzeitigkeit-Overrides nach aufrufendem Namespace; harte Obergrenzen gelten weiter. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | + +### Koordination, Speicher und Laufzeit {#coordination-storage-and-runtime-controls} + +| Variable | Vorgabe | Zweck | Alter Alias | +| --- | --- | --- | --- | +| `DW_OBSERVABILITY_CONTEXT_ENABLED` | `false` | Begrenzte Speicherung und Übertragung von Trace-Kontext sowie Discovery aktivieren, wenn optionale API und Schema installiert sind. | - | +| `DW_OBSERVABILITY_BAGGAGE_ALLOWLIST` | `[]` | JSON-Liste erlaubter Baggage-Schlüssel an Run-Ursprüngen; standardmäßig leer. Links tragen niemals Baggage. | - | +| `DW_STORAGE_ADMISSION_FILE` | `unset` | Optionale lokale, schreibgeschützte Datei zur Beobachtung von Speicherdruck; ungültige oder veraltete Beobachtungen sperren Schreibvorgänge. | - | +| `DW_STORAGE_ADMISSION_SOURCE` | `unset` | Erwartete Identität der Speicherressource in der Zulassungsbeobachtung. | - | +| `DW_STORAGE_ADMISSION_MAX_AGE_SECONDS` | `15` | Maximales Alter einer Speicherbeobachtung in Sekunden, von 1 bis 300. | - | +| `DW_RUNTIME_CREDENTIALS_ENABLED` | `false` | Dauerhafte, datenbankgestützte und Namespace-gebundene Runtime-Bearer-Zugangsdaten über die Admin-API aktivieren. | `WORKFLOW_SERVER_RUNTIME_CREDENTIALS_ENABLED` | +| `DW_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | Obergrenze pro Knoten für gehaltene Workflow-/Activity-Long-Polls eines Namespace; höchstens das globale Worker-Limit. Ohne gemeinsame Cache-Autorität wird abgelehnt. | `WORKFLOW_SERVER_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | Obergrenze pro Knoten für gehaltene Query-Task-Long-Polls eines Namespace; höchstens das globale Query-Limit. Ohne gemeinsame Cache-Autorität wird abgelehnt. | `WORKFLOW_SERVER_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_V1_ENABLED` | `false` | Embedded-v1-Migration und Queue-Leerung nur zum bewussten Erhalt von v1-Zustand aktivieren; eigenständiger Server nutzt standardmäßig nur v2. | `WORKFLOW_V1_ENABLED` | + ## Infrastrukturvariablen der Laufzeitumgebung {#runtime-infrastructure-variables} Infrastrukturvariablen konfigurieren Framework und Abhängigkeiten. Die Server-Prüfung erkennt sie und warnt deshalb nicht, sie sind aber keine stabilen Durable Workflow API-Einstellungen. diff --git a/i18n/de/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md b/i18n/de/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md index 9dfb4c9668a..b9fedbf76d4 100644 --- a/i18n/de/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md +++ b/i18n/de/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md @@ -89,6 +89,67 @@ Ein offener Anwendungs-Breaker löst vor der Zahlung `NonRetryableError` aus. Ge Geschützte Dienstaufrufe gehören in **gewöhnliche eingereihte Aktivitäten**. Inline-lokale Aktivitäten erzeugen keinen gewöhnlichen Aktivitätstask; Queue-/Namespace-/Gruppen-Obergrenzen messen sie nicht. Ein vorbereiteter lokaler Claim prüft Ausführungsbefugnis, nicht dieses Budget. Eingebettetes Laravel hat keine Admission des eigenständigen Servers; verwenden Sie eigene Deployment-Kontrollen. Siehe [lokale Aktivitäten](../features/local-activities.md). +## Anfragezulassung pro Namespace {#namespace-request-admission} + +Dieser Vertrag gilt für den veröffentlichten **PHP Server 2.11.0**. Prüfen Sie Ihr Image und die [versionierte Konfigurationsreferenz](./server-config-reference.md#additional-published-php-controls). HTTP-Budgets sind von Worker-Slots, Task-Dispatch, gehaltenen Polls und dauerhaften Kontingenten getrennt. Das Budget gehört zum durch `Durable-Workflow-Namespace` oder `DW_DEFAULT_NAMESPACE` aufgelösten Namespace, auch wenn ein Verwaltungspfad einen anderen Namespace nennt. + +Authentifizierte Anfragen, die die Zulassung erreichen, zählen in diesen Control- und Verwaltungsroutenfamilien einschließlich Unterpfaden: `/api/namespaces`, `/api/storage`, `/api/workflows`, `/api/activities`, `/api/bridge-adapters`, `/api/workers`, `/api/worker-sessions`, `/api/task-queues`, `/api/deployments`, `/api/schedules`, `/api/search-attributes`, `/api/service-endpoints`, `/api/service-catalog`. Verwaltungsrouten im Plural `/api/workers` zählen. + +Die singulären `/api/worker/*`-Routen für Registrierung, Polling und Ergebnisse verwenden dieses HTTP-Budget nicht. Health/Readiness, `/api/cluster/info`, Admin-Routen `/api/system/*`, Runtime-Zugangsdaten und externer Payload-Transport bleiben ebenfalls außerhalb; ihre eigenen Zugriffs-, Kapazitäts- und Speicherprüfungen gelten weiterhin. Frühere Ablehnungen durch Authentifizierung, Protokoll oder Namespace-Auflösung erreichen den Zähler nicht. + +Die Rate verwendet feste Minuten-Buckets der Serveruhr, keine geglättete oder gleitende Rate. Ein Budget N kann N Anfragen kurz vor der Grenze und weitere N danach zulassen. Später fehlschlagende Anfragen zählen weiter; die Ratenprüfung erfolgt vor der Gleichzeitigkeit, sodass eine Parallelitätsablehnung Minutenbudget verbrauchen kann. Der Parallelitätsslot bleibt bis zum Ende und zur Bereinigung der Anfrage belegt; er zählt keine laufenden Workflows. + +API-Replikate benötigen denselben gemeinsamen Redis-Speicher/Schlüsselpräfix, synchronisierte Uhren und konsistent geladene Konfiguration. Weitere Replikate multiplizieren das gemeinsame Budget nicht. Ein lokaler Dateicache koordiniert nur Prozesse mit kompatiblem Schreibzugriff; er ist nicht die Mehrknoten-Baseline. Knotenspezifische Grenzen gehaltener Worker-/Query-Polls gelten separat. [Starten Sie betroffene Rollen nach Umgebungsänderungen neu](./server-config-reference.md#how-changes-take-effect). + +```dotenv +DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE=100 +DW_NAMESPACE_MAX_CONCURRENT_REQUESTS=8 +DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE=150 +DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS=10 +DW_NAMESPACE_ADMISSION_OVERRIDES='{"payments":{"max_requests_per_minute":200,"max_concurrent_requests":12},"reports":{"max_requests_per_minute":40,"max_concurrent_requests":3}}' +``` + +Für vorhandene Namespaces ergibt das Beispiel bei `payments` 150 Anfragen/Minute und 10 gleichzeitige, bei `reports` 40/3, sonst 100/8. Overrides dürfen Vorgaben erhöhen oder senken, aber die harten Grenzen 150/10 bleiben bestehen. Die Konfiguration erzeugt keine Namespaces und reserviert keinen Durchsatz. + +Bei diesen HTTP-Kontrollen setzt ein fehlender Wert keine entsprechende Grenze; eine harte Obergrenze allein kann dennoch begrenzen. Ein `null`-Override fällt auf die Vorgabe zurück. Werte müssen positive ganze Zahlen sein: `0` ist ungültig. PHP-Obergrenzen sind 10000000 Anfragen/Minute und 1024 gleichzeitige Anfragen, unabhängig von der realen HTTP-Pool-Kapazität. Veröffentlichtes PHP 2.11.0 behandelt fehlerhaftes `DW_NAMESPACE_ADMISSION_OVERRIDES`-JSON stillschweigend als leere Overrides und nutzt globale Vorgaben. Validieren Sie JSON vor dem Deployment; ohne globale Vorgaben/harten Grenzen geht die beabsichtigte Namespace-Grenze verloren. Diese [bestätigte Produktlücke](https://github.com/durable-workflow/durable-workflow.github.io/issues/335#issuecomment-6369150521) wird durch Dokumentation nicht behoben. + +| Grund | HTTP | Wiederholhinweis in Sekunden | +| --- | --- | --- | +| `namespace_request_rate_exhausted` | `429` | Bis zur nächsten Minute, 1–60 | +| `namespace_request_concurrency_exhausted` | `429` | 1 | +| `namespace_request_admission_unavailable` | `503` | 1 | + +JSON `retry_after_seconds` und Header `Retry-After` stimmen überein. Nicht verfügbare konfigurierte Koordination oder ungültige numerische Grenzen führen zu 503. Namespace-bezogene Admin-Metriken bleiben auch bei erschöpften normalen Anfragen verfügbar; `dw_namespace_request_admission_rejections` meldet die begrenzten Gründe. Nutzen Sie begrenzte Caller-Retry-/Backoff-Richtlinien und Idempotenz; ein unsicherer Transportausgang erlaubt kein automatisches Wiederholen von Schreibvorgängen. Siehe [Timeout-Budgets](../deployment.md#worker-long-poll-timeout-budgets). + +## Kontingente für dauerhaften Namespace-Zustand {#namespace-durable-state} + +`DW_NAMESPACE_DURABLE_LIMITS` setzt Vorgaben für erhaltene Zeilen, `DW_NAMESPACE_DURABLE_OVERRIDES` ändert sie pro Namespace und `DW_NAMESPACE_DURABLE_HARD_LIMITS` ergänzt unübergehbare Obergrenzen. Leere Objekte fügen keine Grenzen hinzu. Overrides dürfen Vorgaben erhöhen oder senken; null fällt auf die Vorgabe zurück. Anders als bei HTTP ist ein dauerhaftes Kontingent 0 gültig und verhindert neue Belegungen. Hier kann vorhandenes `payments` 250 offene Runs halten, andere Namespaces 100, bei harter Grenze 500. + +```dotenv +DW_NAMESPACE_DURABLE_LIMITS='{"max_open_workflow_runs":100,"max_open_workflow_run_waits":200,"max_pending_workflow_timers":200}' +DW_NAMESPACE_DURABLE_HARD_LIMITS='{"max_open_workflow_runs":500}' +DW_NAMESPACE_DURABLE_OVERRIDES='{"payments":{"max_open_workflow_runs":250}}' +``` + +Verwenden Sie `max_` für folgende Ressourcen. Zeilen zählen im eigenen Namespace oder dem des verknüpften Workflows/Runs. Erhaltene Gesamtzahlen und offene/ausstehende Teilmengen werden unabhängig begrenzt. Maßgeblich sind Datenbankzählungen; Mutationen werden über die Namespace-Zeile serialisiert. + +| Ressource | Gezählte Zeilen | +| --- | --- | +| `workflow_instances`, `workflow_runs` | Alle erhaltenen Workflow-Instanz-/Run-Zeilen einschließlich terminaler Runs. | +| `open_workflow_runs` | Runs mit Status `pending`, `running` oder `waiting`. | +| `workflow_history_events`, `workflow_commands`, `workflow_tasks` | Erhaltene Historien-, Befehls- und Workflow-Task-Zeilen. | +| `pending_workflow_tasks` | Workflow-Task-Zeilen in der Queue mit Status `ready`; aktive Leases haben eigene Zulassungskontrollen. | +| `workflow_timers`, `pending_workflow_timers` | Alle erhaltenen Timer beziehungsweise die Teilmenge `pending`. | +| `workflow_run_waits`, `open_workflow_run_waits` | Alle erhaltenen Run-Wartezeilen beziehungsweise die Teilmenge `open`. | +| `schedules`, `schedule_history_events`, `worker_registrations` | Erhaltene Schedules, Schedule-Historie und Worker-Registrierungen; veraltete Registrierungen zählen bis zur Löschung. | +| `workflow_streams`, `workflow_stream_items` | Zeilen dauerhafter und eingehender Streams sowie ihrer Elemente. | + +Ein auf Kind oder Service-Aufruf wartender Elternworkflow belegt weiter einen offenen Run im eigenen Namespace. Das Kind ergänzt seinen Run; im selben Namespace müssen beide offenen Runs und ihre Wartezeiten/Timer eingeplant werden. Eine Service-Operation, die einen Workflow erzeugt, verbraucht Zeilen in dessen Namespace; Signal/Update auf einem bestehenden Run erzeugt nicht automatisch einen zweiten Run. Service-Aufruf- und externe Payload-Kontingente gelten separat. + +Erschöpfung liefert 429 `namespace__exhausted`. Prüfen Sie `retryable`: Manche Kontingente sind nicht wiederholbar und liefern keinen Wartehinweis; wiederholbare dauerhafte Ablehnungen nennen 60 Sekunden, ohne spätere Kapazität zu garantieren. Eine nicht auswertbare konfigurierte Quote liefert 503 `namespace_durable_state_quota_unavailable` mit einer Sekunde Wartehinweis. Erhaltene Zeilen können Retention oder eine Kapazitäts-/Konfigurationsänderung erfordern, keine enge Retry-Schleife. + +Wählen Sie beim Abruf von Admin-Metriken den Namespace per Header. `dw_namespace_durable_state_usage` und JSON-Felder `limits`, `usage`, `remaining`, `configuration_status`, `measurement_status` zeigen diesen Bereich; Namespace ist Anfragekontext statt unbegrenztes Metriklabel. Nicht verfügbare Messwerte bedeuten weder Nullnutzung noch unbegrenzte Kapazität. Siehe die [vollständige Referenz](./server-config-reference.md#namespace-durable-controls). + ## Server-Konfiguration {#server-configuration} Setzen Sie globale Grenzen, wenn alle Warteschlangen dieselbe Obergrenze haben sollen: diff --git a/i18n/de/source-hashes.json b/i18n/de/source-hashes.json index f3d1cd198fb..c384bb21231 100644 --- a/i18n/de/source-hashes.json +++ b/i18n/de/source-hashes.json @@ -86,12 +86,12 @@ "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", "polyglot/rust.md": "5ff66bcb7e5369bcffd8611342a35c27028cac5a4ee376e86d90334a2b12d365", "polyglot/server-api-reference.md": "e94af77a13b341d6fdc9941d4ee94e5053ab932d2e77069b238eb33351414e83", - "polyglot/server-config-reference.md": "edb4cf00b9df2c9946b32a81c6bb2c4db6eaee89794b85286c61c235a4846414", + "polyglot/server-config-reference.md": "b2dc3ddd188b078875cb46bf32b94053d89912c063c1687cc98ff5ba2baba812", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "7950b0c82dac2940c30b0aa042f3105dc9bdc70b524600cce4ed6d311cda7171", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", "polyglot/task-matching-dispatch.md": "9c8ffbbee16b5da48e7882721d7ba8eac209a374a6ca766d93d2b17e825b203d", - "polyglot/task-queue-admission.md": "47713eeaf3b10ead16b6b6c40816b97142d0f78670e40d181405db70ce49e7ac", + "polyglot/task-queue-admission.md": "ff04476dfca350f828d807b392d5e8b81c3c3baee252906021558a7eba6b936b", "polyglot/worker-build-id-rollout.md": "62ddf1ca054cf4b83de2fa020f313a153ece00519f804c4f8f30aca53c979af0", "polyglot/worker-compatibility-routing.md": "ef58f23c112f0e6b968927ba861177903adca21ed33b6b9371681e23a18b2994", "polyglot/worker-protocol.md": "007e844b0a7ab284b7cd343e79f01a27a0dabee3fe4cf19064170581bb897b85", 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 92216fda7b4..17b603fd841 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 @@ -271,6 +271,74 @@ Use `DW_V2_GUARDRAILS_BOOT` en CI y en los manifiestos de despliegue. El nombre Consulte [Asignación y despacho de tareas](/docs/polyglot/task-matching-dispatch) al configurar `DW_V2_MATCHING_ROLE_QUEUE_WAKE` o un daemon dedicado de `workflow:v2:repair-pass --loop`. Estas opciones cambian dónde se descubren las tareas listas, no el contrato del protocolo de workers. +## Controles adicionales del PHP Server publicado {#additional-published-php-controls} + +Esta referencia cubre el contrato publicado de **PHP Server 2.11.0**, incluidos los controles siguientes. Comprueba la imagen que ejecutas: la versión de instalación seleccionada por separado puede ser anterior. `unset` indica que no se proporciona un valor de entorno; su efecto depende del control. Los valores predeterminados y alias proceden del [contrato publicado](https://github.com/durable-workflow/server/blob/36d16273604755f3dd0743cab331cc7c62e51d8e/config/dw-contract.php). La compilación comprueba su snapshot versionado en todos los idiomas. Esta referencia no cambia el conjunto de versiones seleccionado. + +### Admisión HTTP por namespace {#namespace-request-controls} + +| Variable | Valor predeterminado | Propósito | Alias anterior | +| --- | --- | --- | --- | +| `DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | `unset` | Límite opcional de peticiones de control por minuto y namespace; sin valor no hay límite. | `WORKFLOW_SERVER_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_MAX_CONCURRENT_REQUESTS` | `unset` | Límite opcional de peticiones de control simultáneas por namespace; sin valor no hay límite. | `WORKFLOW_SERVER_NAMESPACE_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | `unset` | Techo obligatorio de peticiones por minuto, incluidas las excepciones por namespace. | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | `unset` | Techo obligatorio de peticiones simultáneas, incluidas las excepciones por namespace. | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_ADMISSION_OVERRIDES` | `{}` | Objeto JSON por namespace con excepciones de frecuencia y concurrencia de peticiones. | `WORKFLOW_SERVER_NAMESPACE_ADMISSION_OVERRIDES` | + +[Admisión de peticiones por namespace](./task-queue-admission.md#namespace-request-admission). + +### Cuotas de estado duradero por namespace {#namespace-durable-controls} + +| Variable | Valor predeterminado | Propósito | Alias anterior | +| --- | --- | --- | --- | +| `DW_NAMESPACE_DURABLE_LIMITS` | `{}` | JSON de cuotas de filas duraderas por namespace. Los totales y límites pending/open son independientes; las tareas pendientes son filas ready en cola, con leases activos limitados aparte. Un objeto vacío no limita. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_LIMITS` | +| `DW_NAMESPACE_DURABLE_HARD_LIMITS` | `{}` | JSON de techos obligatorios de filas duraderas, incluidas excepciones; un objeto vacío no añade techos del operador. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_HARD_LIMITS` | +| `DW_NAMESPACE_DURABLE_OVERRIDES` | `{}` | JSON de excepciones de cuotas duraderas por namespace; los techos obligatorios siguen vigentes. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_OVERRIDES` | + +[Cuotas de estado duradero por namespace](./task-queue-admission.md#namespace-durable-state). + +### Cuotas de payload externo y transporte S3 {#external-payload-quotas-and-s3} + +| Variable | Valor predeterminado | Propósito | Alias anterior | +| --- | --- | --- | --- | +| `DW_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | `unset` | Bytes distintos entre upload slots inmutables de un completion con lease; sin valor usa `DW_EXTERNAL_PAYLOAD_MAX_BYTES`. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | +| `DW_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | `unset` | Bytes acumulados de payloads externos por namespace. Cuenta objetos listos y en curso; sin valor no limita. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | Cantidad de objetos de payload externo por namespace. Cuenta objetos listos y en curso; sin valor no limita. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | `unset` | Techo obligatorio de bytes acumulados de payload externo por namespace, incluidas excepciones. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | Techo obligatorio de objetos de payload externo por namespace, incluidas excepciones. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | `{}` | Objeto JSON por namespace con excepciones de cuota `max_bytes` y `max_objects`. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | +| `DW_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | `unset` | Access-key ID opcional del disco S3 compatible gestionado por el runtime; puede omitirse con workload identity. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | +| `DW_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | `unset` | Clave secreta opcional del disco S3 compatible gestionado; debe configurarse junto al access-key ID. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | +| `DW_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | `unset` | Session token opcional de credenciales temporales del disco S3 compatible gestionado. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | +| `DW_EXTERNAL_PAYLOAD_S3_REGION` | `us-east-1` | Región del disco S3 compatible gestionado por el runtime. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_REGION` | +| `DW_EXTERNAL_PAYLOAD_S3_BUCKET` | `unset` | Bucket del disco S3 compatible gestionado por el runtime. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_BUCKET` | +| `DW_EXTERNAL_PAYLOAD_S3_ENDPOINT` | `unset` | Endpoint HTTPS opcional del servicio S3 compatible de payloads externos. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ENDPOINT` | +| `DW_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | `false` | Usar direccionamiento de bucket path-style para el servicio S3 compatible gestionado. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | + +### Límites de servicio por namespace llamador {#service-caller-namespace-controls} + +| Variable | Valor predeterminado | Propósito | Alias anterior | +| --- | --- | --- | --- | +| `DW_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | `unset` | Límite compartido opcional por minuto de llamadas de servicio, agregado por namespace llamador. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | `unset` | Límite compartido opcional de llamadas de servicio en curso, agregado por namespace llamador. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | `unset` | Techo obligatorio por minuto para políticas de límite de servicio y de namespace llamador. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | `unset` | Techo obligatorio de llamadas en curso para políticas de límite de servicio y de namespace llamador. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | `{}` | JSON de excepciones de frecuencia y llamadas en curso por namespace llamador; siguen aplicándose los techos. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | + +### Coordinación, almacenamiento y runtime {#coordination-storage-and-runtime-controls} + +| Variable | Valor predeterminado | Propósito | Alias anterior | +| --- | --- | --- | --- | +| `DW_OBSERVABILITY_CONTEXT_ENABLED` | `false` | Activar persistencia y entrega acotadas de trace context y descubrimiento cuando estén instaladas su API y su esquema opcionales. | - | +| `DW_OBSERVABILITY_BAGGAGE_ALLOWLIST` | `[]` | Lista JSON de claves baggage permitidas en los orígenes del run; vacía por defecto. Los links nunca llevan baggage. | - | +| `DW_STORAGE_ADMISSION_FILE` | `unset` | Archivo local opcional de observación de presión de almacenamiento, de solo lectura; observaciones inválidas o antiguas bloquean escrituras. | - | +| `DW_STORAGE_ADMISSION_SOURCE` | `unset` | Identidad esperada del recurso de almacenamiento en la observación de admisión. | - | +| `DW_STORAGE_ADMISSION_MAX_AGE_SECONDS` | `15` | Edad máxima de la observación de almacenamiento en segundos, entre 1 y 300. | - | +| `DW_RUNTIME_CREDENTIALS_ENABLED` | `false` | Activar credenciales bearer de runtime duraderas, ligadas al namespace y respaldadas por base de datos, mediante la API admin. | `WORKFLOW_SERVER_RUNTIME_CREDENTIALS_ENABLED` | +| `DW_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | Límite por nodo de esperas long-poll workflow/activity de un namespace; no supera el límite global de workers. Rechaza si no hay autoridad de caché compartida. | `WORKFLOW_SERVER_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | Límite por nodo de esperas long-poll query-task de un namespace; no supera el límite global de queries. Rechaza si no hay autoridad de caché compartida. | `WORKFLOW_SERVER_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_V1_ENABLED` | `false` | Activar migración y vaciado de cola embedded v1 solo para conservar deliberadamente su estado; Server independiente usa únicamente v2 por defecto. | `WORKFLOW_V1_ENABLED` | + ## Variables de infraestructura de ejecución {#runtime-infrastructure-variables} Las variables de infraestructura de ejecución controlan el framework y sus dependencias. La auditoría de Server las reconoce para no emitir advertencias, pero no son controles estables de la API de Durable Workflow. diff --git a/i18n/es/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md b/i18n/es/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md index f5217a99ee8..85b17632a48 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md @@ -92,6 +92,67 @@ Un breaker de aplicación abierto lanza `NonRetryableError` antes del pago; fall Mantenga las llamadas protegidas en **actividades normales encoladas**. Las actividades locales inline no crean una tarea de actividad normal y los límites de despacho por cola/namespace/grupo no las miden. Un claim local preparado valida autoridad de ejecución, no este presupuesto. Laravel integrado no tiene admission del Server independiente; use sus controles de despliegue. Véanse [actividades locales](../features/local-activities.md). +## Admisión de peticiones por namespace {#namespace-request-admission} + +Este contrato corresponde al **PHP Server 2.11.0** publicado. Comprueba tu imagen y la [referencia de configuración versionada](./server-config-reference.md#additional-published-php-controls). Los presupuestos HTTP son independientes de los slots de worker, el despacho, los polls retenidos y las cuotas duraderas. El presupuesto pertenece al namespace resuelto mediante `Durable-Workflow-Namespace` o `DW_DEFAULT_NAMESPACE`, incluso si una ruta administrativa nombra otro namespace. + +Las peticiones autenticadas que alcanzan la admisión se contabilizan en estas familias de rutas de control y gestión, incluidos sus descendientes: `/api/namespaces`, `/api/storage`, `/api/workflows`, `/api/activities`, `/api/bridge-adapters`, `/api/workers`, `/api/worker-sessions`, `/api/task-queues`, `/api/deployments`, `/api/schedules`, `/api/search-attributes`, `/api/service-endpoints`, `/api/service-catalog`. Las rutas de gestión en plural `/api/workers` cuentan. + +Las rutas en singular `/api/worker/*` de registro, polling y resultados no usan este presupuesto HTTP. Health/readiness, `/api/cluster/info`, las rutas admin `/api/system/*`, las credenciales runtime y el transporte de payload externo también quedan fuera; siguen aplicando sus propias comprobaciones de acceso, capacidad y almacenamiento. Los rechazos anteriores de autenticación, protocolo o resolución de namespace no llegan al contador. + +La frecuencia usa buckets de minutos fijos según el reloj del Server, no un ritmo uniforme ni una ventana móvil. Un presupuesto N puede admitir N peticiones justo antes del límite y otras N después. Los fallos posteriores siguen contando; la frecuencia se admite antes de comprobar la concurrencia, por lo que un rechazo de concurrencia puede consumir presupuesto del minuto. El slot simultáneo se mantiene hasta finalizar la petición y liberar sus recursos; no cuenta workflows en ejecución. + +Entre réplicas API, usa el mismo Redis compartido y prefijo de claves, relojes sincronizados y configuración cargada coherente. Añadir réplicas no multiplica el presupuesto compartido. Una caché local de archivos solo coordina procesos con acceso de escritura compatible; no es la configuración base multinodo. Los límites de polls worker/query retenidos por nodo son independientes. [Reinicia los roles afectados al cambiar el entorno](./server-config-reference.md#how-changes-take-effect). + +```dotenv +DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE=100 +DW_NAMESPACE_MAX_CONCURRENT_REQUESTS=8 +DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE=150 +DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS=10 +DW_NAMESPACE_ADMISSION_OVERRIDES='{"payments":{"max_requests_per_minute":200,"max_concurrent_requests":12},"reports":{"max_requests_per_minute":40,"max_concurrent_requests":3}}' +``` + +Para namespaces existentes, el ejemplo resuelve `payments` a 150 peticiones/minuto y 10 simultáneas, `reports` a 40/3 y los demás a 100/8. Las excepciones pueden subir o bajar los valores predeterminados, pero siguen aplicándose los techos 150/10. Esta configuración no crea namespaces ni reserva rendimiento. + +Para estos controles HTTP, un valor ausente no configura ese límite; un techo obligatorio por sí solo puede imponerlo. Una excepción null vuelve al valor predeterminado. Los valores deben ser enteros positivos: cero es inválido. Los techos de implementación PHP son 10000000 peticiones/minuto y 1024 simultáneas, independientemente de la capacidad real del pool HTTP. PHP 2.11.0 publicado interpreta silenciosamente JSON malformado en `DW_NAMESPACE_ADMISSION_OVERRIDES` como excepciones vacías y vuelve a los valores globales. Valida el JSON antes del despliegue; sin valores globales ni techos obligatorios se pierde el límite previsto. Esta [deficiencia confirmada del producto](https://github.com/durable-workflow/durable-workflow.github.io/issues/335#issuecomment-6369150521) sigue separada de la actualización documental. + +| Motivo | HTTP | Espera sugerida en segundos | +| --- | --- | --- | +| `namespace_request_rate_exhausted` | `429` | Hasta el próximo minuto, 1–60 | +| `namespace_request_concurrency_exhausted` | `429` | 1 | +| `namespace_request_admission_unavailable` | `503` | 1 | + +El JSON `retry_after_seconds` coincide con la cabecera `Retry-After`. Una coordinación configurada no disponible o límites numéricos inválidos rechaza con 503. Consulta las métricas admin del namespace aunque el presupuesto ordinario esté agotado; `dw_namespace_request_admission_rejections` expone los motivos acotados. Aplica una política limitada de retry/backoff del llamador e idempotencia; un resultado de transporte incierto no autoriza a repetir una escritura automáticamente. Consulta los [presupuestos de timeout](../deployment.md#worker-long-poll-timeout-budgets). + +## Cuotas de estado duradero por namespace {#namespace-durable-state} + +`DW_NAMESPACE_DURABLE_LIMITS` fija límites predeterminados de filas conservadas, `DW_NAMESPACE_DURABLE_OVERRIDES` los cambia por namespace y `DW_NAMESPACE_DURABLE_HARD_LIMITS` añade techos obligatorios. Los objetos vacíos no añaden límites. Las excepciones pueden subir o bajar valores; null vuelve al predeterminado. A diferencia de la admisión HTTP, una cuota duradera cero es válida e impide nuevas asignaciones. Aquí `payments` existente puede mantener 250 runs abiertos y los demás namespaces 100, bajo un techo de 500. + +```dotenv +DW_NAMESPACE_DURABLE_LIMITS='{"max_open_workflow_runs":100,"max_open_workflow_run_waits":200,"max_pending_workflow_timers":200}' +DW_NAMESPACE_DURABLE_HARD_LIMITS='{"max_open_workflow_runs":500}' +DW_NAMESPACE_DURABLE_OVERRIDES='{"payments":{"max_open_workflow_runs":250}}' +``` + +Usa campos `max_` para los recursos siguientes. Cada fila cuenta en su namespace propietario o en el de su workflow/run asociado. Los totales conservados y los subconjuntos abiertos/pendientes tienen límites independientes. Se usan recuentos autoritativos de la base de datos, serializando las mutaciones mediante la fila del namespace. + +| Recurso | Qué cuenta | +| --- | --- | +| `workflow_instances`, `workflow_runs` | Todas las filas conservadas de instancias/runs de workflow, incluidos runs terminales. | +| `open_workflow_runs` | Runs con estado `pending`, `running` o `waiting`. | +| `workflow_history_events`, `workflow_commands`, `workflow_tasks` | Filas conservadas de historial, comandos y tareas de workflow. | +| `pending_workflow_tasks` | Filas de tareas de workflow en cola con estado `ready`; los leases activos tienen controles separados. | +| `workflow_timers`, `pending_workflow_timers` | Todos los temporizadores conservados y el subconjunto `pending`, respectivamente. | +| `workflow_run_waits`, `open_workflow_run_waits` | Todas las esperas de run conservadas y el subconjunto `open`, respectivamente. | +| `schedules`, `schedule_history_events`, `worker_registrations` | Schedules, historial y registros de workers conservados; los registros obsoletos cuentan hasta borrarse. | +| `workflow_streams`, `workflow_stream_items` | Filas de streams duraderos y entrantes, y filas de sus elementos. | + +Un padre que espera un hijo o una llamada de servicio sigue consumiendo un run abierto en su namespace. El hijo añade su run; si comparten namespace, planifica ambos runs abiertos y sus esperas/temporizadores. Una operación de servicio que crea un workflow consume filas en el namespace de ese workflow; signal/update sobre un run existente no crea automáticamente otro run. Los límites de llamadas de servicio y payload externo son independientes. + +El agotamiento devuelve 429 `namespace__exhausted`. Lee `retryable`: algunas cuotas no admiten reintento ni sugieren espera; los rechazos duraderos reintentables anuncian 60 segundos, sin prometer capacidad entonces. Si no puede evaluarse una cuota configurada, devuelve 503 `namespace_durable_state_quota_unavailable` con un segundo de espera. La presión de filas conservadas puede exigir retención o un cambio de capacidad/configuración, no un bucle de retries. + +Selecciona el namespace mediante la cabecera al consultar métricas admin. `dw_namespace_durable_state_usage` y los campos JSON `limits`, `usage`, `remaining`, `configuration_status` y `measurement_status` muestran ese ámbito; el namespace pertenece a la petición, no es una etiqueta de métricas ilimitada. Una medición no disponible no significa uso cero ni capacidad ilimitada. Consulta la [referencia completa](./server-config-reference.md#namespace-durable-controls). + ## Configuración del servidor {#server-configuration} Configura límites globales cuando todas las colas deban tener el mismo techo: diff --git a/i18n/es/source-hashes.json b/i18n/es/source-hashes.json index f3d1cd198fb..c384bb21231 100644 --- a/i18n/es/source-hashes.json +++ b/i18n/es/source-hashes.json @@ -86,12 +86,12 @@ "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", "polyglot/rust.md": "5ff66bcb7e5369bcffd8611342a35c27028cac5a4ee376e86d90334a2b12d365", "polyglot/server-api-reference.md": "e94af77a13b341d6fdc9941d4ee94e5053ab932d2e77069b238eb33351414e83", - "polyglot/server-config-reference.md": "edb4cf00b9df2c9946b32a81c6bb2c4db6eaee89794b85286c61c235a4846414", + "polyglot/server-config-reference.md": "b2dc3ddd188b078875cb46bf32b94053d89912c063c1687cc98ff5ba2baba812", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "7950b0c82dac2940c30b0aa042f3105dc9bdc70b524600cce4ed6d311cda7171", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", "polyglot/task-matching-dispatch.md": "9c8ffbbee16b5da48e7882721d7ba8eac209a374a6ca766d93d2b17e825b203d", - "polyglot/task-queue-admission.md": "47713eeaf3b10ead16b6b6c40816b97142d0f78670e40d181405db70ce49e7ac", + "polyglot/task-queue-admission.md": "ff04476dfca350f828d807b392d5e8b81c3c3baee252906021558a7eba6b936b", "polyglot/worker-build-id-rollout.md": "62ddf1ca054cf4b83de2fa020f313a153ece00519f804c4f8f30aca53c979af0", "polyglot/worker-compatibility-routing.md": "ef58f23c112f0e6b968927ba861177903adca21ed33b6b9371681e23a18b2994", "polyglot/worker-protocol.md": "007e844b0a7ab284b7cd343e79f01a27a0dabee3fe4cf19064170581bb897b85", 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 706bfdb8ba2..4cbd4e5361a 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 @@ -271,6 +271,74 @@ Utilisez `DW_V2_GUARDRAILS_BOOT` dans la CI et les manifestes de déploiement. L Consultez [Attribution et distribution des tâches](/docs/polyglot/task-matching-dispatch) pour configurer `DW_V2_MATCHING_ROLE_QUEUE_WAKE` ou un démon dédié `workflow:v2:repair-pass --loop`. Ces paramètres changent l’emplacement de la détection des tâches prêtes, pas le contrat du protocole worker. +## Contrôles supplémentaires du PHP Server publié {#additional-published-php-controls} + +Cette référence couvre le contrat publié de **PHP Server 2.11.0**, dont les contrôles ci-dessous. Vérifiez l’image réellement exécutée : la version d’installation choisie séparément peut être plus ancienne. `unset` signifie qu’aucune valeur d’environnement n’est fournie ; son effet dépend du contrôle. Valeurs par défaut et alias viennent du [contrat publié](https://github.com/durable-workflow/server/blob/36d16273604755f3dd0743cab331cc7c62e51d8e/config/dw-contract.php). Le build vérifie son snapshot versionné dans chaque langue. Cette référence ne modifie pas les versions d’installation sélectionnées. + +### Admission HTTP par namespace {#namespace-request-controls} + +| Variable | Valeur par défaut | Rôle | Ancien alias | +| --- | --- | --- | --- | +| `DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | `unset` | Plafond facultatif des requêtes de contrôle par minute et namespace ; aucune limite si absent. | `WORKFLOW_SERVER_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_MAX_CONCURRENT_REQUESTS` | `unset` | Plafond facultatif des requêtes de contrôle simultanées par namespace ; aucune limite si absent. | `WORKFLOW_SERVER_NAMESPACE_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | `unset` | Plafond impératif des requêtes par minute, y compris les exceptions par namespace. | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | `unset` | Plafond impératif des requêtes simultanées, y compris les exceptions par namespace. | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_ADMISSION_OVERRIDES` | `{}` | Objet JSON par namespace avec exceptions de fréquence et de concurrence des requêtes. | `WORKFLOW_SERVER_NAMESPACE_ADMISSION_OVERRIDES` | + +[Admission des requêtes par namespace](./task-queue-admission.md#namespace-request-admission). + +### Quotas d’état durable par namespace {#namespace-durable-controls} + +| Variable | Valeur par défaut | Rôle | Ancien alias | +| --- | --- | --- | --- | +| `DW_NAMESPACE_DURABLE_LIMITS` | `{}` | JSON des quotas de lignes durables par namespace. Totaux et limites pending/open sont indépendants ; les tâches en attente sont les lignes ready en file, les leases actifs étant limités séparément. Un objet vide ne limite pas. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_LIMITS` | +| `DW_NAMESPACE_DURABLE_HARD_LIMITS` | `{}` | JSON des plafonds impératifs de lignes durables, exceptions comprises ; un objet vide n’ajoute aucun plafond opérateur. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_HARD_LIMITS` | +| `DW_NAMESPACE_DURABLE_OVERRIDES` | `{}` | JSON des exceptions de quotas durables par namespace ; les plafonds impératifs restent applicables. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_OVERRIDES` | + +[Quotas d’état durable par namespace](./task-queue-admission.md#namespace-durable-state). + +### Quotas de payload externe et transport S3 {#external-payload-quotas-and-s3} + +| Variable | Valeur par défaut | Rôle | Ancien alias | +| --- | --- | --- | --- | +| `DW_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | `unset` | Octets distincts des upload slots immuables d’un completion sous lease ; si absent, utilise `DW_EXTERNAL_PAYLOAD_MAX_BYTES`. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | +| `DW_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | `unset` | Octets cumulés des payloads externes par namespace. Compte les objets prêts et en cours ; aucune limite si absent. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | Nombre d’objets de payload externe par namespace. Compte les objets prêts et en cours ; aucune limite si absent. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | `unset` | Plafond impératif des octets cumulés de payload externe par namespace, exceptions comprises. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | Plafond impératif des objets de payload externe par namespace, exceptions comprises. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | `{}` | Objet JSON par namespace avec exceptions de quotas `max_bytes` et `max_objects`. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | +| `DW_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | `unset` | Access-key ID facultatif du disque compatible S3 géré par le runtime ; peut être omis avec workload identity. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | +| `DW_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | `unset` | Clé secrète facultative du disque compatible S3 géré ; à définir avec l’access-key ID. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | +| `DW_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | `unset` | Session token facultatif des identifiants temporaires du disque compatible S3 géré. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | +| `DW_EXTERNAL_PAYLOAD_S3_REGION` | `us-east-1` | Région du disque compatible S3 géré par le runtime. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_REGION` | +| `DW_EXTERNAL_PAYLOAD_S3_BUCKET` | `unset` | Bucket du disque compatible S3 géré par le runtime. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_BUCKET` | +| `DW_EXTERNAL_PAYLOAD_S3_ENDPOINT` | `unset` | Endpoint HTTPS facultatif du service compatible S3 pour les payloads externes. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ENDPOINT` | +| `DW_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | `false` | Utiliser l’adressage de bucket path-style pour le service compatible S3 géré. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | + +### Limites de service par namespace appelant {#service-caller-namespace-controls} + +| Variable | Valeur par défaut | Rôle | Ancien alias | +| --- | --- | --- | --- | +| `DW_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | `unset` | Limite facultative partagée des appels de service par minute, agrégée par namespace appelant. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | `unset` | Limite facultative partagée des appels de service en cours, agrégée par namespace appelant. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | `unset` | Plafond impératif par minute des politiques de frontière de service et de namespace appelant. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | `unset` | Plafond impératif des appels en cours des politiques de frontière de service et de namespace appelant. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | `{}` | JSON des exceptions de fréquence et d’appels en cours par namespace appelant ; les plafonds restent applicables. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | + +### Coordination, stockage et runtime {#coordination-storage-and-runtime-controls} + +| Variable | Valeur par défaut | Rôle | Ancien alias | +| --- | --- | --- | --- | +| `DW_OBSERVABILITY_CONTEXT_ENABLED` | `false` | Activer la persistance et la transmission bornées du trace context et la découverte lorsque leur API et leur schéma optionnels sont installés. | - | +| `DW_OBSERVABILITY_BAGGAGE_ALLOWLIST` | `[]` | Liste JSON des clés baggage autorisées aux origines du run ; vide par défaut. Les links ne transportent jamais de baggage. | - | +| `DW_STORAGE_ADMISSION_FILE` | `unset` | Fichier local facultatif d’observation de pression du stockage, en lecture seule ; les observations invalides ou anciennes bloquent les écritures. | - | +| `DW_STORAGE_ADMISSION_SOURCE` | `unset` | Identité attendue de la ressource de stockage dans l’observation d’admission. | - | +| `DW_STORAGE_ADMISSION_MAX_AGE_SECONDS` | `15` | Âge maximal de l’observation de stockage en secondes, de 1 à 300. | - | +| `DW_RUNTIME_CREDENTIALS_ENABLED` | `false` | Activer des identifiants bearer de runtime durables, liés au namespace et stockés en base, via l’API admin. | `WORKFLOW_SERVER_RUNTIME_CREDENTIALS_ENABLED` | +| `DW_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | Limite par nœud des attentes long-poll workflow/activity d’un namespace ; ne dépasse pas le plafond global des workers. Refuse si l’autorité du cache partagé est indisponible. | `WORKFLOW_SERVER_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | Limite par nœud des attentes long-poll query-task d’un namespace ; ne dépasse pas le plafond global des queries. Refuse si l’autorité du cache partagé est indisponible. | `WORKFLOW_SERVER_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_V1_ENABLED` | `false` | Activer migration et vidage de file embedded v1 seulement pour conserver délibérément son état ; Server autonome utilise uniquement v2 par défaut. | `WORKFLOW_V1_ENABLED` | + ## Variables de l’infrastructure d’exécution {#runtime-infrastructure-variables} Les variables d’infrastructure règlent le framework et ses dépendances. L’audit Server les reconnaît et ne les signale pas, mais elles ne constituent pas une API de configuration stable de Durable Workflow. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md b/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md index 6ccfa1ad2b3..5037005a1a7 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md @@ -115,6 +115,67 @@ Un breaker applicatif ouvert lève `NonRetryableError` avant le paiement ; les e Gardez les appels protégés dans des **activités ordinaires en file**. Les activités locales inline ne créent aucune tâche d’activité ordinaire ; les plafonds de dispatch par file/namespace/groupe ne les mesurent pas. Une acquisition locale préparée valide l’autorité d’exécution, pas ce budget. Laravel embarqué n’a pas l’admission du Server autonome ; utilisez ses propres contrôles de déploiement. Voir les [activités locales](../features/local-activities.md). +## Admission des requêtes par namespace {#namespace-request-admission} + +Ce contrat concerne le **PHP Server 2.11.0** publié. Vérifiez votre image et la [référence de configuration versionnée](./server-config-reference.md#additional-published-php-controls). Les budgets HTTP sont distincts des slots de worker, du dispatch, des polls retenus et des quotas durables. Le budget appartient au namespace résolu par `Durable-Workflow-Namespace` ou `DW_DEFAULT_NAMESPACE`, même si une route administrative désigne un autre namespace. + +Les requêtes authentifiées atteignant l’admission sont comptées pour ces familles de routes de contrôle et de gestion, descendants compris : `/api/namespaces`, `/api/storage`, `/api/workflows`, `/api/activities`, `/api/bridge-adapters`, `/api/workers`, `/api/worker-sessions`, `/api/task-queues`, `/api/deployments`, `/api/schedules`, `/api/search-attributes`, `/api/service-endpoints`, `/api/service-catalog`. Les routes de gestion au pluriel `/api/workers` comptent. + +Les routes au singulier `/api/worker/*` d’enregistrement, polling et résultats n’utilisent pas ce budget HTTP. Health/readiness, `/api/cluster/info`, les routes admin `/api/system/*`, les identifiants runtime et le transport de payload externe restent aussi hors de ce contrôle ; leurs propres vérifications d’accès, capacité et stockage demeurent. Les refus antérieurs d’authentification, protocole ou résolution de namespace n’atteignent pas le compteur. + +La fréquence utilise des buckets de minutes fixes selon l’horloge du Server, pas un débit lissé ou une fenêtre glissante. Un budget N peut admettre N requêtes juste avant la limite et N autres après. Les erreurs ultérieures restent comptées ; la fréquence est admise avant la concurrence, donc un refus de concurrence peut consommer le budget de la minute. Le slot simultané reste occupé jusqu’à la fin et au nettoyage de la requête ; il ne compte pas les workflows actifs. + +Entre réplicas API, utilisez le même Redis partagé et préfixe de clés, des horloges synchronisées et une configuration chargée cohérente. Ajouter des réplicas ne multiplie pas le budget partagé. Un cache de fichiers local ne coordonne que les processus ayant un accès en écriture compatible ; ce n’est pas la configuration multinœud de référence. Les limites par nœud de polls worker/query retenus restent distinctes. [Redémarrez les rôles concernés après un changement d’environnement](./server-config-reference.md#how-changes-take-effect). + +```dotenv +DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE=100 +DW_NAMESPACE_MAX_CONCURRENT_REQUESTS=8 +DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE=150 +DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS=10 +DW_NAMESPACE_ADMISSION_OVERRIDES='{"payments":{"max_requests_per_minute":200,"max_concurrent_requests":12},"reports":{"max_requests_per_minute":40,"max_concurrent_requests":3}}' +``` + +Pour des namespaces existants, cet exemple donne à `payments` 150 requêtes/minute et 10 simultanées, à `reports` 40/3 et aux autres 100/8. Les exceptions peuvent relever ou abaisser les valeurs par défaut, mais les plafonds 150/10 restent applicables. Cette configuration ne crée pas de namespace et ne réserve aucun débit. + +Pour ces contrôles HTTP, une valeur absente n’ajoute pas cette limite ; un plafond impératif seul peut toutefois la fixer. Une exception null revient à la valeur par défaut. Les valeurs doivent être des entiers positifs : zéro est invalide. Les plafonds PHP sont 10000000 requêtes/minute et 1024 simultanées, indépendamment de la capacité réelle du pool HTTP. PHP 2.11.0 publié traite silencieusement un JSON mal formé de `DW_NAMESPACE_ADMISSION_OVERRIDES` comme des exceptions vides, revenant aux valeurs globales. Validez le JSON avant déploiement ; sans valeurs globales ni plafonds, la limite prévue disparaît. Cette [lacune produit confirmée](https://github.com/durable-workflow/durable-workflow.github.io/issues/335#issuecomment-6369150521) reste distincte de la documentation. + +| Motif | HTTP | Attente suggérée en secondes | +| --- | --- | --- | +| `namespace_request_rate_exhausted` | `429` | Jusqu’à la prochaine minute, 1–60 | +| `namespace_request_concurrency_exhausted` | `429` | 1 | +| `namespace_request_admission_unavailable` | `503` | 1 | + +Le JSON `retry_after_seconds` correspond à l’en-tête `Retry-After`. Une coordination configurée indisponible ou des limites numériques invalides provoquent un refus 503. Les métriques admin du namespace restent consultables après épuisement des requêtes ordinaires ; `dw_namespace_request_admission_rejections` expose les motifs bornés. Appliquez un retry/backoff borné côté appelant et l’idempotence ; un résultat de transport incertain ne permet pas de renvoyer une écriture automatiquement. Voir les [budgets de timeout](../deployment.md#worker-long-poll-timeout-budgets). + +## Quotas d’état durable par namespace {#namespace-durable-state} + +`DW_NAMESPACE_DURABLE_LIMITS` définit les limites par défaut des lignes conservées, `DW_NAMESPACE_DURABLE_OVERRIDES` les modifie par namespace et `DW_NAMESPACE_DURABLE_HARD_LIMITS` ajoute des plafonds impératifs. Les objets vides n’ajoutent aucune limite. Les exceptions peuvent augmenter ou réduire les valeurs ; null revient au défaut. Contrairement à l’admission HTTP, zéro est un quota durable valide et empêche de nouvelles allocations. Ici, `payments` existant peut conserver 250 runs ouverts, les autres namespaces 100, sous un plafond 500. + +```dotenv +DW_NAMESPACE_DURABLE_LIMITS='{"max_open_workflow_runs":100,"max_open_workflow_run_waits":200,"max_pending_workflow_timers":200}' +DW_NAMESPACE_DURABLE_HARD_LIMITS='{"max_open_workflow_runs":500}' +DW_NAMESPACE_DURABLE_OVERRIDES='{"payments":{"max_open_workflow_runs":250}}' +``` + +Utilisez les champs `max_` pour les ressources suivantes. Les lignes comptent dans leur namespace propriétaire ou celui du workflow/run associé. Totaux conservés et sous-ensembles ouverts/en attente ont des limites indépendantes. L’application utilise les comptes faisant autorité en base, avec sérialisation des mutations sur la ligne du namespace. + +| Ressource | Éléments comptés | +| --- | --- | +| `workflow_instances`, `workflow_runs` | Toutes les lignes conservées d’instances/runs de workflow, runs terminaux compris. | +| `open_workflow_runs` | Runs à l’état `pending`, `running` ou `waiting`. | +| `workflow_history_events`, `workflow_commands`, `workflow_tasks` | Lignes conservées d’historique, commandes et tâches de workflow. | +| `pending_workflow_tasks` | Lignes de tâches de workflow en file à l’état `ready` ; les leases actifs ont des contrôles distincts. | +| `workflow_timers`, `pending_workflow_timers` | Tous les timers conservés et leur sous-ensemble `pending`, respectivement. | +| `workflow_run_waits`, `open_workflow_run_waits` | Toutes les attentes de run conservées et leur sous-ensemble `open`, respectivement. | +| `schedules`, `schedule_history_events`, `worker_registrations` | Schedules, historique et enregistrements de workers conservés ; les enregistrements obsolètes comptent jusqu’à suppression. | +| `workflow_streams`, `workflow_stream_items` | Lignes des streams durables et entrants, et de leurs éléments. | + +Un parent attendant un enfant ou un appel de service consomme toujours un run ouvert dans son namespace. L’enfant ajoute son run ; dans un même namespace, prévoyez les deux runs ouverts et leurs attentes/timers. Une opération de service créant un workflow consomme des lignes dans son namespace ; signal/update sur un run existant ne crée pas automatiquement un second run. Les quotas d’appels de service et de payload externe sont distincts. + +L’épuisement renvoie 429 `namespace__exhausted`. Lisez `retryable` : certains quotas ne sont pas réessayables et n’indiquent pas d’attente ; les refus durables réessayables annoncent 60 secondes sans promettre de capacité ensuite. L’évaluation impossible d’un quota configuré renvoie 503 `namespace_durable_state_quota_unavailable`, avec une seconde d’attente. La pression des lignes conservées peut nécessiter rétention ou changement de capacité/configuration, pas une boucle de retries. + +Choisissez le namespace par l’en-tête lors des lectures de métriques admin. `dw_namespace_durable_state_usage` et les champs JSON `limits`, `usage`, `remaining`, `configuration_status` et `measurement_status` exposent ce périmètre ; le namespace relève de la requête et n’est pas un label illimité. Une mesure indisponible ne signifie ni usage nul ni capacité illimitée. Voir la [référence complète](./server-config-reference.md#namespace-durable-controls). + ## Configuration du serveur {#server-configuration} Définissez des plafonds globaux si chaque file doit avoir la même limite : diff --git a/i18n/fr/source-hashes.json b/i18n/fr/source-hashes.json index f3d1cd198fb..c384bb21231 100644 --- a/i18n/fr/source-hashes.json +++ b/i18n/fr/source-hashes.json @@ -86,12 +86,12 @@ "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", "polyglot/rust.md": "5ff66bcb7e5369bcffd8611342a35c27028cac5a4ee376e86d90334a2b12d365", "polyglot/server-api-reference.md": "e94af77a13b341d6fdc9941d4ee94e5053ab932d2e77069b238eb33351414e83", - "polyglot/server-config-reference.md": "edb4cf00b9df2c9946b32a81c6bb2c4db6eaee89794b85286c61c235a4846414", + "polyglot/server-config-reference.md": "b2dc3ddd188b078875cb46bf32b94053d89912c063c1687cc98ff5ba2baba812", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "7950b0c82dac2940c30b0aa042f3105dc9bdc70b524600cce4ed6d311cda7171", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", "polyglot/task-matching-dispatch.md": "9c8ffbbee16b5da48e7882721d7ba8eac209a374a6ca766d93d2b17e825b203d", - "polyglot/task-queue-admission.md": "47713eeaf3b10ead16b6b6c40816b97142d0f78670e40d181405db70ce49e7ac", + "polyglot/task-queue-admission.md": "ff04476dfca350f828d807b392d5e8b81c3c3baee252906021558a7eba6b936b", "polyglot/worker-build-id-rollout.md": "62ddf1ca054cf4b83de2fa020f313a153ece00519f804c4f8f30aca53c979af0", "polyglot/worker-compatibility-routing.md": "ef58f23c112f0e6b968927ba861177903adca21ed33b6b9371681e23a18b2994", "polyglot/worker-protocol.md": "007e844b0a7ab284b7cd343e79f01a27a0dabee3fe4cf19064170581bb897b85", 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 31c890ea3ce..b9578544b79 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 @@ -271,6 +271,74 @@ CI とデプロイ用マニフェストには `DW_V2_GUARDRAILS_BOOT` を使用 `DW_V2_MATCHING_ROLE_QUEUE_WAKE` または専用の `workflow:v2:repair-pass --loop` デーモンを設定する場合は、[タスクのマッチングと配信](/docs/polyglot/task-matching-dispatch)を参照してください。これらの設定は実行可能タスクを検出する場所を変えるものであり、Worker プロトコルの契約自体を変えるものではありません。 +## 公開済み PHP Server の追加設定 {#additional-published-php-controls} + +このリファレンスは、以下の設定を含む公開済み **PHP Server 2.11.0** の契約を対象にします。実際に使うイメージを確認してください。独立に選ばれたインストール版は旧版の場合があります。`unset` は環境変数の値が未設定であることを示し、その効果は設定ごとに異なります。既定値と旧名は[公開済み契約](https://github.com/durable-workflow/server/blob/36d16273604755f3dd0743cab331cc7c62e51d8e/config/dw-contract.php)に基づきます。ドキュメントのビルドでは、このバージョン付き契約 snapshot を全言語で検査します。選択済みのインストール版の組み合わせは変わりません。 + +### namespace ごとの HTTP 受付制限 {#namespace-request-controls} + +| 変数 | 既定値 | 目的 | 旧名 | +| --- | --- | --- | --- | +| `DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | `unset` | namespace ごとの1分間の制御プレーン要求数の任意上限。未設定なら無制限です。 | `WORKFLOW_SERVER_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_MAX_CONCURRENT_REQUESTS` | `unset` | namespace ごとの同時制御プレーン要求数の任意上限。未設定なら無制限です。 | `WORKFLOW_SERVER_NAMESPACE_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | `unset` | namespace の上書きにも適用される、回避できない1分間の要求数上限。 | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | `unset` | namespace の上書きにも適用される、回避できない同時要求数上限。 | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_ADMISSION_OVERRIDES` | `{}` | namespace をキーに、要求頻度と同時数を上書きする JSON オブジェクト。 | `WORKFLOW_SERVER_NAMESPACE_ADMISSION_OVERRIDES` | + +[namespace ごとのリクエスト受付制限](./task-queue-admission.md#namespace-request-admission). + +### namespace の永続状態クォータ {#namespace-durable-controls} + +| 変数 | 既定値 | 目的 | 旧名 | +| --- | --- | --- | --- | +| `DW_NAMESPACE_DURABLE_LIMITS` | `{}` | namespace の永続行数の既定クォータを指定する JSON。総数と pending/open の制限は独立です。pending tasks はキューの ready 行を数え、active lease は別に制限します。空オブジェクトは無制限です。 | `WORKFLOW_SERVER_NAMESPACE_DURABLE_LIMITS` | +| `DW_NAMESPACE_DURABLE_HARD_LIMITS` | `{}` | 上書きにも適用される、回避できない永続行数の上限を指定する JSON。空オブジェクトは運用者の上限を追加しません。 | `WORKFLOW_SERVER_NAMESPACE_DURABLE_HARD_LIMITS` | +| `DW_NAMESPACE_DURABLE_OVERRIDES` | `{}` | namespace ごとの永続行数クォータの上書き JSON。hard limit は引き続き適用されます。 | `WORKFLOW_SERVER_NAMESPACE_DURABLE_OVERRIDES` | + +[namespace の永続状態クォータ](./task-queue-admission.md#namespace-durable-state). + +### 外部 payload のクォータと S3 転送 {#external-payload-quotas-and-s3} + +| 変数 | 既定値 | 目的 | 旧名 | +| --- | --- | --- | --- | +| `DW_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | `unset` | lease 付き completion の不変 upload slots 全体での異なるバイト数。未設定なら `DW_EXTERNAL_PAYLOAD_MAX_BYTES` を使います。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | +| `DW_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | `unset` | namespace の外部 payload の累積バイト上限。準備済みと処理中のオブジェクトを数え、未設定なら無制限です。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | namespace の外部 payload のオブジェクト数上限。準備済みと処理中を数え、未設定なら無制限です。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | `unset` | namespace の上書きにも適用される、外部 payload の累積バイト数の hard limit。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | namespace の上書きにも適用される、外部 payload のオブジェクト数の hard limit。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | `{}` | namespace をキーに `max_bytes` と `max_objects` のクォータを上書きする JSON。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | +| `DW_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | `unset` | runtime 管理の S3 互換ディスクの任意 access-key ID。workload identity が認証情報を提供する場合は省略できます。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | +| `DW_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | `unset` | 管理対象 S3 互換ディスクの任意 secret access key。access-key ID と一緒に指定します。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | +| `DW_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | `unset` | 管理対象 S3 互換ディスクの一時認証情報に使う任意 session token。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | +| `DW_EXTERNAL_PAYLOAD_S3_REGION` | `us-east-1` | runtime 管理の S3 互換ディスクのリージョン。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_REGION` | +| `DW_EXTERNAL_PAYLOAD_S3_BUCKET` | `unset` | runtime 管理の S3 互換ディスクの bucket。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_BUCKET` | +| `DW_EXTERNAL_PAYLOAD_S3_ENDPOINT` | `unset` | 外部 payload の S3 互換サービスに使う任意 HTTPS endpoint。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ENDPOINT` | +| `DW_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | `false` | 管理対象 S3 互換サービスで bucket の path-style アドレスを使います。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | + +### 呼び出し元 namespace のサービス境界 {#service-caller-namespace-controls} + +| 変数 | 既定値 | 目的 | 旧名 | +| --- | --- | --- | --- | +| `DW_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | `unset` | 呼び出し元 namespace 全体で集計する、1分間のサービス呼び出し数の任意共有上限。 | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | `unset` | 呼び出し元 namespace 全体で集計する、実行中サービス呼び出し数の任意共有上限。 | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | `unset` | サービス境界と呼び出し元 namespace のポリシーに適用する、回避できない1分間の上限。 | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | `unset` | サービス境界と呼び出し元 namespace のポリシーに適用する、回避できない実行中呼び出し数の上限。 | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | `{}` | 呼び出し元 namespace ごとに頻度と実行中呼び出し数を上書きする JSON。hard limit は引き続き適用されます。 | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | + +### 連携、ストレージ、runtime {#coordination-storage-and-runtime-controls} + +| 変数 | 既定値 | 目的 | 旧名 | +| --- | --- | --- | --- | +| `DW_OBSERVABILITY_CONTEXT_ENABLED` | `false` | 任意の API と schema がインストール済みの場合、制限付き trace context の永続化・配送・discovery を有効にします。 | - | +| `DW_OBSERVABILITY_BAGGAGE_ALLOWLIST` | `[]` | run の起点に許可する baggage key の JSON 配列。既定は空です。link に baggage は含めません。 | - | +| `DW_STORAGE_ADMISSION_FILE` | `unset` | ストレージ逼迫の観測を読む任意のローカル読み取り専用ファイル。無効または古い観測は書き込みを拒否します。 | - | +| `DW_STORAGE_ADMISSION_SOURCE` | `unset` | 受付判断用の観測に含まれるストレージリソースの想定識別子。 | - | +| `DW_STORAGE_ADMISSION_MAX_AGE_SECONDS` | `15` | ストレージ観測の最大経過秒数。1〜300秒です。 | - | +| `DW_RUNTIME_CREDENTIALS_ENABLED` | `false` | データベースに永続化され namespace に束縛された runtime bearer 認証情報を admin API で管理できるようにします。 | `WORKFLOW_SERVER_RUNTIME_CREDENTIALS_ENABLED` | +| `DW_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | 単一 namespace の workflow/activity long-poll 待機数のノード単位上限。全体の worker 上限以下で、共有 cache authority が使えない場合は拒否します。 | `WORKFLOW_SERVER_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | 単一 namespace の query-task long-poll 待機数のノード単位上限。全体の query 上限以下で、共有 cache authority が使えない場合は拒否します。 | `WORKFLOW_SERVER_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_V1_ENABLED` | `false` | v1 状態を意図的に維持する場合のみ embedded v1 の移行とキューの drain を有効にします。standalone Server は既定で v2 専用です。 | `WORKFLOW_V1_ENABLED` | + ## 実行基盤の変数 {#runtime-infrastructure-variables} 実行基盤の変数は、フレームワークや依存ライブラリの設定です。Server の監査はこれらを認識して警告を抑えますが、安定した Durable Workflow API の設定項目ではありません。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md b/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md index 7d7de245cd9..b1c55f5457c 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md @@ -89,6 +89,67 @@ class PaymentWorkflow: 保護対象の下流呼び出しは**通常のキューに入る activity** に置いてください。インラインのローカル activity は通常の activity task を作らず、キュー/namespace/グループの activity ディスパッチ上限は計量しません。prepared local claim は実行権限を検証し、この予算は検証しません。組み込み Laravel に独立 Server の admission はなく、独自のデプロイ制御を使います。[ローカル activity](../features/local-activities.md)を参照してください。 +## namespace ごとのリクエスト受付制限 {#namespace-request-admission} + +以下は公開済み **PHP Server 2.11.0** の契約です。実際のイメージと[バージョン付き設定リファレンス](./server-config-reference.md#additional-published-php-controls)を確認してください。HTTP 予算は、worker slot、task dispatch、保留中の poll、永続状態クォータとは別です。予算は `Durable-Workflow-Namespace` または `DW_DEFAULT_NAMESPACE` で解決されたリクエストの namespace に属し、管理 URL が別の namespace を指す場合も同じです。 + +認証後に namespace の受付制限へ到達したリクエストは、次の制御・管理ルート群とその配下で計上されます。`/api/namespaces`, `/api/storage`, `/api/workflows`, `/api/activities`, `/api/bridge-adapters`, `/api/workers`, `/api/worker-sessions`, `/api/task-queues`, `/api/deployments`, `/api/schedules`, `/api/search-attributes`, `/api/service-endpoints`, `/api/service-catalog`。複数形の `/api/workers` 管理ルートも対象です。 + +単数形の `/api/worker/*` の登録、polling、結果報告は、この HTTP 予算を使いません。health/readiness、`/api/cluster/info`、管理用 `/api/system/*`、runtime 認証情報、外部 payload 転送もこの gate の対象外ですが、それぞれのアクセス・容量・ストレージ検査は適用されます。認証、プロトコル、namespace 解決で先に拒否されたリクエストは、このカウンターまで到達しません。 + +頻度制限は Server の時計による固定の分単位 bucket です。平滑化されたレートや移動窓ではありません。予算 N では、境界の直前に N 件、直後にさらに N 件を受け付ける場合があります。後段で失敗しても計上されます。頻度の判定は同時数の前なので、同時数による拒否も分予算を消費する場合があります。同時数 slot はリクエスト終了と cleanup まで保持され、実行中 workflow 数を数えるものではありません。 + +複数 API replica では、同じ共有 Redis store/key prefix、同期した時計、一貫した読み込み済み設定が必要です。replica を増やしても共有 namespace 予算は増えません。ローカル file cache は、互換性のある書き込み権限を持つプロセス間だけを調整し、複数ノード用の基準構成ではありません。ノード単位の worker/query poll 待機数上限は別です。[環境変数変更後は対象 role を再起動](./server-config-reference.md#how-changes-take-effect)してください。 + +```dotenv +DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE=100 +DW_NAMESPACE_MAX_CONCURRENT_REQUESTS=8 +DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE=150 +DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS=10 +DW_NAMESPACE_ADMISSION_OVERRIDES='{"payments":{"max_requests_per_minute":200,"max_concurrent_requests":12},"reports":{"max_requests_per_minute":40,"max_concurrent_requests":3}}' +``` + +既存 namespace では、例の実効値は `payments` が毎分150件・同時10件、`reports` が40/3、その他が100/8です。override は既定値を増減できますが、hard cap の150/10は適用されます。この設定は namespace を作成せず、スループットを予約しません。 + +これらの HTTP 設定は未設定なら対応する上限を追加しませんが、hard cap だけでも上限になります。null override は既定値へ戻ります。値は正の整数が必要で、0は無効です。PHP 実装上限は毎分10000000件・同時1024件で、実際の HTTP pool 容量とは別です。公開 PHP2.11.0 は不正な `DW_NAMESPACE_ADMISSION_OVERRIDES` JSON を空の override として黙って扱い、全体の既定値へ戻します。デプロイ前に JSON を検証してください。既定値と hard cap がなければ意図した namespace 上限が失われます。この[確認済み製品不具合](https://github.com/durable-workflow/durable-workflow.github.io/issues/335#issuecomment-6369150521)はドキュメント更新では修正されません。 + +| 理由 | HTTP | 再試行の目安(秒) | +| --- | --- | --- | +| `namespace_request_rate_exhausted` | `429` | 次の分まで、1〜60 | +| `namespace_request_concurrency_exhausted` | `429` | 1 | +| `namespace_request_admission_unavailable` | `503` | 1 | + +JSON の `retry_after_seconds` と `Retry-After` ヘッダーは一致します。設定済みの調整機構が利用不能、または数値上限が無効な場合は503で拒否します。通常リクエストの予算を使い切っても namespace の管理メトリクスを確認できます。`dw_namespace_request_admission_rejections` が有限の理由を報告します。呼び出し側の retry/backoff を制限し、冪等性を保ってください。通信結果が不確かな場合、書き込みを自動再送してよいことにはなりません。[タイムアウト予算](../deployment.md#worker-long-poll-timeout-budgets)も参照してください。 + +## namespace の永続状態クォータ {#namespace-durable-state} + +`DW_NAMESPACE_DURABLE_LIMITS` は保持行数の既定上限、`DW_NAMESPACE_DURABLE_OVERRIDES` は namespace ごとの上書き、`DW_NAMESPACE_DURABLE_HARD_LIMITS` は回避できない hard cap です。空オブジェクトは上限を追加しません。override は既定値を増減でき、null は既定値へ戻ります。HTTP 制限と異なり、永続クォータの0は有効で、新規割り当てを防ぎます。例では既存 `payments` は open run を250、その他は100まで保持でき、hard cap は500です。 + +```dotenv +DW_NAMESPACE_DURABLE_LIMITS='{"max_open_workflow_runs":100,"max_open_workflow_run_waits":200,"max_pending_workflow_timers":200}' +DW_NAMESPACE_DURABLE_HARD_LIMITS='{"max_open_workflow_runs":500}' +DW_NAMESPACE_DURABLE_OVERRIDES='{"payments":{"max_open_workflow_runs":250}}' +``` + +以下のリソースに `max_` フィールドを使います。各行は、その所有 namespace、または関連する workflow/run の namespace で計上されます。保持総数と open/pending の部分集合は独立した上限です。namespace 行で変更を直列化し、データベースの正本の件数で判断します。 + +| リソース | 計上対象 | +| --- | --- | +| `workflow_instances`, `workflow_runs` | 終了済み run も含む、保持中の全 workflow instance/run 行。 | +| `open_workflow_runs` | 状態が `pending`、`running`、`waiting` の run。 | +| `workflow_history_events`, `workflow_commands`, `workflow_tasks` | 保持中の履歴、command、workflow task 行。 | +| `pending_workflow_tasks` | キュー内で状態が `ready` の workflow task 行。active lease には別の受付制限があります。 | +| `workflow_timers`, `pending_workflow_timers` | 保持中の全 timer と、その `pending` 部分集合。 | +| `workflow_run_waits`, `open_workflow_run_waits` | 保持中の全 run wait と、その `open` 部分集合。 | +| `schedules`, `schedule_history_events`, `worker_registrations` | 保持中の schedule、schedule history、worker 登録行。古い登録も削除まで計上されます。 | +| `workflow_streams`, `workflow_stream_items` | durable stream と inbound stream、およびその item 行。 | + +子や service call を待つ親も、自分の namespace で open run を使い続けます。子は自分の run を追加します。同じ namespace なら両方の open run と wait/timer を計画してください。workflow を作成する service operation は、その workflow の namespace に行を消費します。既存 run への signal/update が自動的に2つ目の run を作るわけではありません。サービス呼び出し境界と外部 payload のクォータは別です。 + +枯渇時は429 `namespace__exhausted` を返します。`retryable` を確認してください。再試行不可で待機目安を持たないクォータもあり、再試行可能な永続クォータ拒否は60秒を提示しますが、その後の空きを保証しません。設定済みクォータを評価できない場合は503 `namespace_durable_state_quota_unavailable` と1秒の目安です。保持行数の逼迫には、短い retry loop ではなく retention や容量・設定変更が必要な場合があります。 + +管理メトリクスではリクエストヘッダーで namespace を選びます。`dw_namespace_durable_state_usage` と JSON の `limits`、`usage`、`remaining`、`configuration_status`、`measurement_status` がその範囲を示します。namespace はリクエストの範囲であり、無制限な metric label ではありません。計測不能は使用量0や無制限容量を意味しません。[完全な設定リファレンス](./server-config-reference.md#namespace-durable-controls)を参照してください。 + ## Server の設定 {#server-configuration} すべてのキューに同じ上限を適用する場合は、全体の上限を設定します。 diff --git a/i18n/ja/source-hashes.json b/i18n/ja/source-hashes.json index f3d1cd198fb..c384bb21231 100644 --- a/i18n/ja/source-hashes.json +++ b/i18n/ja/source-hashes.json @@ -86,12 +86,12 @@ "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", "polyglot/rust.md": "5ff66bcb7e5369bcffd8611342a35c27028cac5a4ee376e86d90334a2b12d365", "polyglot/server-api-reference.md": "e94af77a13b341d6fdc9941d4ee94e5053ab932d2e77069b238eb33351414e83", - "polyglot/server-config-reference.md": "edb4cf00b9df2c9946b32a81c6bb2c4db6eaee89794b85286c61c235a4846414", + "polyglot/server-config-reference.md": "b2dc3ddd188b078875cb46bf32b94053d89912c063c1687cc98ff5ba2baba812", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "7950b0c82dac2940c30b0aa042f3105dc9bdc70b524600cce4ed6d311cda7171", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", "polyglot/task-matching-dispatch.md": "9c8ffbbee16b5da48e7882721d7ba8eac209a374a6ca766d93d2b17e825b203d", - "polyglot/task-queue-admission.md": "47713eeaf3b10ead16b6b6c40816b97142d0f78670e40d181405db70ce49e7ac", + "polyglot/task-queue-admission.md": "ff04476dfca350f828d807b392d5e8b81c3c3baee252906021558a7eba6b936b", "polyglot/worker-build-id-rollout.md": "62ddf1ca054cf4b83de2fa020f313a153ece00519f804c4f8f30aca53c979af0", "polyglot/worker-compatibility-routing.md": "ef58f23c112f0e6b968927ba861177903adca21ed33b6b9371681e23a18b2994", "polyglot/worker-protocol.md": "007e844b0a7ab284b7cd343e79f01a27a0dabee3fe4cf19064170581bb897b85", 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 8f84de23410..a169bbfe421 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 @@ -271,6 +271,74 @@ Use `DW_V2_GUARDRAILS_BOOT` na CI e nos manifestos de implantação. O nome anti Consulte [Correspondência e despacho de tarefas](/docs/polyglot/task-matching-dispatch) ao configurar `DW_V2_MATCHING_ROLE_QUEUE_WAKE` ou um daemon dedicado de `workflow:v2:repair-pass --loop`. Essas opções alteram onde as tarefas prontas são descobertas, não o contrato do protocolo dos workers. +## Controles adicionais do PHP Server publicado {#additional-published-php-controls} + +Esta referência cobre o contrato publicado do **PHP Server 2.11.0**, incluindo os controles abaixo. Confira a imagem executada: a versão de instalação escolhida separadamente pode ser anterior. `unset` indica ausência de valor de ambiente; seu efeito depende do controle. Padrões e aliases vêm do [contrato publicado](https://github.com/durable-workflow/server/blob/36d16273604755f3dd0743cab331cc7c62e51d8e/config/dw-contract.php). O build verifica o snapshot versionado em todos os idiomas. Esta referência não altera o conjunto de versões selecionado. + +### Admissão HTTP por namespace {#namespace-request-controls} + +| Variável | Padrão | Finalidade | Alias antigo | +| --- | --- | --- | --- | +| `DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | `unset` | Limite opcional de requisições de controle por minuto e namespace; sem valor não há limite. | `WORKFLOW_SERVER_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_MAX_CONCURRENT_REQUESTS` | `unset` | Limite opcional de requisições de controle simultâneas por namespace; sem valor não há limite. | `WORKFLOW_SERVER_NAMESPACE_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | `unset` | Teto obrigatório de requisições por minuto, incluindo overrides de namespace. | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | `unset` | Teto obrigatório de requisições simultâneas, incluindo overrides de namespace. | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_ADMISSION_OVERRIDES` | `{}` | Objeto JSON por namespace com overrides de frequência e concorrência de requisições. | `WORKFLOW_SERVER_NAMESPACE_ADMISSION_OVERRIDES` | + +[Admissão de requisições por namespace](./task-queue-admission.md#namespace-request-admission). + +### Cotas de estado durável por namespace {#namespace-durable-controls} + +| Variável | Padrão | Finalidade | Alias antigo | +| --- | --- | --- | --- | +| `DW_NAMESPACE_DURABLE_LIMITS` | `{}` | JSON de cotas padrão de linhas duráveis por namespace. Totais e limites pending/open são independentes; tarefas pendentes são linhas ready na fila, com leases ativos limitados à parte. Objeto vazio não limita. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_LIMITS` | +| `DW_NAMESPACE_DURABLE_HARD_LIMITS` | `{}` | JSON de tetos obrigatórios de linhas duráveis, incluindo overrides; objeto vazio não acrescenta tetos do operador. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_HARD_LIMITS` | +| `DW_NAMESPACE_DURABLE_OVERRIDES` | `{}` | JSON de overrides de cotas duráveis por namespace; tetos obrigatórios continuam valendo. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_OVERRIDES` | + +[Cotas de estado durável por namespace](./task-queue-admission.md#namespace-durable-state). + +### Cotas de payload externo e transporte S3 {#external-payload-quotas-and-s3} + +| Variável | Padrão | Finalidade | Alias antigo | +| --- | --- | --- | --- | +| `DW_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | `unset` | Bytes distintos entre upload slots imutáveis de um completion com lease; sem valor usa `DW_EXTERNAL_PAYLOAD_MAX_BYTES`. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | +| `DW_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | `unset` | Bytes acumulados de payload externo por namespace. Conta objetos prontos e em andamento; sem valor não limita. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | Quantidade de objetos de payload externo por namespace. Conta objetos prontos e em andamento; sem valor não limita. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | `unset` | Teto obrigatório de bytes acumulados de payload externo por namespace, incluindo overrides. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | Teto obrigatório de objetos de payload externo por namespace, incluindo overrides. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | `{}` | Objeto JSON por namespace com overrides de cotas `max_bytes` e `max_objects`. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | +| `DW_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | `unset` | Access-key ID opcional do disco compatível com S3 gerenciado pelo runtime; pode ser omitido com workload identity. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | +| `DW_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | `unset` | Chave secreta opcional do disco compatível com S3 gerenciado; deve acompanhar o access-key ID. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | +| `DW_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | `unset` | Session token opcional de credenciais temporárias do disco compatível com S3 gerenciado. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | +| `DW_EXTERNAL_PAYLOAD_S3_REGION` | `us-east-1` | Região do disco compatível com S3 gerenciado pelo runtime. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_REGION` | +| `DW_EXTERNAL_PAYLOAD_S3_BUCKET` | `unset` | Bucket do disco compatível com S3 gerenciado pelo runtime. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_BUCKET` | +| `DW_EXTERNAL_PAYLOAD_S3_ENDPOINT` | `unset` | Endpoint HTTPS opcional do serviço compatível com S3 para payloads externos. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ENDPOINT` | +| `DW_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | `false` | Usar endereçamento de bucket path-style no serviço compatível com S3 gerenciado. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | + +### Limites de serviço por namespace chamador {#service-caller-namespace-controls} + +| Variável | Padrão | Finalidade | Alias antigo | +| --- | --- | --- | --- | +| `DW_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | `unset` | Limite compartilhado opcional por minuto de chamadas de serviço, agregado por namespace chamador. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | `unset` | Limite compartilhado opcional de chamadas de serviço em andamento, agregado por namespace chamador. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | `unset` | Teto obrigatório por minuto para políticas de fronteira de serviço e namespace chamador. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | `unset` | Teto obrigatório de chamadas em andamento para políticas de fronteira de serviço e namespace chamador. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | `{}` | JSON de overrides de frequência e chamadas em andamento por namespace chamador; os tetos continuam valendo. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | + +### Coordenação, armazenamento e runtime {#coordination-storage-and-runtime-controls} + +| Variável | Padrão | Finalidade | Alias antigo | +| --- | --- | --- | --- | +| `DW_OBSERVABILITY_CONTEXT_ENABLED` | `false` | Ativar persistência e entrega limitadas de trace context e descoberta quando sua API e seu schema opcionais estiverem instalados. | - | +| `DW_OBSERVABILITY_BAGGAGE_ALLOWLIST` | `[]` | Lista JSON de chaves baggage permitidas nas origens do run; vazia por padrão. Links nunca carregam baggage. | - | +| `DW_STORAGE_ADMISSION_FILE` | `unset` | Arquivo local opcional de observação de pressão de armazenamento, somente leitura; observações inválidas ou antigas bloqueiam escritas. | - | +| `DW_STORAGE_ADMISSION_SOURCE` | `unset` | Identidade esperada do recurso de armazenamento na observação de admissão. | - | +| `DW_STORAGE_ADMISSION_MAX_AGE_SECONDS` | `15` | Idade máxima da observação de armazenamento em segundos, de 1 a 300. | - | +| `DW_RUNTIME_CREDENTIALS_ENABLED` | `false` | Ativar credenciais bearer de runtime duráveis, vinculadas ao namespace e apoiadas em banco de dados, pela API admin. | `WORKFLOW_SERVER_RUNTIME_CREDENTIALS_ENABLED` | +| `DW_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | Limite por nó de esperas long-poll workflow/activity de um namespace; não excede o teto global de workers. Recusa se a autoridade de cache compartilhado estiver indisponível. | `WORKFLOW_SERVER_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | Limite por nó de esperas long-poll query-task de um namespace; não excede o teto global de queries. Recusa se a autoridade de cache compartilhado estiver indisponível. | `WORKFLOW_SERVER_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_V1_ENABLED` | `false` | Ativar migração e esvaziamento de fila embedded v1 apenas para preservar seu estado deliberadamente; Server independente usa somente v2 por padrão. | `WORKFLOW_V1_ENABLED` | + ## Variáveis de infraestrutura de execução {#runtime-infrastructure-variables} As variáveis de infraestrutura de execução controlam o framework e suas dependências. A auditoria do Server as reconhece para não emitir avisos, mas elas não são controles estáveis da API do Durable Workflow. diff --git a/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md b/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md index 2a460f029af..550978a680f 100644 --- a/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md +++ b/i18n/pt-BR/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md @@ -92,6 +92,67 @@ Um breaker aberto gera `NonRetryableError` antes do pagamento; falhas repetívei Mantenha chamadas protegidas em **atividades comuns enfileiradas**. Atividades locais inline não criam tarefa de atividade comum e os limites de despacho por fila/namespace/grupo não as medem. Um claim local preparado valida autoridade, não este orçamento. Laravel integrado não tem admission do Server independente; use seus controles de implantação. Veja [atividades locais](../features/local-activities.md). +## Admissão de requisições por namespace {#namespace-request-admission} + +Este contrato corresponde ao **PHP Server 2.11.0** publicado. Confira a imagem executada e a [referência versionada de configuração](./server-config-reference.md#additional-published-php-controls). Os orçamentos HTTP são separados de slots de worker, despacho, polls retidos e cotas duráveis. O orçamento pertence ao namespace resolvido por `Durable-Workflow-Namespace` ou `DW_DEFAULT_NAMESPACE`, inclusive quando uma rota administrativa nomeia outro namespace. + +Requisições autenticadas que chegam à admissão contam nestas famílias de rotas de controle e gestão, incluindo seus descendentes: `/api/namespaces`, `/api/storage`, `/api/workflows`, `/api/activities`, `/api/bridge-adapters`, `/api/workers`, `/api/worker-sessions`, `/api/task-queues`, `/api/deployments`, `/api/schedules`, `/api/search-attributes`, `/api/service-endpoints`, `/api/service-catalog`. As rotas de gestão no plural `/api/workers` contam. + +As rotas no singular `/api/worker/*` de registro, polling e resultados não usam este orçamento HTTP. Health/readiness, `/api/cluster/info`, rotas admin `/api/system/*`, credenciais runtime e transporte de payload externo também ficam fora; suas próprias verificações de acesso, capacidade e armazenamento continuam valendo. Recusas anteriores de autenticação, protocolo ou resolução de namespace não chegam ao contador. + +A frequência usa buckets de minutos fixos pelo relógio do Server, não uma taxa uniforme ou janela móvel. Um orçamento N pode admitir N requisições antes da virada e mais N depois. Falhas posteriores continuam contando; a frequência é admitida antes da concorrência, então uma recusa de concorrência pode consumir o orçamento do minuto. O slot simultâneo fica ocupado até o fim da requisição e sua limpeza; ele não conta workflows em execução. + +Entre réplicas API, use o mesmo Redis compartilhado e prefixo de chaves, relógios sincronizados e configuração carregada consistente. Adicionar réplicas não multiplica o orçamento compartilhado. Cache local em arquivos coordena apenas processos com acesso de escrita compatível; não é a configuração base multinó. Os limites de polls worker/query retidos por nó são separados. [Reinicie os papéis afetados após mudar o ambiente](./server-config-reference.md#how-changes-take-effect). + +```dotenv +DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE=100 +DW_NAMESPACE_MAX_CONCURRENT_REQUESTS=8 +DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE=150 +DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS=10 +DW_NAMESPACE_ADMISSION_OVERRIDES='{"payments":{"max_requests_per_minute":200,"max_concurrent_requests":12},"reports":{"max_requests_per_minute":40,"max_concurrent_requests":3}}' +``` + +Para namespaces existentes, o exemplo resulta em `payments` com 150 requisições/minuto e 10 simultâneas, `reports` com 40/3 e os demais com 100/8. Overrides podem elevar ou reduzir os padrões, mas os tetos 150/10 continuam valendo. A configuração não cria namespaces nem reserva desempenho. + +Para estes controles HTTP, valor ausente não configura aquele limite; um teto obrigatório sozinho ainda pode limitá-lo. Override null volta ao padrão. Os valores devem ser inteiros positivos: zero é inválido. Os tetos da implementação PHP são 10000000 requisições/minuto e 1024 simultâneas, independentemente da capacidade real do pool HTTP. PHP 2.11.0 publicado trata silenciosamente JSON malformado em `DW_NAMESPACE_ADMISSION_OVERRIDES` como overrides vazios e volta aos padrões globais. Valide o JSON antes do deploy; sem padrões ou tetos obrigatórios, perde-se o limite pretendido. Esta [falha confirmada do produto](https://github.com/durable-workflow/durable-workflow.github.io/issues/335#issuecomment-6369150521) continua separada da atualização documental. + +| Motivo | HTTP | Espera sugerida em segundos | +| --- | --- | --- | +| `namespace_request_rate_exhausted` | `429` | Até o próximo minuto, 1–60 | +| `namespace_request_concurrency_exhausted` | `429` | 1 | +| `namespace_request_admission_unavailable` | `503` | 1 | + +O JSON `retry_after_seconds` coincide com o cabeçalho `Retry-After`. Coordenação configurada indisponível ou limites numéricos inválidos recusa com 503. Consulte métricas admin do namespace mesmo após esgotar o orçamento comum; `dw_namespace_request_admission_rejections` mostra os motivos limitados. Aplique retry/backoff limitado do chamador e idempotência; resultado de transporte incerto não permite repetir uma escrita automaticamente. Veja os [orçamentos de timeout](../deployment.md#worker-long-poll-timeout-budgets). + +## Cotas de estado durável por namespace {#namespace-durable-state} + +`DW_NAMESPACE_DURABLE_LIMITS` define limites padrão de linhas retidas, `DW_NAMESPACE_DURABLE_OVERRIDES` os altera por namespace e `DW_NAMESPACE_DURABLE_HARD_LIMITS` adiciona tetos obrigatórios. Objetos vazios não acrescentam limites. Overrides podem elevar ou reduzir os padrões; null volta ao padrão. Ao contrário da admissão HTTP, cota durável zero é válida e impede novas alocações. Aqui `payments` existente pode manter 250 runs abertos e os demais namespaces 100, sob um teto de 500. + +```dotenv +DW_NAMESPACE_DURABLE_LIMITS='{"max_open_workflow_runs":100,"max_open_workflow_run_waits":200,"max_pending_workflow_timers":200}' +DW_NAMESPACE_DURABLE_HARD_LIMITS='{"max_open_workflow_runs":500}' +DW_NAMESPACE_DURABLE_OVERRIDES='{"payments":{"max_open_workflow_runs":250}}' +``` + +Use campos `max_` para os recursos abaixo. Cada linha conta no namespace proprietário ou no do workflow/run associado. Totais retidos e subconjuntos abertos/pendentes têm limites independentes. A aplicação usa contagens autoritativas do banco, serializando mutações pela linha do namespace. + +| Recurso | O que conta | +| --- | --- | +| `workflow_instances`, `workflow_runs` | Todas as linhas retidas de instâncias/runs de workflow, incluindo runs terminais. | +| `open_workflow_runs` | Runs com status `pending`, `running` ou `waiting`. | +| `workflow_history_events`, `workflow_commands`, `workflow_tasks` | Linhas retidas de histórico, comandos e tarefas de workflow. | +| `pending_workflow_tasks` | Linhas de tarefas de workflow na fila com status `ready`; leases ativos têm controles separados. | +| `workflow_timers`, `pending_workflow_timers` | Todos os timers retidos e o subconjunto `pending`, respectivamente. | +| `workflow_run_waits`, `open_workflow_run_waits` | Todas as esperas de run retidas e o subconjunto `open`, respectivamente. | +| `schedules`, `schedule_history_events`, `worker_registrations` | Schedules, histórico e registros de workers retidos; registros obsoletos contam até serem removidos. | +| `workflow_streams`, `workflow_stream_items` | Linhas de streams duráveis e de entrada, e linhas de seus itens. | + +Um pai esperando um filho ou chamada de serviço ainda ocupa um run aberto no próprio namespace. O filho adiciona seu run; no mesmo namespace, planeje ambos os runs abertos e suas esperas/timers. Uma operação de serviço que cria workflow consome linhas no namespace desse workflow; signal/update em run existente não cria outro run automaticamente. Limites de chamadas de serviço e payload externo são separados. + +O esgotamento retorna 429 `namespace__exhausted`. Leia `retryable`: algumas cotas não admitem retry nem sugerem espera; recusas duráveis retentáveis indicam 60 segundos, sem prometer capacidade depois. Falha ao avaliar cota configurada retorna 503 `namespace_durable_state_quota_unavailable` com um segundo de espera. Pressão de linhas retidas pode exigir retenção ou mudança de capacidade/configuração, não um loop de retries. + +Selecione o namespace pelo cabeçalho ao consultar métricas admin. `dw_namespace_durable_state_usage` e os campos JSON `limits`, `usage`, `remaining`, `configuration_status` e `measurement_status` mostram esse escopo; namespace pertence à requisição, não é um label ilimitado. Medições indisponíveis não significam uso zero nem capacidade ilimitada. Veja a [referência completa](./server-config-reference.md#namespace-durable-controls). + ## Configuração do servidor {#server-configuration} Defina limites globais quando todas as filas devam compartilhar o mesmo teto: diff --git a/i18n/pt-BR/source-hashes.json b/i18n/pt-BR/source-hashes.json index f3d1cd198fb..c384bb21231 100644 --- a/i18n/pt-BR/source-hashes.json +++ b/i18n/pt-BR/source-hashes.json @@ -86,12 +86,12 @@ "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", "polyglot/rust.md": "5ff66bcb7e5369bcffd8611342a35c27028cac5a4ee376e86d90334a2b12d365", "polyglot/server-api-reference.md": "e94af77a13b341d6fdc9941d4ee94e5053ab932d2e77069b238eb33351414e83", - "polyglot/server-config-reference.md": "edb4cf00b9df2c9946b32a81c6bb2c4db6eaee89794b85286c61c235a4846414", + "polyglot/server-config-reference.md": "b2dc3ddd188b078875cb46bf32b94053d89912c063c1687cc98ff5ba2baba812", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "7950b0c82dac2940c30b0aa042f3105dc9bdc70b524600cce4ed6d311cda7171", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", "polyglot/task-matching-dispatch.md": "9c8ffbbee16b5da48e7882721d7ba8eac209a374a6ca766d93d2b17e825b203d", - "polyglot/task-queue-admission.md": "47713eeaf3b10ead16b6b6c40816b97142d0f78670e40d181405db70ce49e7ac", + "polyglot/task-queue-admission.md": "ff04476dfca350f828d807b392d5e8b81c3c3baee252906021558a7eba6b936b", "polyglot/worker-build-id-rollout.md": "62ddf1ca054cf4b83de2fa020f313a153ece00519f804c4f8f30aca53c979af0", "polyglot/worker-compatibility-routing.md": "ef58f23c112f0e6b968927ba861177903adca21ed33b6b9371681e23a18b2994", "polyglot/worker-protocol.md": "007e844b0a7ab284b7cd343e79f01a27a0dabee3fe4cf19064170581bb897b85", 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 b79327a0332..17054b05bdb 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 @@ -327,6 +327,74 @@ workers, які виконують ті самі workflows. `workflow:v2:repair-pass --loop`. Ці налаштування змінюють місце пошуку готових tasks, зберігаючи той самий контракт worker-протоколу. +## Додаткові параметри опублікованого PHP Server {#additional-published-php-controls} + +Цей довідник охоплює контракт опублікованого **PHP Server 2.11.0**, включно з наведеними нижче параметрами. Перевірте фактично запущений образ: незалежно вибрана версія встановлення може бути старішою. `unset` означає відсутність значення змінної; наслідок залежить від параметра. Типові значення й псевдоніми взято з [опублікованого контракту](https://github.com/durable-workflow/server/blob/36d16273604755f3dd0743cab331cc7c62e51d8e/config/dw-contract.php). Під час збірки документації версійний snapshot контракту перевіряється для кожної мови. Вибраний набір версій встановлення не змінюється. + +### Допуск HTTP-запитів namespace {#namespace-request-controls} + +| Змінна | Типове значення | Призначення | Застарілий псевдонім | +| --- | --- | --- | --- | +| `DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | `unset` | Необов’язкова кількість запитів control plane за хвилину для namespace; без значення межі немає. | `WORKFLOW_SERVER_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_MAX_CONCURRENT_REQUESTS` | `unset` | Необов’язкова кількість одночасних запитів control plane для namespace; без значення межі немає. | `WORKFLOW_SERVER_NAMESPACE_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | `unset` | Непереборна верхня межа запитів за хвилину, зокрема для перевизначень namespace. | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | `unset` | Непереборна верхня межа одночасних запитів, зокрема для перевизначень namespace. | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_ADMISSION_OVERRIDES` | `{}` | JSON-об’єкт за namespace із перевизначеннями частоти та одночасності запитів. | `WORKFLOW_SERVER_NAMESPACE_ADMISSION_OVERRIDES` | + +[Допуск запитів namespace](./task-queue-admission.md#namespace-request-admission). + +### Квоти сталого стану namespace {#namespace-durable-controls} + +| Змінна | Типове значення | Призначення | Застарілий псевдонім | +| --- | --- | --- | --- | +| `DW_NAMESPACE_DURABLE_LIMITS` | `{}` | JSON типових квот сталих рядків namespace. Загальні та pending/open-квоти незалежні; pending tasks — готові рядки черги, активні leases обмежуються окремо. Порожній об’єкт не задає меж. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_LIMITS` | +| `DW_NAMESPACE_DURABLE_HARD_LIMITS` | `{}` | JSON непереборних верхніх меж сталих рядків, зокрема для перевизначень namespace; порожній об’єкт не додає операторських обмежень. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_HARD_LIMITS` | +| `DW_NAMESPACE_DURABLE_OVERRIDES` | `{}` | JSON перевизначень квот сталих рядків за namespace; жорсткі межі залишаються чинними. | `WORKFLOW_SERVER_NAMESPACE_DURABLE_OVERRIDES` | + +[Квоти сталого стану namespace](./task-queue-admission.md#namespace-durable-state). + +### Квоти зовнішніх payload і транспорт S3 {#external-payload-quotas-and-s3} + +| Змінна | Типове значення | Призначення | Застарілий псевдонім | +| --- | --- | --- | --- | +| `DW_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | `unset` | Окремі байти в незмінних upload slots одного leased completion; без значення використовується `DW_EXTERNAL_PAYLOAD_MAX_BYTES`. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | +| `DW_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | `unset` | Сумарні байти зовнішніх payload namespace. Враховуються готові й незавершені об’єкти; без значення межі немає. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | Кількість зовнішніх payload-об’єктів namespace. Враховуються готові й незавершені об’єкти; без значення межі немає. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | `unset` | Непереборна верхня межа сумарних байтів зовнішніх payload namespace, включно з перевизначеннями. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | Непереборна верхня межа кількості зовнішніх payload-об’єктів namespace, включно з перевизначеннями. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | `{}` | JSON за namespace із перевизначеннями квот `max_bytes` і `max_objects`. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | +| `DW_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | `unset` | Необов’язковий access-key ID керованого runtime S3-сумісного диска; може бути відсутній за workload identity. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | +| `DW_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | `unset` | Необов’язковий секретний ключ керованого S3-сумісного диска; задається разом з access-key ID. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | +| `DW_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | `unset` | Необов’язковий session token тимчасових облікових даних керованого S3-сумісного диска. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | +| `DW_EXTERNAL_PAYLOAD_S3_REGION` | `us-east-1` | Регіон керованого runtime S3-сумісного диска. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_REGION` | +| `DW_EXTERNAL_PAYLOAD_S3_BUCKET` | `unset` | Bucket керованого runtime S3-сумісного диска. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_BUCKET` | +| `DW_EXTERNAL_PAYLOAD_S3_ENDPOINT` | `unset` | Необов’язковий HTTPS endpoint S3-сумісного сховища зовнішніх payload. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ENDPOINT` | +| `DW_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | `false` | Використовувати path-style адресацію bucket для керованого S3-сумісного сховища. | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | + +### Межі сервісних викликів namespace викликача {#service-caller-namespace-controls} + +| Змінна | Типове значення | Призначення | Застарілий псевдонім | +| --- | --- | --- | --- | +| `DW_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | `unset` | Спільна необов’язкова кількість сервісних викликів за хвилину в усіх межах namespace викликача. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | `unset` | Спільна необов’язкова кількість одночасних сервісних викликів namespace викликача. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | `unset` | Непереборна хвилинна межа політик сервісної межі й namespace викликача. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | `unset` | Непереборна межа одночасних викликів політик сервісної межі й namespace викликача. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | `{}` | JSON перевизначень частоти й одночасності сервісних викликів за namespace викликача; жорсткі межі чинні. | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | + +### Координація, сховище й runtime {#coordination-storage-and-runtime-controls} + +| Змінна | Типове значення | Призначення | Застарілий псевдонім | +| --- | --- | --- | --- | +| `DW_OBSERVABILITY_CONTEXT_ENABLED` | `false` | Увімкнути необов’язкове обмежене збереження й передавання trace context та discovery після встановлення відповідних API і схеми. | - | +| `DW_OBSERVABILITY_BAGGAGE_ALLOWLIST` | `[]` | JSON-список дозволених baggage keys для джерел run; типовий список порожній. Links не несуть baggage. | - | +| `DW_STORAGE_ADMISSION_FILE` | `unset` | Необов’язковий локальний read-only файл спостереження тиску сховища; невалідні чи застарілі дані блокують записи. | - | +| `DW_STORAGE_ADMISSION_SOURCE` | `unset` | Очікувана ідентичність ресурсу сховища в спостереженні допуску. | - | +| `DW_STORAGE_ADMISSION_MAX_AGE_SECONDS` | `15` | Максимальний вік спостереження сховища в секундах, від 1 до 300. | - | +| `DW_RUNTIME_CREDENTIALS_ENABLED` | `false` | Увімкнути сталі namespace-bound runtime bearer credentials у базі даних, керовані через admin API. | `WORKFLOW_SERVER_RUNTIME_CREDENTIALS_ENABLED` | +| `DW_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | Межа утримуваних workflow/activity long polls одного namespace на цьому вузлі; не перевищує глобальну worker-межу. Недоступний спільний cache authority спричиняє відмову. | `WORKFLOW_SERVER_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | Межа утримуваних query-task long polls одного namespace на цьому вузлі; не перевищує глобальну query-межу. Недоступний спільний cache authority спричиняє відмову. | `WORKFLOW_SERVER_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_V1_ENABLED` | `false` | Увімкнути міграцію та спорожнення черги embedded v1 лише для свідомого збереження v1-стану; standalone Server типово працює лише з v2. | `WORKFLOW_V1_ENABLED` | + ## Змінні інфраструктури runtime {#runtime-infrastructure-variables} Інфраструктурні змінні runtime керують фреймворком та залежностями. diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md b/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md index 56f44c5d3ca..01a74bfe6f1 100644 --- a/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md +++ b/i18n/uk/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md @@ -116,6 +116,67 @@ class PaymentWorkflow: Залишайте захищені downstream-виклики у **звичайних queued activity**. Inline local activity не створюють звичайного activity-task, тому queue/namespace/budget-group dispatch-ліміти activity їх не вимірюють. Prepared local claim перевіряє повноваження виконання, а не цей бюджет. Вбудований Laravel не має admission окремого Server; використовуйте власні засоби розгортання. Див. [local activity](../features/local-activities.md). +## Допуск запитів namespace {#namespace-request-admission} + +Цей контракт стосується опублікованого **PHP Server 2.11.0**. Перевірте фактичний образ і [версійний довідник конфігурації](./server-config-reference.md#additional-published-php-controls). HTTP-бюджети namespace відокремлені від слотів worker, dispatch завдань, утримуваних worker polls і квот сталого стану. Бюджет належить namespace запиту, визначеному через `Durable-Workflow-Namespace` або `DW_DEFAULT_NAMESPACE`, навіть коли шлях адміністративного запиту називає інший namespace. + +Автентифіковані запити, які дійшли до допуску namespace, враховуються для таких груп маршрутів control plane та керування, включно з вкладеними шляхами: `/api/namespaces`, `/api/storage`, `/api/workflows`, `/api/activities`, `/api/bridge-adapters`, `/api/workers`, `/api/worker-sessions`, `/api/task-queues`, `/api/deployments`, `/api/schedules`, `/api/search-attributes`, `/api/service-endpoints`, `/api/service-catalog`. Адміністративні маршрути у множині `/api/workers` враховуються. + +Маршрути реєстрації, polling та результатів в однині `/api/worker/*` не використовують цей HTTP-бюджет. Health/readiness, `/api/cluster/info`, адміністративні `/api/system/*`, runtime credentials і транспорт зовнішніх payload також не проходять цей gate; їхні власні перевірки авторизації, місткості й сховища залишаються чинними. Відмови автентифікації, протоколу чи визначення namespace до цього middleware не збільшують лічильник. + +Частота обмежується фіксованими хвилинними bucket за годинником Server, а не плавним чи рухомим вікном. Бюджет N може пропустити N запитів перед межею та ще N після неї. Подальші помилки запиту не скасовують облік; частота перевіряється перед одночасністю, тож відмова через одночасність може витратити хвилинний бюджет. Слот одночасності утримується до завершення запиту й cleanup; він не рахує запущені workflow. + +Між API-репліками потрібні спільний Redis store/key prefix, синхронізований час і однакова завантажена конфігурація. Додавання реплік не множить спільний бюджет namespace. Локальний file cache координує лише процеси із сумісним доступом до запису файлів; це не базова конфігурація кількох вузлів. Обмеження утримуваних worker/query polls на вузол окремі. [Перезапускайте відповідні ролі після зміни середовища](./server-config-reference.md#how-changes-take-effect). + +```dotenv +DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE=100 +DW_NAMESPACE_MAX_CONCURRENT_REQUESTS=8 +DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE=150 +DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS=10 +DW_NAMESPACE_ADMISSION_OVERRIDES='{"payments":{"max_requests_per_minute":200,"max_concurrent_requests":12},"reports":{"max_requests_per_minute":40,"max_concurrent_requests":3}}' +``` + +Для наявних namespace приклад дає `payments` 150 запитів/хвилину та 10 одночасних, `reports` — 40/3, іншим — 100/8. Перевизначення можуть підвищувати чи знижувати типові значення, але жорсткі межі 150/10 залишаються чинними. Конфігурація не створює namespace і не резервує пропускну здатність. + +Для HTTP-параметрів відсутність значення не задає відповідної межі; жорстка межа сама по собі все одно може обмежувати. Перевизначення null повертає типове значення. Потрібні додатні цілі числа: нуль невалідний. Межі реалізації PHP — 10000000 запитів/хвилину та 1024 одночасних запити, незалежно від фактичної місткості HTTP-пулу. Опублікований PHP 2.11.0 мовчки трактує невалідний JSON `DW_NAMESPACE_ADMISSION_OVERRIDES` як порожні перевизначення й повертається до глобальних типових значень. Перевіряйте JSON до розгортання; якщо типові та жорсткі межі відсутні, задумана межа namespace зникає. Ця [підтверджена прогалина продукту](https://github.com/durable-workflow/durable-workflow.github.io/issues/335#issuecomment-6369150521) не закривається оновленням документації. + +| Причина | HTTP | Підказка повтору, секунди | +| --- | --- | --- | +| `namespace_request_rate_exhausted` | `429` | До наступної хвилини, 1–60 | +| `namespace_request_concurrency_exhausted` | `429` | 1 | +| `namespace_request_admission_unavailable` | `503` | 1 | + +JSON-поле `retry_after_seconds` узгоджене із заголовком `Retry-After`. Недоступність налаштованої координації чи невалідні числові межі дає закриту відмову 503. Адміністративні метрики namespace доступні й за вичерпаного бюджету звичайних запитів; `dw_namespace_request_admission_rejections` показує скінченний перелік причин. Використовуйте обмежені caller retry/backoff та ідемпотентність; невизначений транспортний результат не дозволяє автоматично повторювати запис. Див. [бюджети часу](../deployment.md#worker-long-poll-timeout-budgets). + +## Квоти сталого стану namespace {#namespace-durable-state} + +`DW_NAMESPACE_DURABLE_LIMITS` задає типові межі збережених рядків, `DW_NAMESPACE_DURABLE_OVERRIDES` змінює їх за namespace, а `DW_NAMESPACE_DURABLE_HARD_LIMITS` додає непереборні стелі. Порожні об’єкти не додають меж. Перевизначення можуть підвищувати чи знижувати типове значення; null повертає типове. На відміну від HTTP-допуску, нульова стала квота валідна та забороняє нові виділення. Тут наявний `payments` може мати 250 відкритих run, інші namespace — 100, за жорсткої межі 500. + +```dotenv +DW_NAMESPACE_DURABLE_LIMITS='{"max_open_workflow_runs":100,"max_open_workflow_run_waits":200,"max_pending_workflow_timers":200}' +DW_NAMESPACE_DURABLE_HARD_LIMITS='{"max_open_workflow_runs":500}' +DW_NAMESPACE_DURABLE_OVERRIDES='{"payments":{"max_open_workflow_runs":250}}' +``` + +Використовуйте поля `max_` для наведених ресурсів. Рядки належать namespace-власнику або namespace пов’язаного workflow/run. Загальна кількість збережених рядків і відкриті/очікувані підмножини мають незалежні квоти. Перевірка читає авторитетні дані БД і серіалізує зміни блокуванням рядка namespace. + +| Ресурс | Що враховується | +| --- | --- | +| `workflow_instances`, `workflow_runs` | Усі збережені рядки екземплярів/run workflow, включно з термінальними run. | +| `open_workflow_runs` | Run зі статусом `pending`, `running` або `waiting`. | +| `workflow_history_events`, `workflow_commands`, `workflow_tasks` | Збережені рядки історії, команд і завдань workflow. | +| `pending_workflow_tasks` | Готові рядки workflow tasks зі статусом `ready` у черзі; активні leases мають окремі обмеження. | +| `workflow_timers`, `pending_workflow_timers` | Усі збережені таймери та підмножина `pending` відповідно. | +| `workflow_run_waits`, `open_workflow_run_waits` | Усі збережені очікування run та підмножина `open` відповідно. | +| `schedules`, `schedule_history_events`, `worker_registrations` | Збережені schedules, їхня історія та реєстрації worker; застарілі реєстрації рахуються до видалення. | +| `workflow_streams`, `workflow_stream_items` | Рядки durable та inbound streams і рядки їхніх елементів. | + +Батьківський workflow, що чекає child або service call, далі займає відкритий run у власному namespace. Child додає власний run; в одному namespace враховуйте обидва відкриті run та їхні очікування/таймери. Сервісна операція, що створює workflow, споживає рядки в його namespace; signal/update на наявному run не створює другий run автоматично. Межі сервісних викликів і зовнішніх payload — окремі параметри. + +Вичерпання дає 429 `namespace__exhausted`. Перевіряйте `retryable`: деякі квоти не допускають повтору та не мають підказки; повторювані сталі відмови вказують 60 секунд, не обіцяючи вільної місткості тоді. Неможливість оцінити налаштовану квоту дає 503 `namespace_durable_state_quota_unavailable` із підказкою в одну секунду. Тиск збережених рядків може вимагати retention або зміни місткості/конфігурації, а не швидкого циклу повторів. + +Обирайте namespace заголовком запиту адміністративних метрик. `dw_namespace_durable_state_usage` і JSON-поля `limits`, `usage`, `remaining`, `configuration_status`, `measurement_status` показують цю область; namespace — контекст запиту, а не необмежена мітка метрик. Недоступні вимірювання не означають нульове використання чи необмежену місткість. Див. [повний довідник конфігурації](./server-config-reference.md#namespace-durable-controls). + ## Налаштування Server {#server-configuration} Задайте глобальні ліміти для однакової стелі кожної черги: diff --git a/i18n/uk/source-hashes.json b/i18n/uk/source-hashes.json index f3d1cd198fb..c384bb21231 100644 --- a/i18n/uk/source-hashes.json +++ b/i18n/uk/source-hashes.json @@ -86,12 +86,12 @@ "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", "polyglot/rust.md": "5ff66bcb7e5369bcffd8611342a35c27028cac5a4ee376e86d90334a2b12d365", "polyglot/server-api-reference.md": "e94af77a13b341d6fdc9941d4ee94e5053ab932d2e77069b238eb33351414e83", - "polyglot/server-config-reference.md": "edb4cf00b9df2c9946b32a81c6bb2c4db6eaee89794b85286c61c235a4846414", + "polyglot/server-config-reference.md": "b2dc3ddd188b078875cb46bf32b94053d89912c063c1687cc98ff5ba2baba812", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "7950b0c82dac2940c30b0aa042f3105dc9bdc70b524600cce4ed6d311cda7171", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", "polyglot/task-matching-dispatch.md": "9c8ffbbee16b5da48e7882721d7ba8eac209a374a6ca766d93d2b17e825b203d", - "polyglot/task-queue-admission.md": "47713eeaf3b10ead16b6b6c40816b97142d0f78670e40d181405db70ce49e7ac", + "polyglot/task-queue-admission.md": "ff04476dfca350f828d807b392d5e8b81c3c3baee252906021558a7eba6b936b", "polyglot/worker-build-id-rollout.md": "62ddf1ca054cf4b83de2fa020f313a153ece00519f804c4f8f30aca53c979af0", "polyglot/worker-compatibility-routing.md": "ef58f23c112f0e6b968927ba861177903adca21ed33b6b9371681e23a18b2994", "polyglot/worker-protocol.md": "007e844b0a7ab284b7cd343e79f01a27a0dabee3fe4cf19064170581bb897b85", 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 11b0e7b0dce..f9aaebb7c69 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 @@ -271,6 +271,74 @@ Server 镜像内置 `durable-workflow/workflow`,因此也提供包级 `DW_V2_* 配置 `DW_V2_MATCHING_ROLE_QUEUE_WAKE` 或专用 `workflow:v2:repair-pass --loop` 守护进程时,请参阅[任务匹配与分派](/docs/polyglot/task-matching-dispatch)。这些设置改变就绪任务的发现位置,而不改变 Worker 协议本身的契约。 +## 已发布 PHP Server 的其他配置 {#additional-published-php-controls} + +本参考覆盖已发布 **PHP Server 2.11.0** 的配置契约,包括下列设置。请检查实际运行的镜像;独立选择的安装版本可能更旧。`unset` 表示未提供环境变量值,其效果取决于具体设置。默认值和旧别名来自[已发布契约](https://github.com/durable-workflow/server/blob/36d16273604755f3dd0743cab331cc7c62e51d8e/config/dw-contract.php)。文档构建会按此版本化契约快照检查全部语言。本参考不改变选定的安装版本组合。 + +### 命名空间 HTTP 准入 {#namespace-request-controls} + +| 变量 | 默认值 | 用途 | 旧别名 | +| --- | --- | --- | --- | +| `DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | `unset` | 每个命名空间每分钟控制面请求数的可选上限;未设置即无限制。 | `WORKFLOW_SERVER_NAMESPACE_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_MAX_CONCURRENT_REQUESTS` | `unset` | 每个命名空间并发控制面请求数的可选上限;未设置即无限制。 | `WORKFLOW_SERVER_NAMESPACE_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | `unset` | 不可绕过的每分钟请求硬上限,也约束命名空间覆盖值。 | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE` | +| `DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | `unset` | 不可绕过的并发请求硬上限,也约束命名空间覆盖值。 | `WORKFLOW_SERVER_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS` | +| `DW_NAMESPACE_ADMISSION_OVERRIDES` | `{}` | 以命名空间为键的 JSON 对象,覆盖请求速率和并发数。 | `WORKFLOW_SERVER_NAMESPACE_ADMISSION_OVERRIDES` | + +[命名空间请求准入](./task-queue-admission.md#namespace-request-admission). + +### 命名空间持久状态配额 {#namespace-durable-controls} + +| 变量 | 默认值 | 用途 | 旧别名 | +| --- | --- | --- | --- | +| `DW_NAMESPACE_DURABLE_LIMITS` | `{}` | 命名空间持久行数默认配额 JSON。总量与 pending/open 限额相互独立;待处理任务只计算队列 ready 行,活动租约另有限额。空对象不限制。 | `WORKFLOW_SERVER_NAMESPACE_DURABLE_LIMITS` | +| `DW_NAMESPACE_DURABLE_HARD_LIMITS` | `{}` | 不可绕过的持久行数硬上限 JSON,也约束命名空间覆盖值;空对象不增加运维硬上限。 | `WORKFLOW_SERVER_NAMESPACE_DURABLE_HARD_LIMITS` | +| `DW_NAMESPACE_DURABLE_OVERRIDES` | `{}` | 按命名空间覆盖持久行数配额的 JSON;硬上限始终有效。 | `WORKFLOW_SERVER_NAMESPACE_DURABLE_OVERRIDES` | + +[命名空间持久状态配额](./task-queue-admission.md#namespace-durable-state). + +### 外部 payload 配额与 S3 传输 {#external-payload-quotas-and-s3} + +| 变量 | 默认值 | 用途 | 旧别名 | +| --- | --- | --- | --- | +| `DW_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | `unset` | 一次持租约完成操作的不可变 upload slots 中不同字节的总量;未设置时使用 `DW_EXTERNAL_PAYLOAD_MAX_BYTES`。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES` | +| `DW_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | `unset` | 每个命名空间外部 payload 累计字节数上限;就绪和进行中对象都计入,未设置即无限制。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | 每个命名空间外部 payload 对象数上限;就绪和进行中对象都计入,未设置即无限制。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | `unset` | 不可绕过的命名空间外部 payload 累计字节硬上限,也约束覆盖值。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | `unset` | 不可绕过的命名空间外部 payload 对象数硬上限,也约束覆盖值。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE` | +| `DW_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | `{}` | 以命名空间为键的 JSON 对象,覆盖 `max_bytes` 和 `max_objects` 配额。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES` | +| `DW_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | `unset` | 运行时管理的 S3 兼容磁盘的可选 access-key ID;由 workload identity 提供凭据时可省略。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID` | +| `DW_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | `unset` | 运行时管理的 S3 兼容磁盘的可选 secret access key;须与 access-key ID 一同设置。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY` | +| `DW_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | `unset` | 运行时管理的 S3 兼容磁盘临时凭据的可选 session token。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN` | +| `DW_EXTERNAL_PAYLOAD_S3_REGION` | `us-east-1` | 运行时管理的 S3 兼容磁盘所用区域。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_REGION` | +| `DW_EXTERNAL_PAYLOAD_S3_BUCKET` | `unset` | 运行时管理的 S3 兼容磁盘所用 bucket。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_BUCKET` | +| `DW_EXTERNAL_PAYLOAD_S3_ENDPOINT` | `unset` | 外部 payload S3 兼容服务的可选 HTTPS endpoint。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ENDPOINT` | +| `DW_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | `false` | 为运行时管理的 S3 兼容服务启用 path-style bucket 寻址。 | `WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT` | + +### 调用方命名空间服务边界 {#service-caller-namespace-controls} + +| 变量 | 默认值 | 用途 | 旧别名 | +| --- | --- | --- | --- | +| `DW_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | `unset` | 按调用方命名空间汇总、共享的每分钟服务调用数可选上限。 | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | `unset` | 按调用方命名空间汇总、共享的进行中服务调用数可选上限。 | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | `unset` | 不可绕过的每分钟硬上限,约束服务边界及调用方命名空间策略。 | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE` | +| `DW_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | `unset` | 不可绕过的进行中调用数硬上限,约束服务边界及调用方命名空间策略。 | `WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT` | +| `DW_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | `{}` | 调用方命名空间的服务调用速率及进行中数量覆盖 JSON;硬上限仍有效。 | `WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES` | + +### 协调、存储与运行时 {#coordination-storage-and-runtime-controls} + +| 变量 | 默认值 | 用途 | 旧别名 | +| --- | --- | --- | --- | +| `DW_OBSERVABILITY_CONTEXT_ENABLED` | `false` | 已安装可选 API 和 schema 时,启用受限 trace context 的持久化、传递及能力发现。 | - | +| `DW_OBSERVABILITY_BAGGAGE_ALLOWLIST` | `[]` | 允许出现在 run 来源中的 baggage 键 JSON 列表,默认为空。link 不携带 baggage。 | - | +| `DW_STORAGE_ADMISSION_FILE` | `unset` | 可选的本地只读存储压力观测文件;观测无效或过期时拒绝写入。 | - | +| `DW_STORAGE_ADMISSION_SOURCE` | `unset` | 准入观测中预期的存储资源标识。 | - | +| `DW_STORAGE_ADMISSION_MAX_AGE_SECONDS` | `15` | 存储观测的最大有效时间,单位秒,范围 1〜300。 | - | +| `DW_RUNTIME_CREDENTIALS_ENABLED` | `false` | 通过 admin API 启用由数据库持久保存、绑定命名空间的运行时 bearer 凭据。 | `WORKFLOW_SERVER_RUNTIME_CREDENTIALS_ENABLED` | +| `DW_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | 单个命名空间 workflow/activity 长轮询等待数的每节点上限,不超过全局 worker 等待上限;共享缓存权威状态不可用时拒绝。 | `WORKFLOW_SERVER_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | `unset` | 单个命名空间 query-task 长轮询等待数的每节点上限,不超过全局 query 等待上限;共享缓存权威状态不可用时拒绝。 | `WORKFLOW_SERVER_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE` | +| `DW_V1_ENABLED` | `false` | 仅为有意保留 v1 状态而启用 embedded v1 迁移和队列排空;独立 Server 默认仅支持 v2。 | `WORKFLOW_V1_ENABLED` | + ## 运行基础设施变量 {#runtime-infrastructure-variables} 运行基础设施变量属于框架及依赖项控制。Server 审计认识这些变量,因此不会发出警告,但它们不是稳定的 Durable Workflow API 配置项。 diff --git a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md index fe989e77976..14b96267951 100644 --- a/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md +++ b/i18n/zh-Hans/docusaurus-plugin-content-docs/current/polyglot/task-queue-admission.md @@ -89,6 +89,67 @@ class PaymentWorkflow: 受保护的下游调用应使用**普通排队活动**。内联本地活动不会创建普通活动任务,因此活动的队列、namespace 和预算组调度上限不会计量它们。prepared 本地活动领取验证执行权限,不检查这项调度预算。嵌入式 Laravel 没有独立 Server 的 admission;请使用其部署控制。参见[本地活动](../features/local-activities.md)。 +## 命名空间请求准入 {#namespace-request-admission} + +以下契约针对已发布的 **PHP Server 2.11.0**。请检查实际镜像及[版本化配置参考](./server-config-reference.md#additional-published-php-controls)。HTTP 预算独立于 worker slot、任务派发、保持中的轮询和持久状态配额。预算属于通过 `Durable-Workflow-Namespace` 或 `DW_DEFAULT_NAMESPACE` 解析出的请求命名空间,即使管理路径指向另一个命名空间也是如此。 + +经过认证并到达命名空间准入的请求,会在下列控制和管理路由族及其子路径上计数:`/api/namespaces`, `/api/storage`, `/api/workflows`, `/api/activities`, `/api/bridge-adapters`, `/api/workers`, `/api/worker-sessions`, `/api/task-queues`, `/api/deployments`, `/api/schedules`, `/api/search-attributes`, `/api/service-endpoints`, `/api/service-catalog`。复数形式的 `/api/workers` 管理请求也计数。 + +单数形式 `/api/worker/*` 的注册、轮询及结果上报不使用此 HTTP 预算。health/readiness、`/api/cluster/info`、管理员 `/api/system/*`、运行时凭据和外部 payload 传输也在此 gate 之外,但各自的认证、容量和存储检查仍有效。更早被认证、协议或命名空间解析拒绝的请求不会到达此计数器。 + +速率按 Server 时钟的固定分钟桶计算,不是平滑速率或滚动窗口。预算 N 可能在边界前接受 N 个请求、边界后再接受 N 个。后续失败仍计数;速率准入先于并发检查,所以并发拒绝也可能消耗分钟预算。并发 slot 一直保持到请求结束并清理释放,不计算运行中的工作流数量。 + +多个 API 副本须使用同一共享 Redis store/key prefix、同步时钟和一致的已加载配置。增加副本不会扩大共享预算。本地文件缓存只协调具有兼容写权限的进程,不是多节点基准配置。每节点的 worker/query 保持轮询上限是独立控制。[环境变更后应重启相关角色](./server-config-reference.md#how-changes-take-effect)。 + +```dotenv +DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE=100 +DW_NAMESPACE_MAX_CONCURRENT_REQUESTS=8 +DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE=150 +DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS=10 +DW_NAMESPACE_ADMISSION_OVERRIDES='{"payments":{"max_requests_per_minute":200,"max_concurrent_requests":12},"reports":{"max_requests_per_minute":40,"max_concurrent_requests":3}}' +``` + +对已有命名空间,示例使 `payments` 的有效值为每分钟150个、并发10个,`reports` 为40/3,其他为100/8。覆盖值可提高或降低默认值,但150/10硬上限仍有效。此配置不创建命名空间,也不预留吞吐量。 + +这些 HTTP 控制未设置时不增加对应限制,但单独设置硬上限仍可限制。null 覆盖值退回默认值。值必须是正整数,0无效。PHP 实现上限为每分钟10000000个请求、并发1024个,与实际 HTTP pool 容量无关。已发布 PHP2.11.0 会将格式错误的 `DW_NAMESPACE_ADMISSION_OVERRIDES` JSON 静默当成空覆盖表,退回全局默认值。部署前应验证 JSON;全局默认值和硬上限都未设置时,预期的命名空间上限会丢失。这一[已确认产品缺陷](https://github.com/durable-workflow/durable-workflow.github.io/issues/335#issuecomment-6369150521)不会由文档更新修复。 + +| 原因 | HTTP | 重试提示(秒) | +| --- | --- | --- | +| `namespace_request_rate_exhausted` | `429` | 距下一分钟,1〜60 | +| `namespace_request_concurrency_exhausted` | `429` | 1 | +| `namespace_request_admission_unavailable` | `503` | 1 | + +JSON `retry_after_seconds` 与 `Retry-After` 头一致。已配置协调不可用或数值上限无效时,以503拒绝。普通请求耗尽后仍可读取命名空间管理员指标;`dw_namespace_request_admission_rejections` 报告有限的原因集合。调用方应使用有限重试/backoff 并保持幂等;传输结果不确定不意味着可以自动重发写请求。另见[超时预算](../deployment.md#worker-long-poll-timeout-budgets)。 + +## 命名空间持久状态配额 {#namespace-durable-state} + +`DW_NAMESPACE_DURABLE_LIMITS` 设置保留行数默认限制,`DW_NAMESPACE_DURABLE_OVERRIDES` 按命名空间覆盖,`DW_NAMESPACE_DURABLE_HARD_LIMITS` 增加不可绕过的硬上限。空对象不增加限制。覆盖值可提高或降低默认值,null 退回默认值。与 HTTP 准入不同,持久配额0有效,会阻止新分配。此例中已有 `payments` 可持有250个开放 run,其他命名空间为100,硬上限为500。 + +```dotenv +DW_NAMESPACE_DURABLE_LIMITS='{"max_open_workflow_runs":100,"max_open_workflow_run_waits":200,"max_pending_workflow_timers":200}' +DW_NAMESPACE_DURABLE_HARD_LIMITS='{"max_open_workflow_runs":500}' +DW_NAMESPACE_DURABLE_OVERRIDES='{"payments":{"max_open_workflow_runs":250}}' +``` + +对下列资源使用 `max_` 字段。行计入自身所属命名空间,或关联工作流/run 的命名空间。保留总数与开放/待处理子集各有独立限制。执行时在命名空间行上串行化变更,以数据库权威计数为准。 + +| 资源 | 计数范围 | +| --- | --- | +| `workflow_instances`, `workflow_runs` | 所有保留的工作流实例/run 行,包括终态 run。 | +| `open_workflow_runs` | 状态为 `pending`、`running` 或 `waiting` 的 run。 | +| `workflow_history_events`, `workflow_commands`, `workflow_tasks` | 保留的历史、命令和工作流任务行。 | +| `pending_workflow_tasks` | 队列中状态为 `ready` 的工作流任务行;活动租约另有准入控制。 | +| `workflow_timers`, `pending_workflow_timers` | 所有保留 timer,及其中 `pending` 子集。 | +| `workflow_run_waits`, `open_workflow_run_waits` | 所有保留 run wait,及其中 `open` 子集。 | +| `schedules`, `schedule_history_events`, `worker_registrations` | 保留的 schedule、schedule history 和 worker 注册行;过期注册在删除前仍计数。 | +| `workflow_streams`, `workflow_stream_items` | 持久和入站 stream 行及其 item 行。 | + +等待子工作流或服务调用的父工作流仍占用自身命名空间的开放 run。子工作流增加自己的 run;同一命名空间应规划两个开放 run 及其 wait/timer。创建工作流的服务操作会在该工作流命名空间消耗行;对已有 run 的 signal/update 不会自动创建第二个 run。服务调用边界和外部 payload 配额是独立控制。 + +耗尽时返回429 `namespace__exhausted`。应读取 `retryable`:部分配额不可重试且不提供等待提示;可重试持久拒绝提示60秒,但不保证届时有容量。无法评估已配置配额时返回503 `namespace_durable_state_quota_unavailable`,提示1秒。保留行数压力可能需要 retention 或容量/配置变更,而不是紧密重试循环。 + +读取管理员指标时,用请求头选择命名空间。`dw_namespace_durable_state_usage` 及 JSON 字段 `limits`、`usage`、`remaining`、`configuration_status`、`measurement_status` 显示该范围;命名空间是请求范围,而非无界指标标签。测量不可用不表示使用量为0或容量无限。另见[完整配置参考](./server-config-reference.md#namespace-durable-controls)。 + ## Server 配置 {#server-configuration} 所有队列应采用同一上限时,设置全局上限: diff --git a/i18n/zh-Hans/source-hashes.json b/i18n/zh-Hans/source-hashes.json index f3d1cd198fb..c384bb21231 100644 --- a/i18n/zh-Hans/source-hashes.json +++ b/i18n/zh-Hans/source-hashes.json @@ -86,12 +86,12 @@ "polyglot/rust-cloud-quickstart.md": "2303434fc9302a81a8381ad4836423ef9952eb3201a4574c432254e3cb68c5f3", "polyglot/rust.md": "5ff66bcb7e5369bcffd8611342a35c27028cac5a4ee376e86d90334a2b12d365", "polyglot/server-api-reference.md": "e94af77a13b341d6fdc9941d4ee94e5053ab932d2e77069b238eb33351414e83", - "polyglot/server-config-reference.md": "edb4cf00b9df2c9946b32a81c6bb2c4db6eaee89794b85286c61c235a4846414", + "polyglot/server-config-reference.md": "b2dc3ddd188b078875cb46bf32b94053d89912c063c1687cc98ff5ba2baba812", "polyglot/server-role-topology.md": "3d048f0c6b5f179399622508f51e67fff8aa5a6d5b2492533fc720eeec2c27f2", "polyglot/server.md": "7950b0c82dac2940c30b0aa042f3105dc9bdc70b524600cce4ed6d311cda7171", "polyglot/service-operations.md": "a2ee46ac8d2e4f18aed4e3cb47a4f0b36f51ccc67f1e841efb99f0297391cf27", "polyglot/task-matching-dispatch.md": "9c8ffbbee16b5da48e7882721d7ba8eac209a374a6ca766d93d2b17e825b203d", - "polyglot/task-queue-admission.md": "47713eeaf3b10ead16b6b6c40816b97142d0f78670e40d181405db70ce49e7ac", + "polyglot/task-queue-admission.md": "ff04476dfca350f828d807b392d5e8b81c3c3baee252906021558a7eba6b936b", "polyglot/worker-build-id-rollout.md": "62ddf1ca054cf4b83de2fa020f313a153ece00519f804c4f8f30aca53c979af0", "polyglot/worker-compatibility-routing.md": "ef58f23c112f0e6b968927ba861177903adca21ed33b6b9371681e23a18b2994", "polyglot/worker-protocol.md": "007e844b0a7ab284b7cd343e79f01a27a0dabee3fe4cf19064170581bb897b85", diff --git a/package.json b/package.json index 4ead007189c..cbf438c78c5 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "postinstall": "patch-package", "prestart": "node scripts/check-dependency-security.js", "start": "docusaurus start", - "build": "npm run check:dependency-security && npm run check:node-toolchain && node scripts/check-helm-chart-pairing.test.js && node scripts/check-local-search.test.js && node scripts/check-doc-translation-updates.test.js && node scripts/check-doc-translations.js && node scripts/check-localized-links.test.js && docusaurus build && node scripts/generate-llms.js && node scripts/generate-llms-full.js", + "build": "npm run check:dependency-security && npm run check:node-toolchain && node scripts/check-helm-chart-pairing.test.js && node scripts/check-server-config-reference.test.js && node scripts/check-server-config-reference.js && node scripts/check-local-search.test.js && node scripts/check-doc-translation-updates.test.js && node scripts/check-doc-translations.js && node scripts/check-localized-links.test.js && docusaurus build && node scripts/generate-llms.js && node scripts/generate-llms-full.js", "check:node-toolchain": "node scripts/check-node-toolchain.js && node scripts/check-node-toolchain.test.js", "check:dependency-security": "node scripts/check-dependency-security.js && node scripts/check-dependency-security.test.js", "check:platform-protocol-specs": "node scripts/check-platform-protocol-specs.js", diff --git a/scripts/check-server-config-reference.js b/scripts/check-server-config-reference.js new file mode 100644 index 00000000000..299e2db8227 --- /dev/null +++ b/scripts/check-server-config-reference.js @@ -0,0 +1,88 @@ +const fs = require('node:fs'); +const path = require('node:path'); + +const root = path.resolve(__dirname, '..'); +const snapshot = require('../tests/fixtures/server-env-contract-2.11.0.json'); +const locales = ['en', 'uk', 'es', 'pt-BR', 'zh-Hans', 'ja', 'fr', 'de']; + +// The versioned input is the qualified published PHP contract. Updating this +// reference requires reviewing that artifact, not following unreleased main. +function validateSnapshot(contract) { + if (contract.schema_version !== 1 || contract.runtime !== 'php' + || !/^\d+\.\d+\.\d+$/.test(contract.server_version) + || !/^[a-f0-9]{40}$/.test(contract.source_revision) + || !/^[a-f0-9]{64}$/.test(contract.contract_file_sha256) + || !/^durableworkflow\/server@sha256:[a-f0-9]{64}$/.test(contract.image) + || contract.source_url !== `https://github.com/durable-workflow/server/blob/${contract.source_revision}/config/dw-contract.php` + || !contract.vars || Object.keys(contract.vars).length === 0) { + throw new Error('Server configuration snapshot needs a published PHP artifact and exact source identity'); + } + for (const [name, entry] of Object.entries(contract.vars)) { + if (!/^DW_[A-Z0-9_]+$/.test(name) || !entry.description + || !Object.hasOwn(entry, 'default') || !entry.since + || (entry.legacy !== undefined && !/^[A-Z][A-Z0-9_]+$/.test(entry.legacy))) { + throw new Error(`Invalid Server configuration contract entry: ${name}`); + } + } +} + +function referenceRows(markdown, locale) { + const rows = new Map(); + for (const line of markdown.split('\n')) { + const match = /^\|\s*`(DW_[A-Z0-9_]+)`\s*\|/.exec(line); + if (!match) continue; + const name = match[1]; + if (rows.has(name)) throw new Error(`${locale}: duplicate configuration row ${name}`); + rows.set(name, line.split(/(? cell.trim())); + } + return rows; +} + +function checkRow(name, cells, entry, locale) { + if (cells.length !== 4 || cells.some(cell => !cell)) { + throw new Error(`${locale}: ${name} needs variable, default, purpose and legacy-alias columns`); + } + if (cells[1] === '-' || cells[2] === '-') { + throw new Error(`${locale}: ${name} needs a documented default and purpose`); + } + const aliases = [...cells[3].matchAll(/`([A-Z][A-Z0-9_]+)`/g)].map(match => match[1]); + const expected = entry.legacy === undefined ? [] : [entry.legacy]; + if (JSON.stringify(aliases) !== JSON.stringify(expected)) { + throw new Error(`${locale}: ${name} legacy alias must match the published contract: ${expected.join(', ') || '(none)'}`); + } +} + +function checkReference(markdown, contract = snapshot, locale = 'en') { + validateSnapshot(contract); + const rows = referenceRows(markdown, locale); + const missing = Object.keys(contract.vars).filter(name => !rows.has(name)); + if (missing.length) throw new Error(`${locale}: missing published Server configuration rows: ${missing.join(', ')}`); + for (const [name, entry] of Object.entries(contract.vars)) { + checkRow(name, rows.get(name), entry, locale); + } + for (const name of rows.keys()) { + if (!Object.hasOwn(contract.vars, name)) throw new Error(`${locale}: ${name} is outside the published PHP configuration snapshot`); + } + return rows.size; +} + +function checkAllReferences() { + for (const locale of locales) { + const filename = locale === 'en' + ? path.join(root, 'docs/polyglot/server-config-reference.md') + : path.join(root, 'i18n', locale, 'docusaurus-plugin-content-docs/current/polyglot/server-config-reference.md'); + const count = checkReference(fs.readFileSync(filename, 'utf8'), snapshot, locale); + console.log(`${locale}: ${count} published PHP Server ${snapshot.server_version} configuration rows complete`); + } +} + +if (require.main === module) { + try { + checkAllReferences(); + } catch (error) { + console.error(error.message); + process.exitCode = 1; + } +} + +module.exports = {checkReference, validateSnapshot}; diff --git a/scripts/check-server-config-reference.test.js b/scripts/check-server-config-reference.test.js new file mode 100644 index 00000000000..5f9d3773143 --- /dev/null +++ b/scripts/check-server-config-reference.test.js @@ -0,0 +1,39 @@ +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const path = require('node:path'); +const test = require('node:test'); +const snapshot = require('../tests/fixtures/server-env-contract-2.11.0.json'); +const {checkReference, validateSnapshot} = require('./check-server-config-reference'); +const source = fs.readFileSync(path.join(__dirname, '../docs/polyglot/server-config-reference.md'), 'utf8'); +const variable = 'DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE'; +const row = source.split('\n').find(line => line.startsWith(`| \`${variable}\` |`)); + +test('qualified published contract has a complete reference', () => { + assert.equal(checkReference(source), Object.keys(snapshot.vars).length); +}); + +test('a name mentioned in prose does not replace its configuration row', () => { + assert.ok(row, 'the reference must have a namespace request-rate row'); + const missing = source.replace(row, `The control is \`${variable}\`.`); + assert.throws(() => checkReference(missing), /missing published Server configuration rows: DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE/); +}); + +test('the documented legacy alias must match the published contract', () => { + const wrongAlias = source.replace(row, row.replace('WORKFLOW_SERVER_NAMESPACE_MAX_REQUESTS_PER_MINUTE', 'WORKFLOW_SERVER_WRONG_RATE')); + assert.throws(() => checkReference(wrongAlias), /legacy alias must match the published contract/); +}); + +test('configuration rows retain a populated default and purpose', () => { + const cells = row.split('|'); + for (const column of [2, 3]) { + const incomplete = [...cells]; + incomplete[column] = ' '; + assert.throws(() => checkReference(source.replace(row, incomplete.join('|'))), /needs variable, default, purpose/); + } +}); + +test('published snapshot provenance cannot be replaced by a moving source branch', () => { + const unqualified = structuredClone(snapshot); + unqualified.source_revision = 'main'; + assert.throws(() => validateSnapshot(unqualified), /published PHP artifact and exact source identity/); +}); diff --git a/tests/fixtures/server-env-contract-2.11.0.json b/tests/fixtures/server-env-contract-2.11.0.json new file mode 100644 index 00000000000..0a1f0de7fab --- /dev/null +++ b/tests/fixtures/server-env-contract-2.11.0.json @@ -0,0 +1,987 @@ +{ + "schema_version": 1, + "runtime": "php", + "server_version": "2.11.0", + "source_revision": "36d16273604755f3dd0743cab331cc7c62e51d8e", + "source_url": "https://github.com/durable-workflow/server/blob/36d16273604755f3dd0743cab331cc7c62e51d8e/config/dw-contract.php", + "contract_file_sha256": "4e6ab12b029d7da3d0c76d082f3b0901c3d234651721c74d296ebe24ba142f69", + "image": "durableworkflow/server@sha256:b29157eb2cf844916debbbb3c01b3257672e0dece778a9c6fa539043a3038f02", + "vars": { + "DW_OBSERVABILITY_CONTEXT_ENABLED": { + "description": "Enable optional bounded trace context persistence, delivery and capability discovery when its optional API and schema are installed.", + "default": "false", + "since": "2.10.0" + }, + "DW_OBSERVABILITY_BAGGAGE_ALLOWLIST": { + "description": "JSON list of baggage keys permitted on run origins; default empty. Links never carry baggage.", + "default": "[]", + "since": "2.10.0" + }, + "DW_MODE": { + "description": "Server mode: \"service\" (default, external workers poll) or \"embedded\" (local queue).", + "default": "service", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_MODE" + }, + "DW_SERVER_ID": { + "description": "Unique identifier for this server instance, used in lease ownership and worker registration.", + "default": "gethostname()", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_ID" + }, + "DW_SERVER_TOPOLOGY_SHAPE": { + "description": "Advertised topology shape for this node in cluster discovery (`embedded`, `standalone_server`, or `split_control_execution`).", + "default": "standalone_server", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_TOPOLOGY_SHAPE" + }, + "DW_SERVER_PROCESS_CLASS": { + "description": "Advertised process class for this node within the selected topology shape, such as `server_http_node` or `scheduler_node`.", + "default": "server_http_node", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_PROCESS_CLASS" + }, + "DW_SERVER_KEY": { + "description": "Optional server-internal runtime key. Docker images generate one automatically when unset.", + "default": "generated at container boot", + "since": "2.0.0" + }, + "DW_DEFAULT_NAMESPACE": { + "description": "Namespace used when a request does not carry the Durable-Workflow-Namespace header.", + "default": "default", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_DEFAULT_NAMESPACE" + }, + "DW_TASK_DISPATCH_MODE": { + "description": "Override for workflows.v2.task_dispatch_mode. In service mode the server defaults to \"poll\"; set \"queue\" to dispatch locally anyway.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_V2_TASK_DISPATCH_MODE" + }, + "DW_WORKFLOW_MEMO_MIGRATION_RECOVERY": { + "description": "One-run MySQL recovery proof for an unrecorded memo rewrite: \"raw-json\" or \"envelope-prefix:\".", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKFLOW_MEMO_MIGRATION_RECOVERY" + }, + "DW_EXTERNAL_EXECUTOR_CONFIG_PATH": { + "description": "Optional path to a durable-workflow.external-executor.config JSON file for external executor handler mappings.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_EXTERNAL_EXECUTOR_CONFIG_PATH" + }, + "DW_EXTERNAL_EXECUTOR_CONFIG_OVERLAY": { + "description": "Optional overlay name from the external executor config file to apply before server validation and discovery.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_EXTERNAL_EXECUTOR_CONFIG_OVERLAY" + }, + "DW_STORAGE_ADMISSION_FILE": { + "description": "Optional read-only local storage-pressure observation file; invalid or stale observations fence writes.", + "default": null, + "since": "2.3.0" + }, + "DW_STORAGE_ADMISSION_SOURCE": { + "description": "Expected storage resource identity in the admission observation.", + "default": null, + "since": "2.3.0" + }, + "DW_STORAGE_ADMISSION_MAX_AGE_SECONDS": { + "description": "Maximum age of a storage observation in seconds (1-300).", + "default": "15", + "since": "2.3.0" + }, + "DW_AUTH_PROVIDER": { + "description": "Optional FQCN of a Laravel-resolvable class implementing App\\Contracts\\AuthProvider.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_AUTH_PROVIDER" + }, + "DW_AUTH_DRIVER": { + "description": "Auth driver: \"none\", \"token\", or \"signature\".", + "default": "token", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_AUTH_DRIVER" + }, + "DW_AUTH_TOKEN": { + "description": "Single shared bearer token when no role-scoped token is configured (backward-compat credential).", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_AUTH_TOKEN" + }, + "DW_SIGNATURE_KEY": { + "description": "HMAC signature key used when DW_AUTH_DRIVER=signature and no role-scoped key is configured.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_SIGNATURE_KEY" + }, + "DW_WORKER_TOKEN": { + "description": "Bearer token for the worker role (worker registration, deregistration, poll, heartbeat, completion endpoints).", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKER_TOKEN" + }, + "DW_OPERATOR_TOKEN": { + "description": "Bearer token for the operator role (control plane plus diagnostic worker registration; polling remains worker-only).", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_OPERATOR_TOKEN" + }, + "DW_ADMIN_TOKEN": { + "description": "Bearer token for the admin role (mutating control plane plus diagnostic worker registration; polling remains worker-only).", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_ADMIN_TOKEN" + }, + "DW_PRINCIPAL_TOKENS": { + "description": "JSON token map for named bearer-token principals; each entry supplies token, subject, roles, optional tenant, label, and non-secret claims.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_PRINCIPAL_TOKENS" + }, + "DW_RUNTIME_CREDENTIALS_ENABLED": { + "description": "Enable durable, database-backed, namespace-bound runtime bearer credentials managed through the admin API.", + "default": "false", + "since": "2.1.0", + "legacy": "WORKFLOW_SERVER_RUNTIME_CREDENTIALS_ENABLED" + }, + "DW_WORKER_SIGNATURE_KEY": { + "description": "HMAC signature key for the worker role (worker registration, deregistration, poll, heartbeat, completion endpoints) when DW_AUTH_DRIVER=signature.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKER_SIGNATURE_KEY" + }, + "DW_OPERATOR_SIGNATURE_KEY": { + "description": "HMAC signature key for the operator role (control plane plus diagnostic worker registration; polling remains worker-only) when DW_AUTH_DRIVER=signature.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_OPERATOR_SIGNATURE_KEY" + }, + "DW_ADMIN_SIGNATURE_KEY": { + "description": "HMAC signature key for the admin role (mutating control plane plus diagnostic worker registration; polling remains worker-only) when DW_AUTH_DRIVER=signature.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_ADMIN_SIGNATURE_KEY" + }, + "DW_AUTH_BACKWARD_COMPATIBLE": { + "description": "When true, honor the single DW_AUTH_TOKEN / DW_SIGNATURE_KEY as a fallback when a role-scoped credential is missing.", + "default": "true", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_AUTH_BACKWARD_COMPATIBLE" + }, + "DW_TRUST_FORWARDED_ATTRIBUTION_HEADERS": { + "description": "When true, record forwarded caller/auth headers from a trusted gateway into workflow command history.", + "default": "false", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_TRUST_FORWARDED_ATTRIBUTION_HEADERS" + }, + "DW_CALLER_TYPE_HEADER": { + "description": "Request header that carries the forwarded caller type.", + "default": "X-Workflow-Caller-Type", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_CALLER_TYPE_HEADER" + }, + "DW_CALLER_LABEL_HEADER": { + "description": "Request header that carries the forwarded caller label.", + "default": "X-Workflow-Caller-Label", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_CALLER_LABEL_HEADER" + }, + "DW_AUTH_STATUS_HEADER": { + "description": "Request header that carries the forwarded auth status.", + "default": "X-Workflow-Auth-Status", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_AUTH_STATUS_HEADER" + }, + "DW_AUTH_METHOD_HEADER": { + "description": "Request header that carries the forwarded auth method.", + "default": "X-Workflow-Auth-Method", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_AUTH_METHOD_HEADER" + }, + "DW_WORKER_POLL_TIMEOUT": { + "description": "Seconds the server holds a poll open waiting for a task.", + "default": "30", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKER_POLL_TIMEOUT" + }, + "DW_WORKER_POLL_INTERVAL_MS": { + "description": "Milliseconds between internal scans while a poll is held open.", + "default": "1000", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKER_POLL_INTERVAL_MS" + }, + "DW_WORKER_POLL_SIGNAL_CHECK_INTERVAL_MS": { + "description": "Milliseconds between wake-signal checks while a poll is held open.", + "default": "100", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKER_POLL_SIGNAL_CHECK_INTERVAL_MS" + }, + "DW_POLLING_CACHE_PATH": { + "description": "Directory for worker-poll coordination state.", + "default": "storage/framework/cache/server-polling/", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_POLLING_CACHE_PATH" + }, + "DW_WAKE_SIGNAL_TTL_SECONDS": { + "description": "TTL for per-queue wake signals that short-circuit a pending poll.", + "default": "max(DW_WORKER_POLL_TIMEOUT + 5, 60)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WAKE_SIGNAL_TTL_SECONDS" + }, + "DW_WORKER_LONG_POLL_MAX_CONCURRENT": { + "description": "Optional cap for concurrent held workflow/activity worker long-poll waits on this server node. Polls above the cap receive an immediate typed HTTP 429 response with an advertised Retry-After delay after their immediate task probe. Query-task polls use their own wait budget so live workflow queries are not starved by idle workflow/activity waits. Unset derives from PHP_CLI_SERVER_WORKERS minus the configured or derived HTTP worker reserve, the derived query-task poll wait budget, and an additional API worker reserve when the standalone CLI server declares a worker count.", + "default": "(unset; derived for PHP_CLI_SERVER_WORKERS)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKER_LONG_POLL_MAX_CONCURRENT" + }, + "DW_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE": { + "description": "Optional per-node cap for concurrent held workflow/activity long-poll waits from one namespace. The effective cap cannot exceed the global worker wait cap. Configured namespace isolation fails closed when shared cache authority is unavailable.", + "default": "(unset)", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_WORKER_LONG_POLL_MAX_CONCURRENT_PER_NAMESPACE" + }, + "DW_WORKER_LONG_POLL_RESERVED_HTTP_WORKERS": { + "description": "Optional number of PHP CLI server workers reserved for health and control-plane requests when deriving the workflow/activity long-poll wait cap. Unset derives a reserve from PHP_CLI_SERVER_WORKERS, keeping more than half of declared standalone CLI server workers outside held long-poll waits.", + "default": "(unset; derived from PHP_CLI_SERVER_WORKERS)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKER_LONG_POLL_RESERVED_HTTP_WORKERS" + }, + "DW_MAX_TASKS_PER_POLL": { + "description": "Maximum tasks returned per worker poll.", + "default": "1", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_MAX_TASKS_PER_POLL" + }, + "DW_SQLITE_CLAIM_LOCK_TTL_SECONDS": { + "description": "Seconds the SQLite quickstart backend holds the cache-backed worker poll claim gate before the lock expires.", + "default": "10", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_SQLITE_CLAIM_LOCK_TTL_SECONDS" + }, + "DW_SQLITE_CLAIM_LOCK_WAIT_SECONDS": { + "description": "Seconds SQLite worker poll claims wait for the cache-backed claim gate before returning backend lock pressure.", + "default": "5", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_SQLITE_CLAIM_LOCK_WAIT_SECONDS" + }, + "DW_WORKFLOW_TASK_MAX_ACTIVE_LEASES_PER_QUEUE": { + "description": "Optional server-side cap for active workflow-task leases per namespace/task queue. Unset means no server-side cap beyond worker registration capacity.", + "default": "(unset)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKFLOW_TASK_MAX_ACTIVE_LEASES_PER_QUEUE" + }, + "DW_WORKFLOW_TASK_MAX_ACTIVE_LEASES_PER_NAMESPACE": { + "description": "Optional server-side cap for active workflow-task leases across all task queues in a namespace. Unset means no namespace-wide active lease cap.", + "default": "(unset)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKFLOW_TASK_MAX_ACTIVE_LEASES_PER_NAMESPACE" + }, + "DW_WORKFLOW_TASK_MAX_DISPATCHES_PER_MINUTE": { + "description": "Optional server-side per-minute workflow-task dispatch cap per namespace/task queue. Unset means no server-side dispatch-rate cap.", + "default": "(unset)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKFLOW_TASK_MAX_DISPATCHES_PER_MINUTE" + }, + "DW_WORKFLOW_TASK_MAX_DISPATCHES_PER_MINUTE_PER_NAMESPACE": { + "description": "Optional server-side per-minute workflow-task dispatch cap across all task queues in a namespace. Unset means no namespace-wide dispatch-rate cap.", + "default": "(unset)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKFLOW_TASK_MAX_DISPATCHES_PER_MINUTE_PER_NAMESPACE" + }, + "DW_ACTIVITY_TASK_MAX_ACTIVE_LEASES_PER_QUEUE": { + "description": "Optional server-side cap for active activity-task leases per namespace/task queue. Unset means no server-side cap beyond worker registration capacity.", + "default": "(unset)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_ACTIVITY_TASK_MAX_ACTIVE_LEASES_PER_QUEUE" + }, + "DW_ACTIVITY_TASK_MAX_ACTIVE_LEASES_PER_NAMESPACE": { + "description": "Optional server-side cap for active activity-task leases across all task queues in a namespace. Unset means no namespace-wide active lease cap.", + "default": "(unset)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_ACTIVITY_TASK_MAX_ACTIVE_LEASES_PER_NAMESPACE" + }, + "DW_ACTIVITY_TASK_MAX_DISPATCHES_PER_MINUTE": { + "description": "Optional server-side per-minute activity-task dispatch cap per namespace/task queue. Unset means no server-side dispatch-rate cap.", + "default": "(unset)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_ACTIVITY_TASK_MAX_DISPATCHES_PER_MINUTE" + }, + "DW_ACTIVITY_TASK_MAX_DISPATCHES_PER_MINUTE_PER_NAMESPACE": { + "description": "Optional server-side per-minute activity-task dispatch cap across all task queues in a namespace. Unset means no namespace-wide dispatch-rate cap.", + "default": "(unset)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_ACTIVITY_TASK_MAX_DISPATCHES_PER_MINUTE_PER_NAMESPACE" + }, + "DW_TASK_QUEUE_ADMISSION_OVERRIDES": { + "description": "JSON object keyed by \"namespace:task_queue\", \"namespace:*\", \"task_queue\", or \"*\" with workflow_tasks/activity_tasks active-lease, dispatch-rate, namespace, and downstream budget-group overrides.", + "default": "{}", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_TASK_QUEUE_ADMISSION_OVERRIDES" + }, + "DW_NAMESPACE_MAX_REQUESTS_PER_MINUTE": { + "description": "Optional per-minute control-plane request cap for each namespace. Unset means unlimited.", + "default": "(unset)", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_NAMESPACE_MAX_REQUESTS_PER_MINUTE" + }, + "DW_NAMESPACE_MAX_CONCURRENT_REQUESTS": { + "description": "Optional concurrent control-plane request cap for each namespace. Unset means unlimited.", + "default": "(unset)", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_NAMESPACE_MAX_CONCURRENT_REQUESTS" + }, + "DW_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE": { + "description": "Non-bypassable ceiling for namespace control-plane requests per minute, including namespace overrides.", + "default": "(unset)", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_NAMESPACE_HARD_MAX_REQUESTS_PER_MINUTE" + }, + "DW_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS": { + "description": "Non-bypassable ceiling for concurrent namespace control-plane requests, including namespace overrides.", + "default": "(unset)", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_NAMESPACE_HARD_MAX_CONCURRENT_REQUESTS" + }, + "DW_NAMESPACE_ADMISSION_OVERRIDES": { + "description": "JSON object keyed by namespace with optional request-rate and concurrent-request overrides.", + "default": "{}", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_NAMESPACE_ADMISSION_OVERRIDES" + }, + "DW_NAMESPACE_DURABLE_LIMITS": { + "description": "JSON object of default per-namespace durable row limits across workflow instances, runs, history, tasks, timers, waits, commands, schedules, workers, and streams. Lifetime and pending/open limits are independent; pending workflow tasks count queued ready rows because active leases have separate admission limits. An empty object is unlimited.", + "default": "{}", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_NAMESPACE_DURABLE_LIMITS" + }, + "DW_NAMESPACE_DURABLE_HARD_LIMITS": { + "description": "JSON object of non-bypassable ceilings for the namespace durable row limit fields, including per-namespace overrides. An empty object adds no operator hard ceilings.", + "default": "{}", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_NAMESPACE_DURABLE_HARD_LIMITS" + }, + "DW_NAMESPACE_DURABLE_OVERRIDES": { + "description": "JSON object keyed by namespace with optional namespace durable row limit overrides. Hard limits remain authoritative.", + "default": "{}", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_NAMESPACE_DURABLE_OVERRIDES" + }, + "DW_DUE_TIMER_RECOVERY_SCAN_LIMIT": { + "description": "Maximum due service-mode timer tasks to recover per worker poll pass.", + "default": "5", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_DUE_TIMER_RECOVERY_SCAN_LIMIT" + }, + "DW_EXPIRED_WORKFLOW_TASK_RECOVERY_SCAN_LIMIT": { + "description": "Maximum expired workflow tasks to recover per pass.", + "default": "5", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_EXPIRED_WORKFLOW_TASK_RECOVERY_SCAN_LIMIT" + }, + "DW_EXPIRED_WORKFLOW_TASK_RECOVERY_TTL_SECONDS": { + "description": "Minimum seconds between expired-task recovery passes per queue.", + "default": "5", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_EXPIRED_WORKFLOW_TASK_RECOVERY_TTL_SECONDS" + }, + "DW_WORKER_PROTOCOL_VERSION": { + "description": "Override for the worker protocol version advertised on worker-plane responses.", + "default": "WorkerProtocol::VERSION", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKER_PROTOCOL_VERSION" + }, + "DW_HISTORY_PAGE_SIZE_DEFAULT": { + "description": "Default page size for worker history reads when the client does not request one.", + "default": "WorkerProtocolVersion::DEFAULT_HISTORY_PAGE_SIZE", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_HISTORY_PAGE_SIZE_DEFAULT" + }, + "DW_HISTORY_PAGE_SIZE_MAX": { + "description": "Maximum page size honored on worker history reads.", + "default": "WorkerProtocolVersion::MAX_HISTORY_PAGE_SIZE", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_HISTORY_PAGE_SIZE_MAX" + }, + "DW_UPDATE_VALIDATION_TIMEOUT": { + "description": "Seconds the control plane waits for a synchronous pre-accept update validator result.", + "default": "10", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_UPDATE_VALIDATION_TIMEOUT" + }, + "DW_UPDATE_VALIDATION_LEASE_TIMEOUT": { + "description": "Seconds an update-validation task lease remains owned before a replacement validator-capable worker may retry it.", + "default": "5", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_UPDATE_VALIDATION_LEASE_TIMEOUT" + }, + "DW_QUERY_TASK_TIMEOUT": { + "description": "Seconds the control plane waits for a query task response from the worker. The default covers one worker long-poll cycle plus dispatch grace, with a 40 second floor and a 55 second structured-response ceiling.", + "default": "min(max(DW_WORKER_POLL_TIMEOUT + 15, 40), 55)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_QUERY_TASK_TIMEOUT" + }, + "DW_QUERY_TASK_LEASE_TIMEOUT": { + "description": "Configured lease timeout (seconds) for ephemeral query tasks, with a runtime minimum of 1 second. Each claim expires at the earlier of claim time plus this timeout and the original query deadline.", + "default": "DW_WORKFLOW_TASK_TIMEOUT", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_QUERY_TASK_LEASE_TIMEOUT" + }, + "DW_QUERY_TASK_POLL_TIMEOUT": { + "description": "Maximum seconds a single query-task worker poll may wait before returning empty. Workers can immediately re-poll; the shorter window keeps synchronous control-plane queries from depending on one long-held worker request.", + "default": "5", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_QUERY_TASK_POLL_TIMEOUT" + }, + "DW_QUERY_TASK_TTL_SECONDS": { + "description": "Configured retention floor for query-task result rows. Effective retention is max(60, this floor, query timeout plus configured lease timeout (minimum 1) plus 60) seconds. Retention does not extend query execution authority.", + "default": "180", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_QUERY_TASK_TTL_SECONDS" + }, + "DW_QUERY_TASK_MAX_PENDING_PER_QUEUE": { + "description": "Maximum pending cache-backed query tasks retained per namespace/task queue before new control-plane queries are rejected.", + "default": "1024", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_QUERY_TASK_MAX_PENDING_PER_QUEUE" + }, + "DW_QUERY_TASK_POLL_MAX_CONCURRENT": { + "description": "Optional cap for concurrent held idle query-task worker long-poll waits on this server node. Polls above the cap receive an immediate typed HTTP 429 response with an advertised Retry-After delay after their immediate task probe. Pending query tasks can still be claimed immediately before a poll waits. Unset derives one held query-task poll when PHP_CLI_SERVER_WORKERS leaves capacity after reserved HTTP workers, API-reserved workers, and workflow/activity waits.", + "default": "(unset; derived for PHP_CLI_SERVER_WORKERS)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_QUERY_TASK_POLL_MAX_CONCURRENT" + }, + "DW_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE": { + "description": "Optional per-node cap for concurrent held query-task long-poll waits from one namespace. The effective cap cannot exceed the global query-task wait cap. Configured namespace isolation fails closed when shared cache authority is unavailable.", + "default": "(unset)", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_QUERY_TASK_POLL_MAX_CONCURRENT_PER_NAMESPACE" + }, + "DW_WORKFLOW_TASK_TIMEOUT": { + "description": "Default workflow-task lease timeout in seconds.", + "default": "60", + "since": "2.0.0", + "legacy": "WORKFLOW_TASK_TIMEOUT" + }, + "DW_ACTIVITY_TASK_TIMEOUT": { + "description": "Default activity-task lease timeout in seconds.", + "default": "300", + "since": "2.0.0", + "legacy": "ACTIVITY_TASK_TIMEOUT" + }, + "DW_WORKER_STALE_AFTER_SECONDS": { + "description": "Seconds after a worker heartbeat before the worker registration is surfaced as stale.", + "default": "max(DW_WORKER_HEARTBEAT_INTERVAL_SECONDS * 3, 30)", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_WORKER_STALE_AFTER_SECONDS" + }, + "DW_WORKER_HEARTBEAT_INTERVAL_SECONDS": { + "description": "Cadence (in seconds) the server advertises to SDKs in the register/heartbeat acknowledgement so each official SDK ticks at the same beat. Bounded to [1, 3600].", + "default": "10", + "since": "2.1.0", + "legacy": "WORKFLOW_SERVER_WORKER_HEARTBEAT_INTERVAL_SECONDS" + }, + "DW_METRICS_WORKFLOW_TASK_FAILURE_TYPE_LIMIT": { + "description": "Maximum workflow_type series reported by dw_workflow_task_consecutive_failures; excess types are summarized.", + "default": "20", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_METRICS_WORKFLOW_TASK_FAILURE_TYPE_LIMIT" + }, + "DW_METRICS_PROMETHEUS_WORKFLOW_SERIES_LIMIT": { + "description": "Maximum workflow series reported by /api/system/prometheus-metrics before excess series are summarized.", + "default": "100", + "since": "2.1.0", + "legacy": "WORKFLOW_SERVER_METRICS_PROMETHEUS_WORKFLOW_SERIES_LIMIT" + }, + "DW_METRICS_PROMETHEUS_ACTIVITY_SERIES_LIMIT": { + "description": "Maximum activity series reported by /api/system/prometheus-metrics before excess series are summarized.", + "default": "100", + "since": "2.1.0", + "legacy": "WORKFLOW_SERVER_METRICS_PROMETHEUS_ACTIVITY_SERIES_LIMIT" + }, + "DW_METRICS_PROMETHEUS_TASK_QUEUE_SERIES_LIMIT": { + "description": "Maximum task-queue runtime series reported by /api/system/prometheus-metrics before excess series are summarized.", + "default": "100", + "since": "2.1.0", + "legacy": "WORKFLOW_SERVER_METRICS_PROMETHEUS_TASK_QUEUE_SERIES_LIMIT" + }, + "DW_MAX_HISTORY_EVENTS": { + "description": "Maximum history events per workflow run before continue-as-new is enforced.", + "default": "50000", + "since": "2.0.0", + "legacy": "WORKFLOW_MAX_HISTORY_EVENTS" + }, + "DW_HISTORY_RETENTION_DAYS": { + "description": "Default number of days closed-run history is retained when a namespace does not override it.", + "default": "30", + "since": "2.0.0", + "legacy": "WORKFLOW_HISTORY_RETENTION_DAYS" + }, + "DW_MAX_PAYLOAD_BYTES": { + "description": "Maximum serialized bytes for a single payload (input/output/signal/update).", + "default": "2097152", + "since": "2.0.0", + "legacy": "WORKFLOW_MAX_PAYLOAD_BYTES" + }, + "DW_EXTERNAL_PAYLOAD_MAX_BYTES": { + "description": "Maximum encoded bytes accepted by the authenticated runtime external-payload transport.", + "default": "67108864", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_BYTES" + }, + "DW_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES": { + "description": "Distinct bytes allowed across immutable upload slots for one leased completion; unset uses DW_EXTERNAL_PAYLOAD_MAX_BYTES.", + "default": "(unset)", + "since": "2.3.5", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_COMPLETION_MAX_BYTES" + }, + "DW_EXTERNAL_PAYLOAD_REQUEST_TIMEOUT": { + "description": "Client-facing request-timeout budget advertised for external-payload upload and fetch.", + "default": "30", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_REQUEST_TIMEOUT" + }, + "DW_EXTERNAL_PAYLOAD_UPLOAD_EXPIRY": { + "description": "Seconds an uploaded external payload may remain unclaimed before its opaque reference expires.", + "default": "3600", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_UPLOAD_EXPIRY" + }, + "DW_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE": { + "description": "Optional cumulative external-payload byte cap for each namespace. Ready and in-progress objects count toward the cap; unset means unlimited.", + "default": "(unset)", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_BYTES_PER_NAMESPACE" + }, + "DW_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE": { + "description": "Optional external-payload object-count cap for each namespace. Ready and in-progress objects count toward the cap; unset means unlimited.", + "default": "(unset)", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_MAX_OBJECTS_PER_NAMESPACE" + }, + "DW_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE": { + "description": "Non-bypassable cumulative external-payload byte ceiling for each namespace, including namespace overrides.", + "default": "(unset)", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_BYTES_PER_NAMESPACE" + }, + "DW_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE": { + "description": "Non-bypassable external-payload object-count ceiling for each namespace, including namespace overrides.", + "default": "(unset)", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_HARD_MAX_OBJECTS_PER_NAMESPACE" + }, + "DW_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES": { + "description": "JSON object keyed by namespace with optional max_bytes and max_objects external-payload quota overrides.", + "default": "{}", + "since": "2.0.3", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_NAMESPACE_OVERRIDES" + }, + "DW_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID": { + "description": "Optional access-key ID for the runtime-managed S3-compatible external-payload disk. May be omitted when workload identity supplies credentials.", + "default": "(unset)", + "since": "2.0.4", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ACCESS_KEY_ID" + }, + "DW_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY": { + "description": "Optional secret access key for the runtime-managed S3-compatible external-payload disk. Must be set with the access-key ID.", + "default": "(unset)", + "since": "2.0.4", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SECRET_ACCESS_KEY" + }, + "DW_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN": { + "description": "Optional session token for temporary credentials on the runtime-managed S3-compatible external-payload disk.", + "default": "(unset)", + "since": "2.0.4", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_SESSION_TOKEN" + }, + "DW_EXTERNAL_PAYLOAD_S3_REGION": { + "description": "Region used by the runtime-managed S3-compatible external-payload disk.", + "default": "us-east-1", + "since": "2.0.4", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_REGION" + }, + "DW_EXTERNAL_PAYLOAD_S3_BUCKET": { + "description": "Bucket used by the runtime-managed S3-compatible external-payload disk.", + "default": "(unset)", + "since": "2.0.4", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_BUCKET" + }, + "DW_EXTERNAL_PAYLOAD_S3_ENDPOINT": { + "description": "Optional HTTPS endpoint for an S3-compatible external-payload service.", + "default": "(unset)", + "since": "2.0.4", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_ENDPOINT" + }, + "DW_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT": { + "description": "Use path-style bucket addressing for the runtime-managed S3-compatible external-payload service.", + "default": "false", + "since": "2.0.4", + "legacy": "WORKFLOW_SERVER_EXTERNAL_PAYLOAD_S3_USE_PATH_STYLE_ENDPOINT" + }, + "DW_MAX_MEMO_BYTES": { + "description": "Maximum serialized bytes for a workflow memo.", + "default": "262144", + "since": "2.0.0", + "legacy": "WORKFLOW_MAX_MEMO_BYTES" + }, + "DW_MAX_SEARCH_ATTRIBUTES": { + "description": "Maximum number of search attributes on a single workflow.", + "default": "100", + "since": "2.0.0", + "legacy": "WORKFLOW_MAX_SEARCH_ATTRIBUTES" + }, + "DW_MAX_SEARCH_ATTRIBUTE_KEY_LENGTH": { + "description": "Maximum length in bytes for a single search-attribute key at the request boundary.", + "default": "128", + "since": "2.0.0", + "legacy": "WORKFLOW_MAX_SEARCH_ATTRIBUTE_KEY_LENGTH" + }, + "DW_MAX_SEARCH_ATTRIBUTE_VALUE_BYTES": { + "description": "Maximum size in bytes for a single search-attribute string value at the request boundary.", + "default": "2048", + "since": "2.0.0", + "legacy": "WORKFLOW_MAX_SEARCH_ATTRIBUTE_VALUE_BYTES" + }, + "DW_MAX_OPERATION_NAME_LENGTH": { + "description": "Maximum length in bytes for a signal, update, or query name accepted at the request boundary.", + "default": "256", + "since": "2.0.0", + "legacy": "WORKFLOW_MAX_OPERATION_NAME_LENGTH" + }, + "DW_MAX_PENDING_ACTIVITIES": { + "description": "Maximum pending activities per workflow run before the server rejects a command batch.", + "default": "2000", + "since": "2.0.0", + "legacy": "WORKFLOW_MAX_PENDING_ACTIVITIES" + }, + "DW_MAX_PENDING_CHILDREN": { + "description": "Maximum pending child workflows per run before the server rejects a command batch.", + "default": "2000", + "since": "2.0.0", + "legacy": "WORKFLOW_MAX_PENDING_CHILDREN" + }, + "DW_MAX_NEXUS_OPERATIONS_PER_CALLER": { + "description": "Maximum Nexus operations returned per caller from the operations history surface before clients must paginate.", + "default": "200", + "since": "2.1.0", + "legacy": "WORKFLOW_MAX_NEXUS_OPERATIONS_PER_CALLER" + }, + "DW_COMPRESSION_ENABLED": { + "description": "Enable response compression for JSON payloads above the minimum size threshold.", + "default": "true", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_COMPRESSION_ENABLED" + }, + "DW_EXPOSE_PACKAGE_PROVENANCE": { + "description": "Include package_provenance in /api/cluster/info (admin-only). Off by default.", + "default": "false", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_EXPOSE_PACKAGE_PROVENANCE" + }, + "DW_PACKAGE_PROVENANCE_PATH": { + "description": "Absolute path to the provenance file written at Docker build time.", + "default": "/.package-provenance", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_PACKAGE_PROVENANCE_PATH" + }, + "DW_SERVICE_BOUNDARY_CROSS_NAMESPACE_DEFAULT": { + "description": "Default service-call boundary action for cross-namespace calls when no more-specific rule matches.", + "default": "allow", + "since": "2.1.0", + "legacy": "WORKFLOW_SERVER_SERVICE_BOUNDARY_CROSS_NAMESPACE_DEFAULT" + }, + "DW_SERVICE_BOUNDARY_RATE_LIMIT_PER_MINUTE": { + "description": "Optional per-minute service-call boundary rate limit. Unset means no boundary-level rate cap.", + "default": null, + "since": "2.1.0", + "legacy": "WORKFLOW_SERVER_SERVICE_BOUNDARY_RATE_LIMIT_PER_MINUTE" + }, + "DW_SERVICE_BOUNDARY_MAX_IN_FLIGHT": { + "description": "Optional service-call boundary concurrency limit. Unset means no boundary-level in-flight cap.", + "default": null, + "since": "2.1.0", + "legacy": "WORKFLOW_SERVER_SERVICE_BOUNDARY_MAX_IN_FLIGHT" + }, + "DW_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE": { + "description": "Optional shared per-minute service-call limit aggregated across each caller namespace.", + "default": null, + "since": "2.1.0", + "legacy": "WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_RATE_LIMIT_PER_MINUTE" + }, + "DW_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT": { + "description": "Optional shared in-flight service-call limit aggregated across each caller namespace.", + "default": null, + "since": "2.1.0", + "legacy": "WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_MAX_IN_FLIGHT" + }, + "DW_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE": { + "description": "Non-bypassable per-minute ceiling for service-call boundary and caller-namespace policies.", + "default": null, + "since": "2.1.0", + "legacy": "WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_RATE_LIMIT_PER_MINUTE" + }, + "DW_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT": { + "description": "Non-bypassable in-flight ceiling for service-call boundary and caller-namespace policies.", + "default": null, + "since": "2.1.0", + "legacy": "WORKFLOW_SERVER_SERVICE_BOUNDARY_HARD_MAX_IN_FLIGHT" + }, + "DW_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES": { + "description": "JSON object of caller-namespace service-call rate and in-flight overrides; hard ceilings still apply.", + "default": "{}", + "since": "2.1.0", + "legacy": "WORKFLOW_SERVER_SERVICE_BOUNDARY_NAMESPACE_OVERRIDES" + }, + "DW_ENV_AUDIT_STRICT": { + "description": "When \"1\", the Docker entrypoint fails container boot if the env:audit finds unknown or legacy DW_* vars.", + "default": "0", + "since": "2.0.0" + }, + "DW_BOOTSTRAP_RETRIES": { + "description": "Number of bootstrap attempts before the entrypoint gives up (migrations + seed).", + "default": "30", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_BOOTSTRAP_RETRIES" + }, + "DW_BOOTSTRAP_DELAY_SECONDS": { + "description": "Seconds between bootstrap attempts.", + "default": "2", + "since": "2.0.0", + "legacy": "WORKFLOW_SERVER_BOOTSTRAP_DELAY_SECONDS" + }, + "DW_V1_ENABLED": { + "description": "Enable legacy embedded v1 migration and queue-drain behavior. Standalone Server defaults to v2-only; enable only when deliberately preserving v1 state.", + "default": "false", + "since": "2.3.15", + "legacy": "WORKFLOW_V1_ENABLED" + }, + "DW_V2_NAMESPACE": { + "description": "Scopes workflow instances to a namespace. When unset, instances are visible to every consumer.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_V2_NAMESPACE" + }, + "DW_V2_TENANCY_ORGANIZATION": { + "description": "Optional organization segment for the workflow package tenancy hierarchy exposed to readiness, discovery, and operator surfaces.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_V2_TENANCY_ORGANIZATION" + }, + "DW_V2_TENANCY_PROJECT": { + "description": "Optional project segment for the workflow package tenancy hierarchy exposed to readiness, discovery, and operator surfaces.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_V2_TENANCY_PROJECT" + }, + "DW_V2_TENANCY_ENVIRONMENT": { + "description": "Optional environment segment for the workflow package tenancy hierarchy exposed to readiness, discovery, and operator surfaces.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_V2_TENANCY_ENVIRONMENT" + }, + "DW_V2_CURRENT_COMPATIBILITY": { + "description": "Worker-compatibility marker this worker advertises (e.g. \"build-2026-04-17\"). Null means no marker.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_V2_CURRENT_COMPATIBILITY" + }, + "DW_V2_SUPPORTED_COMPATIBILITIES": { + "description": "Comma-separated list of worker-compatibility markers this worker accepts, or \"*\" to accept any.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_V2_SUPPORTED_COMPATIBILITIES" + }, + "DW_V2_COMPATIBILITY_NAMESPACE": { + "description": "Compatibility namespace when multiple apps share one workflow database but maintain independent compatibility fleets.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_V2_COMPATIBILITY_NAMESPACE" + }, + "DW_V2_COMPATIBILITY_HEARTBEAT_TTL": { + "description": "Seconds a worker-compatibility heartbeat remains valid.", + "default": "30", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_COMPATIBILITY_HEARTBEAT_TTL" + }, + "DW_V2_PIN_TO_RECORDED_FINGERPRINT": { + "description": "Prefer an eligible worker matching the recorded definition. If none remains, current code must validate strict replay. False removes only this source preference, not build pins or replay checks.", + "default": "true", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_PIN_TO_RECORDED_FINGERPRINT" + }, + "DW_V2_CONTINUE_AS_NEW_EVENT_THRESHOLD": { + "description": "History event count at which the package signals the workflow author to continue-as-new.", + "default": "10000", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_CONTINUE_AS_NEW_EVENT_THRESHOLD" + }, + "DW_V2_CONTINUE_AS_NEW_SIZE_BYTES_THRESHOLD": { + "description": "Serialized-history size (bytes) at which the package signals continue-as-new.", + "default": "5242880", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_CONTINUE_AS_NEW_SIZE_BYTES_THRESHOLD" + }, + "DW_V2_HISTORY_EXPORT_SIGNING_KEY": { + "description": "Optional HMAC key for authenticating history export archives. Unset emits unsigned exports.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_V2_HISTORY_EXPORT_SIGNING_KEY" + }, + "DW_V2_HISTORY_EXPORT_SIGNING_KEY_ID": { + "description": "Optional key identifier recorded alongside signed history exports for rotation.", + "default": null, + "since": "2.0.0", + "legacy": "WORKFLOW_V2_HISTORY_EXPORT_SIGNING_KEY_ID" + }, + "DW_V2_UPDATE_WAIT_COMPLETION_TIMEOUT_SECONDS": { + "description": "Seconds the server waits for a workflow update to reach a terminal stage before returning.", + "default": "10", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_UPDATE_WAIT_COMPLETION_TIMEOUT_SECONDS" + }, + "DW_V2_UPDATE_WAIT_POLL_INTERVAL_MS": { + "description": "Milliseconds between update-stage polls while waiting for a workflow update.", + "default": "50", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_UPDATE_WAIT_POLL_INTERVAL_MS" + }, + "DW_V2_GUARDRAILS_BOOT": { + "description": "Boot-time structural guardrail mode: \"warn\", \"fail\", or \"silent\".", + "default": "warn", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_GUARDRAILS_BOOT" + }, + "DW_V2_LIMIT_PENDING_ACTIVITIES": { + "description": "Package-level pending-activity ceiling before a command batch is rejected.", + "default": "2000", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_LIMIT_PENDING_ACTIVITIES" + }, + "DW_V2_LIMIT_PENDING_CHILDREN": { + "description": "Package-level pending-child-workflow ceiling before a command batch is rejected.", + "default": "1000", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_LIMIT_PENDING_CHILDREN" + }, + "DW_V2_LIMIT_PENDING_TIMERS": { + "description": "Package-level pending-timer ceiling before a command batch is rejected.", + "default": "2000", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_LIMIT_PENDING_TIMERS" + }, + "DW_V2_LIMIT_PENDING_SIGNALS": { + "description": "Package-level pending-signal ceiling before a command batch is rejected.", + "default": "5000", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_LIMIT_PENDING_SIGNALS" + }, + "DW_V2_LIMIT_PENDING_UPDATES": { + "description": "Package-level pending-update ceiling before a command batch is rejected.", + "default": "500", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_LIMIT_PENDING_UPDATES" + }, + "DW_V2_LIMIT_COMMAND_BATCH_SIZE": { + "description": "Maximum commands accepted in a single workflow-task completion.", + "default": "1000", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_LIMIT_COMMAND_BATCH_SIZE" + }, + "DW_V2_LIMIT_PAYLOAD_SIZE_BYTES": { + "description": "Package-level single-payload byte ceiling.", + "default": "2097152", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_LIMIT_PAYLOAD_SIZE_BYTES" + }, + "DW_V2_LIMIT_MEMO_SIZE_BYTES": { + "description": "Package-level workflow-memo byte ceiling.", + "default": "262144", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_LIMIT_MEMO_SIZE_BYTES" + }, + "DW_V2_LIMIT_SEARCH_ATTRIBUTE_SIZE_BYTES": { + "description": "Package-level search-attribute byte ceiling.", + "default": "40960", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_LIMIT_SEARCH_ATTRIBUTE_SIZE_BYTES" + }, + "DW_V2_LIMIT_HISTORY_TRANSACTION_SIZE": { + "description": "Package-level history-transaction event ceiling.", + "default": "5000", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_LIMIT_HISTORY_TRANSACTION_SIZE" + }, + "DW_V2_LIMIT_WARNING_THRESHOLD_PERCENT": { + "description": "Percent of a structural limit at which the package emits an approaching-limit warning.", + "default": "80", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_LIMIT_WARNING_THRESHOLD_PERCENT" + }, + "DW_V2_TASK_DISPATCH_MODE": { + "description": "Package-level workflow-task dispatch mode (\"queue\" or \"poll\"). Usually overridden by the server via DW_TASK_DISPATCH_MODE; included here for operators who bypass server.php.", + "default": "queue", + "since": "2.0.0" + }, + "DW_V2_MATCHING_ROLE_QUEUE_WAKE": { + "description": "Whether queue workers run the in-worker matching-role wake on every Looping event (default true). Set to false to opt execution-only nodes out of the broad-poll wake when a dedicated `php artisan workflow:v2:repair-pass --loop` daemon owns the sweep instead.", + "default": "true", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_MATCHING_ROLE_QUEUE_WAKE" + }, + "DW_V2_TASK_REPAIR_REDISPATCH_AFTER_SECONDS": { + "description": "Seconds before an orphaned workflow task is redispatched by the repair loop.", + "default": "3", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_TASK_REPAIR_REDISPATCH_AFTER_SECONDS" + }, + "DW_V2_TASK_REPAIR_LOOP_THROTTLE_SECONDS": { + "description": "Minimum seconds between successive task-repair passes per queue.", + "default": "5", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_TASK_REPAIR_LOOP_THROTTLE_SECONDS" + }, + "DW_V2_TASK_REPAIR_SCAN_LIMIT": { + "description": "Maximum tasks considered per task-repair pass.", + "default": "25", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_TASK_REPAIR_SCAN_LIMIT" + }, + "DW_V2_TASK_REPAIR_FAILURE_BACKOFF_MAX_SECONDS": { + "description": "Ceiling on task-repair failure backoff in seconds.", + "default": "60", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_TASK_REPAIR_FAILURE_BACKOFF_MAX_SECONDS" + }, + "DW_V2_MULTI_NODE": { + "description": "Declare the deployment has multiple server nodes so cache backends are validated for cross-node coordination.", + "default": "false", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_MULTI_NODE" + }, + "DW_V2_VALIDATE_CACHE_BACKEND": { + "description": "Whether to validate the long-poll cache backend at boot.", + "default": "true", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_VALIDATE_CACHE_BACKEND" + }, + "DW_V2_CACHE_VALIDATION_MODE": { + "description": "How to handle cache-backend validation failures: \"fail\", \"warn\", or \"silent\".", + "default": "warn", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_CACHE_VALIDATION_MODE" + }, + "DW_V2_FLEET_VALIDATION_MODE": { + "description": "How to handle fleet-compatibility validation failures for worker compatibility checks and task dispatch: \"warn\" logs, \"fail\" blocks dispatch and fails closed when no compatible worker is available.", + "default": "warn", + "since": "2.0.0", + "legacy": "WORKFLOW_V2_FLEET_VALIDATION_MODE" + }, + "DW_SERIALIZER": { + "description": "Payload codec diagnostic input. Final v2 always resolves new-run payloads to \"avro\"; legacy values are surfaced by workflow:v2:doctor.", + "default": "avro", + "since": "2.0.0", + "legacy": "WORKFLOW_SERIALIZER" + } + } +}