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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/server-parity.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ on:
- tests/Unit/ServerParityWorkerReplacementContractTest.mjs
- tests/Unit/ServerParityOperatorMetricsContractTest.mjs
- tests/Unit/ServerParityActivityLeaseRenewalContractTest.mjs
- tests/Unit/ServerParityNexusOperationsContractTest.mjs
- tests/Unit/ServerParityRecordLocalActivityContractTest.mjs
- tests/Unit/ServerParityWorkflowPollRequestContractTest.mjs
- tests/Unit/ServerParityActivityCancellationAckContractTest.mjs
Expand Down Expand Up @@ -1804,7 +1805,7 @@ jobs:
bash scripts/ci/run-composer.sh --rm -v "$PWD:/source" -w /source -- \
install --working-dir=scripts/conformance/server-parity --no-interaction --no-progress
docker run --rm --user=1000:1000 --entrypoint node -v "$PWD:/source:ro" -w /source \
"$image" --test tests/Unit/ServerParityRunnerTest.mjs tests/Unit/ServerParitySdkDirectionLanesTest.mjs tests/Unit/ServerParityCodecDeadlineCellsTest.mjs tests/Unit/ServerParityCooperativeContractTest.mjs tests/Unit/ServerParityChildCancellationContractTest.mjs tests/Unit/ServerParityScheduleContractTest.mjs tests/Unit/ServerParityVisibilityContractTest.mjs tests/Unit/ServerParityAdmissionContractTest.mjs tests/Unit/ServerParityRoleTokenContractTest.mjs tests/Unit/ServerParityWorkerDeregistrationContractTest.mjs tests/Unit/ServerParitySearchAttributeContractTest.mjs tests/Unit/ServerParityWorkerListingContractTest.mjs tests/Unit/ServerParityWorkerReplacementContractTest.mjs tests/Unit/ServerParityPatchDeploymentContractTest.mjs tests/Unit/ServerParityWaitingHistoryContractTest.mjs tests/Unit/ServerParityTaskRetryContractTest.mjs tests/Unit/ServerParityPublishedPatchContractTest.mjs tests/Unit/ServerParityPublishedPatchTransportTest.mjs tests/Unit/ServerParityRecordFileTest.mjs tests/Unit/ServerParityFailureLocationTest.mjs tests/Unit/ServerParityFailureExcerptTest.mjs tests/Unit/ServerParityLateWorkflowCompletionContractTest.mjs tests/Unit/ServerParityStorageTestContractTest.mjs tests/Unit/ServerParitySchedulePoliciesContractTest.mjs tests/Unit/ServerParitySignalsBeforeWorkerContractTest.mjs tests/Unit/ServerParityScheduleCatalogContractTest.mjs tests/Unit/ServerParityOperatorMetricsContractTest.mjs tests/Unit/ServerParityActivityLeaseRenewalContractTest.mjs tests/Unit/ServerParityRecordLocalActivityContractTest.mjs tests/Unit/ServerParityActivityCancellationAckContractTest.mjs tests/Unit/ServerParityServiceCatalogContractTest.mjs tests/Unit/ServerParityWorkflowImportContractTest.mjs tests/Unit/ServerParityWaterlineImportContractTest.mjs tests/Unit/ServerParitySystemMetricsContractTest.mjs tests/Unit/ServerParityOperatorDashboardTypesContractTest.mjs tests/Unit/ServerParityPrometheusMetricsContractTest.mjs tests/Unit/ServerParityPayloadCleanupContractTest.mjs tests/Unit/ServerParityRepairPassContractTest.mjs tests/Unit/ServerParityClusterInfoContractTest.mjs tests/Unit/ServerParityNamespaceDeleteContractTest.mjs tests/Unit/ServerParityMessageStreamsContractTest.mjs tests/Unit/ServerParityCancellationScopesContractTest.mjs tests/Unit/ServerParityWorkflowPollRequestContractTest.mjs tests/Unit/ServerParityUpdateValidationContractTest.mjs tests/Unit/ServerParityFixtureSelectionTest.mjs tests/Unit/ServerParityUpdateValidationRetryTest.mjs tests/Unit/ServerParityKilledAuthorPollTest.mjs tests/Unit/ServerParityImagePullTest.mjs tests/Unit/ServerParityWorkerSessionsContractTest.mjs tests/Unit/ServerParityWorkerSessionActivitiesContractTest.mjs > parity-evidence/comparator-tests.txt
"$image" --test tests/Unit/ServerParityRunnerTest.mjs tests/Unit/ServerParitySdkDirectionLanesTest.mjs tests/Unit/ServerParityCodecDeadlineCellsTest.mjs tests/Unit/ServerParityCooperativeContractTest.mjs tests/Unit/ServerParityChildCancellationContractTest.mjs tests/Unit/ServerParityScheduleContractTest.mjs tests/Unit/ServerParityVisibilityContractTest.mjs tests/Unit/ServerParityAdmissionContractTest.mjs tests/Unit/ServerParityRoleTokenContractTest.mjs tests/Unit/ServerParityWorkerDeregistrationContractTest.mjs tests/Unit/ServerParitySearchAttributeContractTest.mjs tests/Unit/ServerParityWorkerListingContractTest.mjs tests/Unit/ServerParityWorkerReplacementContractTest.mjs tests/Unit/ServerParityPatchDeploymentContractTest.mjs tests/Unit/ServerParityWaitingHistoryContractTest.mjs tests/Unit/ServerParityTaskRetryContractTest.mjs tests/Unit/ServerParityPublishedPatchContractTest.mjs tests/Unit/ServerParityPublishedPatchTransportTest.mjs tests/Unit/ServerParityRecordFileTest.mjs tests/Unit/ServerParityFailureLocationTest.mjs tests/Unit/ServerParityFailureExcerptTest.mjs tests/Unit/ServerParityLateWorkflowCompletionContractTest.mjs tests/Unit/ServerParityStorageTestContractTest.mjs tests/Unit/ServerParitySchedulePoliciesContractTest.mjs tests/Unit/ServerParitySignalsBeforeWorkerContractTest.mjs tests/Unit/ServerParityScheduleCatalogContractTest.mjs tests/Unit/ServerParityOperatorMetricsContractTest.mjs tests/Unit/ServerParityActivityLeaseRenewalContractTest.mjs tests/Unit/ServerParityRecordLocalActivityContractTest.mjs tests/Unit/ServerParityActivityCancellationAckContractTest.mjs tests/Unit/ServerParityServiceCatalogContractTest.mjs tests/Unit/ServerParityWorkflowImportContractTest.mjs tests/Unit/ServerParityWaterlineImportContractTest.mjs tests/Unit/ServerParitySystemMetricsContractTest.mjs tests/Unit/ServerParityOperatorDashboardTypesContractTest.mjs tests/Unit/ServerParityPrometheusMetricsContractTest.mjs tests/Unit/ServerParityPayloadCleanupContractTest.mjs tests/Unit/ServerParityRepairPassContractTest.mjs tests/Unit/ServerParityClusterInfoContractTest.mjs tests/Unit/ServerParityNamespaceDeleteContractTest.mjs tests/Unit/ServerParityMessageStreamsContractTest.mjs tests/Unit/ServerParityCancellationScopesContractTest.mjs tests/Unit/ServerParityWorkflowPollRequestContractTest.mjs tests/Unit/ServerParityUpdateValidationContractTest.mjs tests/Unit/ServerParityFixtureSelectionTest.mjs tests/Unit/ServerParityUpdateValidationRetryTest.mjs tests/Unit/ServerParityKilledAuthorPollTest.mjs tests/Unit/ServerParityImagePullTest.mjs tests/Unit/ServerParityWorkerSessionsContractTest.mjs tests/Unit/ServerParityWorkerSessionActivitiesContractTest.mjs tests/Unit/ServerParityNexusOperationsContractTest.mjs > parity-evidence/comparator-tests.txt
docker run --rm --user=1000:1000 --cpus=1 --memory=256m --memory-swap=256m \
--network=none --entrypoint node -v "$PWD:/source:ro" -w /source \
"$image" --test tests/Unit/ServerParityCodecDeadlineLoadTest.mjs > parity-evidence/codec-load-tests.txt
Expand Down
12 changes: 8 additions & 4 deletions docs/rust-server-port.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,12 @@ Updated October 24, 2026.
([#737](https://github.com/durable-workflow/server/issues/737)).

No expectation is edited to make native pass.
- **Parity surface.** Native serves 143 of the 175 API route methods in
- **Parity surface.** Native serves 145 of the 175 API route methods in
published 2.11.1's route table, with message streams, update validation,
activity cancellation acknowledgement, worker sessions, workflow-task
cancellation scopes, and embedded v2 and Waterline v1 workflow import. An
execution test sends each one through the native router, and the ones
cancellation scopes, caller-indexed Nexus operation reads, and embedded v2
and Waterline v1 workflow import. An execution test sends each one through
the native router, and the ones
still answering `501 rust_capability_not_implemented` must match
[`unserved-php-routes.v2.11.1.txt`](../rust/tests/fixtures/unserved-php-routes.v2.11.1.txt).
Unlike published PHP, native's embedded v2 import refuses a bundle whose
Expand Down Expand Up @@ -163,8 +164,11 @@ any other unknown path or method answers PHP's own 404 or 405
- Service endpoints. (The service catalog reads from Server 2.11 are served:
native never holds catalog rows, so every list is PHP's empty page and every
identity its not-found answer; the `service-catalog` fixture checks 37 cases.)
- Nexus operations.
- Bridge adapters.
- (Caller-indexed Nexus operation reads are served, with the
`nexus-operations` fixture. Native writes no service calls and takeover
refuses a source that holds any, so every list is PHP's empty answer; an
execution test seeds rows for the row shape and newest-first order.)

## Known gaps found in review

Expand Down
1 change: 1 addition & 0 deletions rust/src/runtime/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1607,6 +1607,7 @@ impl Runtime {
delegate!(heartbeat_activity(task_id: &str, body: Value, protocol: &str) -> Result<Value>);
delegate!(activity_status(task_id: &str, body: Value, protocol: &str) -> Result<Value>);
delegate!(renew_activity_lease(task_id: &str, body: Value) -> Result<Value>);
delegate!(nexus_operations(workflow_id: &str, run_id: Option<&str>, limit: i64) -> Result<Vec<Value>>);
delegate!(import_existing_run(run_id: &str) -> Result<Option<super::workflow_import::ExistingRun>>);
delegate!(import_write(plan: &super::workflow_import::Plan) -> std::result::Result<super::workflow_import::Rows, String>);
delegate!(waterline_existing(workflow_id: &str, run_id: &str) -> Result<super::waterline_import::Existing>);
Expand Down
35 changes: 34 additions & 1 deletion rust/src/runtime/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ pub fn router(runtime: Runtime) -> Router {
get(super::run_observation::selected),
)
.route("/api/workflows/{workflow_id}/runs", get(list_runs))
.route("/api/workflows/{workflow_id}/nexus-operations", get(nexus_operations_current))
.route("/api/workflows/{workflow_id}/runs/{run_id}/nexus-operations", get(nexus_operations_run))
.route("/api/workflows/{workflow_id}/cancel", post(cancel_current))
.route(
"/api/workflows/{workflow_id}/terminate",
Expand Down Expand Up @@ -775,7 +777,9 @@ fn workflow_route(rest: &str) -> Option<Allowed> {
| [_, "runs", _, "history", "export"]
| [_, "runs", _, "streams"]
| [_, "runs", _, "streams", _]
| [_, "runs", _, "streams", _, "items"] => Some(READ),
| [_, "runs", _, "streams", _, "items"]
| [_, "nexus-operations"]
| [_, "runs", _, "nexus-operations"] => Some(READ),
[_, "signal" | "query" | "update", _]
| [_, "runs", _, "signal" | "query" | "update", _]
| [_, "repair" | "request-cancellation"]
Expand Down Expand Up @@ -1191,6 +1195,35 @@ async fn describe_current(
))
}

/// `GET /api/workflows/{workflow_id}/nexus-operations`.
async fn nexus_operations_current(
Extension(runtime): Extension<Runtime>,
Path(workflow_id): Path<String>,
Query(query): Query<std::collections::HashMap<String, String>>,
) -> Result<Json<Value>> {
nexus_operations(runtime, &workflow_id, None, query).await
}

/// `GET /api/workflows/{workflow_id}/runs/{run_id}/nexus-operations`.
async fn nexus_operations_run(
Extension(runtime): Extension<Runtime>,
Path((workflow_id, run_id)): Path<(String, String)>,
Query(query): Query<std::collections::HashMap<String, String>>,
) -> Result<Json<Value>> {
nexus_operations(runtime, &workflow_id, Some(&run_id), query).await
}

async fn nexus_operations(
runtime: Runtime,
workflow_id: &str,
run_id: Option<&str>,
query: std::collections::HashMap<String, String>,
) -> Result<Json<Value>> {
let limit = super::nexus_operations::list_limit(query.get("limit").map(String::as_str));
let calls = runtime.nexus_operations(workflow_id, run_id, limit).await?;
Ok(Json(super::nexus_operations::listing(workflow_id, run_id, runtime.namespace(), limit, calls)))
}

async fn list_runs(
Extension(runtime): Extension<Runtime>,
Path(workflow): Path<String>,
Expand Down
2 changes: 1 addition & 1 deletion rust/src/runtime/laravel_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ fn php_string(value: &Value) -> Option<String> {
}

/// PHP 8's `is_numeric` for a request value.
fn php_numeric(value: &Value) -> Option<f64> {
pub(super) fn php_numeric(value: &Value) -> Option<f64> {
match value {
Value::Number(number) => number.as_f64(),
Value::String(text) => {
Expand Down
1 change: 1 addition & 0 deletions rust/src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ mod memos;
pub mod mysql;
mod namespace_cleanup;
mod namespaces;
mod nexus_operations;
mod operator_dashboard;
mod operator_metrics;
mod payload_cleanup;
Expand Down
Loading
Loading