Automatic request header code generation for resource routing#1179
Open
tconley1428 wants to merge 17 commits intomasterfrom
Open
Automatic request header code generation for resource routing#1179tconley1428 wants to merge 17 commits intomasterfrom
tconley1428 wants to merge 17 commits intomasterfrom
Conversation
- Fix generate_resource_id to return empty string when both IDs are empty, matching Go's getActivityResourceId behavior - Add missing resource_id to RespondActivityTaskCanceledByIdRequest - Reformat resource_id() in activities.rs for readability and consistency Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract to_snake_case, to_pascal_case, proto_to_rust_path as shared free functions used by both PayloadVisitorGenerator and RequestHeaderGenerator - Simplify to_map_entry_name to delegate to to_pascal_case - Remove HeaderExtractionOptions wrapper; call extract_temporal_request_headers directly with Option<&MetadataMap> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The descriptor file includes full proto metadata (including extension annotations) regardless of server codegen. build_server(true) only generates unused server stubs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace regex-based template parsing with a simple char iterator.
The only usage was extracting {field_path} placeholders from templates.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update all .returning() and .withf() closures in tests to account for the extra resource_id parameter on activity methods and workflow_id parameter on fail_workflow_task. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…types 18 tests in request_headers.rs verifying the code-generated extract_temporal_request_headers produces correct temporal-resource-id headers for: - Workflow requests (start, signal, task completed/failed) - Activity requests (completed, failed, canceled + ById variants) - Heartbeat requests (by token and by ID) - Worker heartbeat - Batch operations (ExecuteMultiOperation) - Duplicate header suppression and empty field handling Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Five tests exercising the full worker pipeline (poll → complete/fail/cancel/heartbeat)
verifying the correct resource_id reaches the client:
- Workflow activity completion: "workflow:{workflow_id}"
- Standalone activity completion: "activity:{activity_id}"
- Activity failure: "workflow:{workflow_id}"
- Activity cancellation: "workflow:{workflow_id}"
- Activity heartbeat: "workflow:{workflow_id}"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
02bc9ff to
a5bf2c4
Compare
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace map_or(true, ...) with is_none_or(...) in generated code
- Use val.to_string() instead of format!("{}", val) for passthrough templates
- Collapse nested if/if-let into single if-let chains
- Remove unused request_type field from MethodHeaderInfo
- Remove unused generate_field_accessor (logic moved inline)
- Fix missed test mock closure in worker_tests.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Revert cosmetic enum reordering that was unrelated to this PR. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
tconley1428
commented
Mar 26, 2026
| let out = PathBuf::from(env::var("OUT_DIR").unwrap()); | ||
| let descriptor_file = out.join("descriptors.bin"); | ||
| let mut builder = tonic_prost_build::configure() | ||
| // We don't actually want to build the grpc definitions - we don't need them (for now). |
Contributor
Author
There was a problem hiding this comment.
Put comment back
tconley1428
commented
Mar 26, 2026
crates/common/build.rs
Outdated
| } | ||
| output.push_str(&format!( | ||
| r#" if let Some(req) = request.downcast_ref::<{}>() | ||
| && let Some(val) = (|| -> Option<&str> {{ Some({}) }})() |
Contributor
Author
There was a problem hiding this comment.
What is the point of this lambda?
Member
There was a problem hiding this comment.
This is exceptionally weird. I think it did this for "performance" reasons so that it wouldn't construct an option if the if check short-circuits on the first thing... but super unnecessary
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The generated code for nested field access used immediately-invoked closures as a workaround to use the ? operator. Now uses chained let bindings in if-let expressions instead, which is clearer and idiomatic. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Unify simple and nested field paths into one code generation path - Extract parse_annotation and parse_field_paths as free functions - Flatten process_descriptors_reflect by inlining process_method_reflect - Remove intermediate val binding in generated code for simple fields - Remove unused generate_field_accessor and generate_extraction_function Generated output is semantically identical (verified by diff and tests). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
temporal.api.protometa.v1.request_headerproto annotations and generates Rust header extraction logicnamespaced_request!macro withrequest_with_headers!that extracts both namespace and annotation-based headers (e.g.,temporal-resource-id)resource_idfields on all relevant request messages for multi-cell routing:workflow:{workflow_id}workflow:{workflow_id}oractivity:{activity_id}for standaloneworker:{worker_grouping_key}Rust equivalent of temporalio/sdk-go#2226.
🤖 Generated with Claude Code