Skip to content

Serve the search attribute registry natively, as published PHP does - #550

Merged
rmcdaniel merged 4 commits into
mainfrom
rust-325-search-attributes
Oct 21, 2026
Merged

rmcdaniel merged 4 commits into
mainfrom
rust-325-search-attributes

Conversation

@rmcdaniel

Copy link
Copy Markdown
Member

Part of #325: the search attribute registry, one of the API families the CLI uses that native lacked.

What changes

Native serves the published registry routes, for operators, in the default namespace or a named one:

  • GET /api/search-attributes
  • POST /api/search-attributes
  • DELETE /api/search-attributes/{name}

They behave as PHP's SearchAttributeController does:

  • Listing. The eleven system attributes, plus the namespace's custom definitions by name. An empty custom map renders as [], as PHP renders it.
  • Registration. Request strings are trimmed (Laravel's TrimStrings). Laravel's validation then applies, with its published messages and error counts. Further refusals:
    • Reserved names. System names and their snake_case aliases, in any case: 409 name_reserved.
    • Duplicates. 409 attribute_already_exists, keeping the original type.
    • Limit. DW_MAX_SEARCH_ATTRIBUTES (legacy WORKFLOW_MAX_SEARCH_ATTRIBUTES, default 100) per namespace: 422 search_attribute_limit_reached.
  • Removal. 409 system_attribute for a system attribute, 404 attribute_not_found for an absent one.

When two registrations of one name race, the unique key decides the winner, and native refuses the loser as a duplicate. PHP surfaces that race as a server error.

Not covered

Native start and upsert still refuse search attribute values, so a definition is registry state only. PHP's enforcement of registered types on start, upsert and visibility filters needs its own fixtures.

Evidence

  • New fixture. search-attributes drives two fresh namespaces through the published SDK 2.2.6 and raw requests. It covers the empty and filled listings, trimming, namespace isolation, the duplicate, three reserved names, six invalid bodies, both removal refusals and the 100-definition limit. The contract checks PHP's exact bodies.
  • Local parity. In a local copy of the SQLite parity step, published PHP 2.5.14, embedded PHP (inapplicable, declared) and native all passed, and the comparison passed.
  • Native tests. Three integration tests cover the registry rules, the per-namespace limit and the operator role; a lib test covers Laravel's validation messages. They passed on SQLite (full execution suite: 285), PostgreSQL and MySQL.
  • Contract unit tests. tests/Unit/ServerParitySearchAttributeContractTest.mjs (17 tests) is added to the CI list.

🤖 Generated with Claude Code

durable-workflow-ops and others added 2 commits October 20, 2026 18:11
GET, POST and DELETE /api/search-attributes list, register and remove a
namespace's custom definitions for operators, with PHP's rules: trimmed
request strings, Laravel's validation messages, reserved system names and
aliases, duplicates that keep their type, a per-namespace limit
(DW_MAX_SEARCH_ATTRIBUTES, default 100) and protected system attributes.
An empty custom map renders as a JSON array, as PHP renders it. A racing
duplicate registration is refused as a duplicate rather than a server
error.

The search-attributes fixture drives two fresh namespaces through the
published SDK and raw requests. Start and upsert still refuse attribute
values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

Parity run 39473462838 failed in one job, mysql-execution (existing-php-mysql-matrix). The native recording of the parallel SDK query-direction cohort got HTTP status 0 (no response) where the contract expects 200: Expected values to be strictly equal: 0 !== 200. PHP and embedded passed that cohort, and every other job and cohort passed. This PR changes only the search attribute registry, not the query path. I've requested a rerun of the failed job to see whether it recurs.

…butes

# Conflicts:
#	docs/rust-server-port.md
@rmcdaniel
rmcdaniel enabled auto-merge October 20, 2026 22:24
@rmcdaniel

Copy link
Copy Markdown
Member Author

Merged main (49a56f5c0: #551 namespace update, #545 database TLS, #556 certifi) into this branch as e28e9d2a4. The only conflict was in the port-log checkpoint list, and I kept both entries.

Parity. I cancelled the Shared Server fixtures run for the merged head (39507850761) as a duplicate:

  • the branch's own change is unchanged since 39473462838, which passed all 13 jobs on 31028eda4;
  • that pass followed one rerun of the mysql-execution job, after the query-direction status-0 failure noted above;
  • main's additions run their own parity after each merge.

Local check of the merged head. On SQLite, the native lib suite (122) and the execution suite (290, including the three search_attributes tests) pass.

Auto-merge is on for the required checks.

…butes

# Conflicts:
#	.github/workflows/server-parity.yml
#	docs/rust-server-port.md
#	rust/src/runtime/http.rs
#	scripts/conformance/server-parity/contract.mjs
#	scripts/conformance/server-parity/probe.php
@rmcdaniel

Copy link
Copy Markdown
Member Author

826d995bb merges main after #543 (terminate and worker listing). Both branches add to the same registries, so I resolved additive conflicts in:

  • contract.mjs and probe.php;
  • the server-parity.yml unit test lists;
  • the port log;
  • named_namespace_operation in http.rs (the search attribute and worker read rules are kept side by side).

Local checks of the merged head:

  • Native suites on SQLite. The lib suite (124) and the execution suite (294) pass.
  • Contract unit tests. The search attribute, worker listing and worker replacement tests pass (48).
  • SQLite parity replica. PHP 2.5.14, embedded PHP and native pass search-attributes, worker-listing, worker-replacement-activity-lease and namespace-isolation, and the comparison passes.

The Shared Server fixtures run for this head (39517434159) is left running. Auto-merge stays on.

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants