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
4 changes: 3 additions & 1 deletion .github/workflows/server-parity.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ on:
- 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/ServerParityWaitingHistoryContractTest.mjs
Expand Down Expand Up @@ -63,6 +64,7 @@ on:
- 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/ServerParityWaitingHistoryContractTest.mjs
Expand Down Expand Up @@ -1424,7 +1426,7 @@ jobs:
-e COMPOSER_HOME=/tmp/composer -v "$PWD:/source" -w /source "$image" \
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/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/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 > parity-evidence/comparator-tests.txt
"$image" --test tests/Unit/ServerParityRunnerTest.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 > 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
23 changes: 23 additions & 0 deletions docs/rust-server-port.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,29 @@ support is not evidence of multi-node safety.
Newest checkpoints first. Each entry is exact to the source, tree and runs it
names, including unsuccessful observations.

October 20, search attribute registry:

- **Source.** Native serves `GET` and `POST /api/search-attributes` and
`DELETE /api/search-attributes/{name}` for operators, in the default or a
named namespace, as PHP's `SearchAttributeController` does. Its rules are:
- request strings are trimmed;
- Laravel's validation messages and error counts;
- system names and their aliases are reserved;
- a duplicate keeps its type;
- `DW_MAX_SEARCH_ATTRIBUTES` (legacy `WORKFLOW_MAX_SEARCH_ATTRIBUTES`,
default 100) limits definitions per namespace;
- system attributes cannot be removed.
- **Concurrent registrations.** When two registrations of one name race, the
unique key decides the winner. PHP surfaces that as a server error; native
refuses the loser as a duplicate.
- **Not covered.** Native start and upsert still refuse search attribute
values, so a definition is registry state only. PHP's enforcement of
definitions on start, upsert and visibility filters needs its own fixtures.
- **Fixture.** `search-attributes` drives two fresh namespaces through the
published SDK and raw requests. Published PHP 2.5.14, embedded PHP (which
declares it inapplicable) and native passed the contract in a local copy of
the SQLite parity step, and the comparison passed.

October 20, worker listing:

- **Source.** Native serves `GET /api/workers` and `GET /api/workers/{id}`,
Expand Down
9 changes: 9 additions & 0 deletions rust/src/runtime/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,10 @@ impl Runtime {
let queries = super::QueryTaskConfig::from_env()?;
let limit = super::memo_limits::configured_limit()?;
let history_budget = super::history_budget::Config::from_env()?;
let search_attribute_limit = super::search_attributes::configured_limit()?;
let mut store = Store::new(sqlite::open(database).await?);
store.memo_size_limit = limit;
store.search_attribute_limit = search_attribute_limit;
store.history_budget = history_budget;
Self::from_storage(Storage::Sqlite(store), token, external, queries).await
}
Expand All @@ -172,8 +174,10 @@ impl Runtime {
let queries = super::QueryTaskConfig::from_env()?;
let limit = super::memo_limits::configured_limit()?;
let history_budget = super::history_budget::Config::from_env()?;
let search_attribute_limit = super::search_attributes::configured_limit()?;
let mut store = Store::new(PostgresStorage::open(options).await?.into_pool());
store.memo_size_limit = limit;
store.search_attribute_limit = search_attribute_limit;
store.history_budget = history_budget;
Self::from_storage(Storage::Postgres(store), token, external, queries).await
}
Expand All @@ -184,8 +188,10 @@ impl Runtime {
let queries = super::QueryTaskConfig::from_env()?;
let limit = super::memo_limits::configured_limit()?;
let history_budget = super::history_budget::Config::from_env()?;
let search_attribute_limit = super::search_attributes::configured_limit()?;
let mut store = Store::new(MySqlStorage::open(options).await?.into_pool());
store.memo_size_limit = limit;
store.search_attribute_limit = search_attribute_limit;
store.history_budget = history_budget;
Self::from_storage(Storage::MySql(store), token, external, queries).await
}
Expand Down Expand Up @@ -288,6 +294,9 @@ impl Runtime {
delegate!(list_namespaces() -> Result<Value>);
delegate!(describe_namespace(name: &str) -> Result<Value>);
delegate!(create_namespace(body: Value) -> Result<Value>);
delegate!(list_search_attributes() -> Result<Value>);
delegate!(create_search_attribute(body: Value) -> Result<Value>);
delegate!(delete_search_attribute(name: &str) -> Result<Value>);
delegate!(set_external_policy(name: &str, body: Value) -> Result<Value>);
delegate!(update_namespace(name: &str, body: Value) -> Result<Value>);
delegate!(
Expand Down
37 changes: 37 additions & 0 deletions rust/src/runtime/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ pub fn router(runtime: Runtime) -> Router {
"/api/external-payloads/v1/{reference_id}",
get(super::external_transport::fetch),
)
.route(
"/api/search-attributes",
get(list_search_attributes).post(create_search_attribute),
)
.route(
"/api/search-attributes/{name}",
delete(delete_search_attribute),
)
.route("/api/workflows", get(list_workflows).post(start))
.route("/api/schedules", post(super::schedule_http::create))
.route(
Expand Down Expand Up @@ -419,6 +427,16 @@ fn named_namespace_operation(method: &str, path: &str) -> bool {
if path == "/api/workflows" {
return method == "POST";
}
// The registry is namespace-scoped state with no default-namespace selector.
if path == "/api/search-attributes" {
return matches!(method, "GET" | "POST");
}
if path
.strip_prefix("/api/search-attributes/")
.is_some_and(|name| !name.is_empty() && !name.contains('/'))
{
return method == "DELETE";
}
if path == "/api/workers"
|| path
.strip_prefix("/api/workers/")
Expand Down Expand Up @@ -508,6 +526,25 @@ async fn create_namespace(
))
}

async fn list_search_attributes(Extension(runtime): Extension<Runtime>) -> Result<Json<Value>> {
Ok(Json(runtime.list_search_attributes().await?))
}
async fn create_search_attribute(
Extension(runtime): Extension<Runtime>,
Json(body): Json<Value>,
) -> Result<(StatusCode, Json<Value>)> {
Ok((
StatusCode::CREATED,
Json(runtime.create_search_attribute(body).await?),
))
}
async fn delete_search_attribute(
Extension(runtime): Extension<Runtime>,
Path(name): Path<String>,
) -> Result<Json<Value>> {
Ok(Json(runtime.delete_search_attribute(&name).await?))
}

async fn admission_error(
request: Request,
worker: bool,
Expand Down
2 changes: 1 addition & 1 deletion rust/src/runtime/memo_limits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ static NUMERIC_PREFIX: LazyLock<Regex> = LazyLock::new(|| {
.expect("static PHP numeric prefix")
});

fn typed_null(value: &str) -> bool {
pub(super) fn typed_null(value: &str) -> bool {
matches!(value.to_ascii_lowercase().as_str(), "null" | "(null)")
}

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 @@ -46,6 +46,7 @@ mod schedule_execution;
mod schedule_http;
mod schedule_storage;
mod schedules;
mod search_attributes;
mod schema;
mod selection_summary;
mod selections;
Expand Down
Loading
Loading