Skip to content

Commit 44fd778

Browse files
authored
Rust Server train: system metrics, Prometheus, payload cleanup, repair pass, leases, limits, standalone activities, deployments, routing (#675)
Rust Server train: definition routing, worker admission, poll waits, schedule probe
2 parents 5f186d4 + fb01821 commit 44fd778

72 files changed

Lines changed: 4772 additions & 234 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/server-parity.yml‎

Lines changed: 79 additions & 27 deletions
Large diffs are not rendered by default.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# October 22, workflow definition routing
2+
3+
- **Gap.** Native records the definition fingerprint a start's worker cohort
4+
agrees on, with `workflow_definition_fingerprint_source: worker`, as PHP
5+
does. It then offered that run's workflow tasks to any worker, so a worker
6+
with another definition could take a pinned run while the recorded one was
7+
live.
8+
- **Source.** Server 2.10.0's `WorkflowDefinitionRouting::forWorker`,
9+
which `WorkflowTaskPoller::matchesRecordedWorkflowDefinition` applies at
10+
claim, and `WorkflowReplayEligibility`.
11+
- **Decision.** For a workflow task of a worker-pinned run:
12+
- a worker advertising the recorded fingerprint for the type takes it
13+
(`matching_definition`);
14+
- without a recorded fingerprint (`recorded_definition_missing`), or
15+
without one from the worker (`worker_definition_missing`), nobody
16+
does;
17+
- a worker with another definition waits while an eligible peer
18+
advertises the recorded one (`matching_definition_preferred`);
19+
- otherwise it takes the task only if it advertises
20+
`workflow_entry_arguments_validation` (`replay_required`, else
21+
`entry_validation_unavailable`).
22+
23+
An unpinned run goes to any worker (`not_worker_pinned`). Native
24+
refuses to start with `DW_V2_PIN_TO_RECORDED_FINGERPRINT` off, so
25+
pinning is always on.
26+
- **Eligible peers** (`eligibleWorkers`). Active registrations on the
27+
run's namespace and queue that:
28+
- match the build the task or run requires;
29+
- support the type, with workflow capacity above zero;
30+
- replay the run (`WorkflowReplayEligibility::allows`). That means a
31+
heartbeat inside the stale window and cooperative-cancellation support
32+
when the run has a request, at the protocol version the worker last
33+
reported. It also means the memo and typed search attribute
34+
capabilities its history needs.
35+
- **Protocol version.** Each registration and heartbeat records its
36+
protocol version under `_worker_protocol_version` in the worker's process
37+
metrics, after the metrics it reported. A heartbeat without metrics
38+
keeps the stored ones. Worker listings therefore show the key, as PHP
39+
2.10.0's do; 2.5.14 had no such key.
40+
- **Reports** (`inspect` and `forQueue`).
41+
- Describe, repair and debug report `definition_routing` for the run's
42+
next due ready task:
43+
- the context (`pinning_enabled`, `worker_pinned`,
44+
`recorded_fingerprint`, type, queue and required build);
45+
- PHP's status, the counts of eligible workers by definition, up to ten
46+
example workers, `blocked` and `runnable_task`;
47+
- PHP's resolution text.
48+
- A blocked route adds debug's `workflow_definition_routing_blocked`
49+
warning and `diagnostic_status: needs_attention`.
50+
- Task queue describe samples up to ten runs with a due ready task. A
51+
blocked sample sets `repair.needs_attention`.
52+
- **Tests** (`definition_routing.rs`).
53+
- A pinned run goes to the worker with its recorded definition. Workers
54+
with another definition, or without one, wait even when they validate
55+
entry arguments.
56+
- Once the recorded definition leaves, only an entry-validating worker
57+
takes the run.
58+
- An unpinned run goes to any worker.
59+
- Registrations and heartbeats record the protocol version with the
60+
reported metrics.
61+
- Describe, debug, task queue and repair report a blocked route, then the
62+
route an entry-validating replacement unblocks.
63+
- The worker listing test now expects the protocol key.
64+
- Full SQLite suite: 398 passed. Routing, worker, poll, child, cooperative,
65+
debug, task queue, repair and describe tests: PostgreSQL 134, MySQL 134.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# October 22, worker poll waits and operation names
2+
3+
- **Gap.** A workflow or activity poll without `timeout_seconds` waited 5
4+
seconds; PHP waits `DW_WORKER_POLL_TIMEOUT` seconds, 30 by default. A
5+
query-task poll without one also waited 5 seconds where PHP starts from
6+
the same setting. Native refused an explicit `null` wait, which PHP's
7+
`nullable` rule accepts.
8+
- **Source.** Server 2.10.0's `LongPoller::until`,
9+
`WorkflowQueryTaskBroker::queryPollTimeoutSeconds` and
10+
`WorkflowController::validateOperationName`.
11+
- **Poll waits.**
12+
- A workflow or activity poll without a wait, or with `null`, waits
13+
`max(0, DW_WORKER_POLL_TIMEOUT)` seconds. The setting is not capped.
14+
- A query-task poll waits the requested time or that setting, capped by
15+
`DW_QUERY_TASK_POLL_TIMEOUT` (default 5); zero answers at once.
16+
- A requested wait passes Laravel's `integer` rule (so `"5"` is five
17+
seconds) and must lie from 0 to 60.
18+
- **Operation names.**
19+
- Signal, update and query requests check the name first, after the
20+
payload transport check, as PHP's controller does. Empty names, names
21+
over 256 bytes and names with ASCII control characters get PHP's
22+
`validation_failed` errors and messages.
23+
- PHP's signal and update name columns hold 255 bytes. Native keeps its
24+
storage guard and refuses a 256-byte or all-space name with
25+
`invalid_signal_name` or `invalid_update_name`. Query names are not
26+
stored in those columns, so a 256-byte query name is accepted.
27+
- **Fixed along the way.** A query poll from a worker registered without
28+
`capabilities` answered 503 `storage_unavailable`, because the claim read
29+
the missing list as required. It now polls empty, as PHP's `stringArray`
30+
does.
31+
- **Tests** (`poll_waits.rs`).
32+
- Workflow, activity and query polls without a wait, or with `null`, take
33+
the configured second.
34+
- A zero setting and a requested `"0"` answer at once.
35+
- Requested waits of 61, -1, `"soon"` and 1.5 are refused.
36+
- A task started during a default wait is claimed.
37+
- A 255-byte signal name is accepted; 256-byte signal and update names
38+
are refused with the storage reasons. Too-long names and names with
39+
control characters get PHP's messages for each kind.
40+
- Full SQLite run (all targets): 228 unit, 397 execution and 2 upgrade
41+
tests passed. Poll, signal, update and query tests: PostgreSQL 122,
42+
MySQL 122.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# October 22, worker registration admission
2+
3+
- **Gap.** Native accepted a registration without the `capability_manifest`
4+
PHP requires from protocol 1.18. It also skipped most of PHP's request
5+
rules and capability guards, refused a missing `worker_id` or type list,
6+
and answered metadata-capability mismatches in its own shape.
7+
- **Source.** Server 2.10.0 `WorkerController::register`:
8+
- its Laravel rules;
9+
- the prepared-local-activity, Nexus and cooperative-cancellation guards;
10+
- `guardPortableWorkerCapabilityManifest`;
11+
- `WorkflowMetadataCapabilityPolicy::firstProtocolMismatch`;
12+
- the message-streams floor;
13+
- `portableWorkerCapabilityManifest`.
14+
- **Request rules.** Laravel trims strings and turns empty ones into null
15+
first; native now does the same for the whole body.
16+
- Every field follows PHP's rules: `runtime` from PHP's list, sizes,
17+
capacities, task slots, process metrics, heartbeat interval.
18+
- `capability_manifest` is required from protocol 1.18 and must hold the
19+
`local_activities`, `worker_sessions` and `sticky_execution` entries.
20+
Each entry needs `supported` (boolean) and `minimum_protocol_version`.
21+
- Failures answer Laravel's 422 `validation_failed` with its messages. The
22+
rule engine gained `numeric` and `required_array_keys`. A `*.field` rule
23+
now covers only array items, as Laravel's expansion does.
24+
- **Guards.** Each answers 409 with `registered: false` and PHP's fields, in
25+
PHP's order:
26+
- `prepared_local_activity_cancellation_policy_capability_mismatch`,
27+
`prepared_local_activity_group_capability_mismatch` and
28+
`prepared_local_activity_capability_mismatch`;
29+
- `nexus_cooperative_cancellation_capability_mismatch` and
30+
`cooperative_cancellation_protocol_mismatch`, below protocol 1.20;
31+
- `worker_capability_manifest_mismatch`, when a flat affinity capability
32+
and its `supported` flag disagree;
33+
- `worker_capability_protocol_floor_mismatch`, when an entry's floor is
34+
below 1.18 or above the request's protocol;
35+
- `workflow_metadata_capability_protocol_mismatch`, for `memo_upserts`
36+
below 1.14 and `typed_search_attributes` below 1.16. This now uses PHP's
37+
`capability`, `requested_version` and `remediation` fields, not native's
38+
former `worker_capability` and `recorded`;
39+
- `message_streams_unavailable`, below 1.15.
40+
- **Accepted registrations.**
41+
- A missing `worker_id` gets a ULID, as PHP does.
42+
- Missing type lists are stored empty.
43+
- Capabilities keep their non-empty strings.
44+
- The manifest is stored normalized: the three entries, a trimmed floor,
45+
and non-empty `implementation` and `reason`.
46+
- **Worker protocol bodies.** Registration refusals now carry
47+
`protocol_version` and `server_capabilities`, as `WorkerProtocol::json`
48+
does. Other worker-plane refusals still lack them (#46's shape sweep).
49+
- **Tests.**
50+
- `worker_admission.rs` uses the server's own router. It covers the
51+
manifest requirement and its errors, field rules with Laravel's
52+
messages, the generated id, the stored manifest, and every guard.
53+
- The other tests' router adds the manifest an SDK sends from 1.18,
54+
matching each registration's flat capabilities.
55+
- Two cooperative tests registered `cooperative_cancellation` at protocol
56+
1.19, which PHP refuses. They now register at 1.20 and still poll at the
57+
protocol each case tests.
58+
- Full SQLite run (all targets): 230 unit, 401 execution and 2 upgrade
59+
tests passed. Worker, registration, admission, cooperative and
60+
namespace tests: PostgreSQL 124, MySQL 124.

0 commit comments

Comments
 (0)