Add scope and limit key API, bump shared core to 7.0.1 and test suite to e2e v2.2#16
Merged
Conversation
Replicates the scope / flow-control limit key feature from the Python SDK (sdk-python PRs #207 and #212). New public API (in preview, requires restate-server 1.7 experimental protocol v7 + vqueues): - `ctx.scope(scope)` / `Restate.scope(scope)` return a `ScopedContext` whose `service_call`/`service_send`/`object_call`/`object_send`/ `workflow_call`/`workflow_send` carry the captured scope and accept an optional `limit_key` for hierarchical concurrency limits. - `generic_call` / `generic_send` gain `scope:` and `limit_key:` kwargs. - `ctx.request` now exposes `scope`, `limit_key`, and `idempotency_key`. Plumbing: - Bump restate-sdk-shared-core 7.0.0 -> 7.0.1 (Cargo.toml, Cargo.lock). - Thread scope/limit_key into the shared-core `Target` in the native `sys_call` (arity 6->8) and `sys_send` (7->9); expose scope/limit_key/ idempotency_key on the native `Input`. - Forward the new fields through `VMWrapper` and populate `Invocation`. - Forward scope/limit_key in the test-services proxy, mirroring sdk-python. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reformat the ScopedContext delegations and workflow_call/workflow_send to the paren-at-EOL style so hash keys align and lines stay within 120 chars. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Point the integration workflow at restatedev/e2e/sdk-tests@v2.2 (was v1.0).
Reviewed the e2e release notes from v2.2 back to v1.0 for test-service
contract changes:
- v2.2: ProxyRequest gains optional scope/limitKey — already forwarded in
test-services/services/proxy.rb (added with the scope/limit_key feature).
- v2.1: test method randomization — no test-service change.
- v2.0: createSignal, runReturns, and the four await combinators are
already implemented in the command interpreter; sleepConcurrently was
removed from the suite, so drop its now-dead handler from test_utils.
- v1.0: persisted timers fix — no test-service change.
Also simplify exclusions.yaml to `{}`: the per-suite keys only ever held
empty arrays (they subtract tests, they don't enable suites), so they
excluded nothing. Matches the sdk-python exclusions file.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
igalshilman
approved these changes
Jul 16, 2026
Port the Java ConcurrencyLimitExample to Ruby: an AmazonMerchantService third-party API wrapper and an OrderFulfillment service that rate-limits checkout calls per user API key via Restate.scope(api_key).service_call(...). (OrderProcessor is already taken by service_configuration.rb, so the processor is named OrderFulfillment.) - examples/concurrency_limit.rb — new runnable example, registered in config.ru - docs/USER_GUIDE.md — new "Scoped Calls & Concurrency Limits" section, Request metadata (scope/limit_key/idempotency_key), examples table entry, and quick-reference entries Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The fluent Service.call / .send! API is the recommended way to make calls, so let it carry a scope too — matching the Java example's Restate.scope(key).service(Class).handler(...) ergonomics. - .call / .send! on Service, VirtualObject, Workflow accept scope:/limit_key: - ServiceCallProxy / ServiceSendProxy thread them through method_missing (a per-call scope:/limit_key: still overrides the proxy default) - examples/concurrency_limit.rb uses the fluent form: AmazonMerchantService.call(scope: api_key).checkout(...) - USER_GUIDE leads with the fluent form; RBS updated Co-Authored-By: Claude Opus 4.8 (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.
Replicates the scope / flow-control limit key feature from the Python SDK (sdk-python #207 and #212) into the Ruby SDK. The shared core already supports it — this wires the API through.
New public API
Note
This API is in preview and is not enabled by default. On restate-server 1.7 it requires the experimental protocol v7 + vqueues features (
RESTATE_EXPERIMENTAL_ENABLE_PROTOCOL_V7=true,RESTATE_EXPERIMENTAL_ENABLE_VQUEUES=true), and scoped virtual objects additionally requireRESTATE_EXPERIMENTAL_ENABLE_SCOPED_VIRTUAL_OBJECTS=true.ctx.scope(scope)/Restate.scope(scope)return aScopedContextwhoseservice_call/service_send/object_call/object_send/workflow_call/workflow_sendcarry the captured scope and accept an optionallimit_key:generic_call/generic_sendgainscope:andlimit_key:keyword args.ctx.requestnow exposesscope,limit_key, andidempotency_key.The
limit_keyenforces hierarchical concurrency limits (one or two/-separated levels) on invocations sharing the same scope; it is not part of the request identity.Plumbing
restate-sdk-shared-core7.0.0 → 7.0.1 (Cargo.toml,Cargo.lock, docs).scope/limit_keyinto the shared-coreTargetin the nativesys_call(arity 6→8) andsys_send(7→9); exposescope/limit_key/idempotency_keyon the nativeInput.VMWrapperand populateInvocation/Request.scope/limit_keyin the test-servicesProxy, mirroring sdk-python.Test suite → e2e v2.2
Bump the integration workflow to
restatedev/e2e/sdk-tests@v2.2(was@v1.0). Reviewed the e2e release notes from v2.2 back to v1.0 for test-service contract changes:ProxyRequestgains optionalscope/limitKey→ forwarded intest-services/services/proxy.rb(part of this PR's feature work).createSignal,runReturns, and the four await combinators are already implemented in the command interpreter;sleepConcurrentlywas removed from the suite → dropped its now-dead handler fromtest_utils.Also simplified
test-services/exclusions.yamlto{}: the per-suite keys only ever held empty arrays (the file subtracts tests, it doesn't enable suites), so they excluded nothing. Matches sdk-python.Verification
cargo check/buildof the native extension against shared-core 7.0.1 ✓sys_callarity 8,sys_sendarity 9,Input#scope/#limit_key/#idempotency_keygetters ✓VMWrapper#sys_call/#sys_sendforward scope/limit_key in the correct argument positions (default nil) ✓VMWrapper#sys_inputmaps scope/limit_key/idempotency_key intoInvocation✓ScopedContextdelegation for all six call/send methods +ctx.scopefactory ✓rubocop(all 57 files) clean; CI "Build, lint, typecheck & test" green ✓🤖 Generated with Claude Code