Skip to content

Add scope and limit key API, bump shared core to 7.0.1 and test suite to e2e v2.2#16

Merged
slinkydeveloper merged 5 commits into
mainfrom
scope-and-limit-key
Jul 16, 2026
Merged

Add scope and limit key API, bump shared core to 7.0.1 and test suite to e2e v2.2#16
slinkydeveloper merged 5 commits into
mainfrom
scope-and-limit-key

Conversation

@slinkydeveloper

@slinkydeveloper slinkydeveloper commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

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 require RESTATE_EXPERIMENTAL_ENABLE_SCOPED_VIRTUAL_OBJECTS=true.

  • 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:

    Restate.scope("tenant1").service_call(Greeter, :greet, "World", limit_key: "tenant1/user42")
  • generic_call / generic_send gain scope: and limit_key: keyword args.

  • ctx.request now exposes scope, limit_key, and idempotency_key.

The limit_key enforces hierarchical concurrency limits (one or two /-separated levels) on invocations sharing the same scope; it is not part of the request identity.

Plumbing

  • Bump restate-sdk-shared-core 7.0.0 → 7.0.1 (Cargo.toml, Cargo.lock, docs).
  • 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 / Request.
  • Forward scope/limit_key in the test-services Proxy, mirroring sdk-python.
  • RBS signatures updated.

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:

  • v2.2ProxyRequest gains optional scope/limitKey → forwarded in test-services/services/proxy.rb (part of this PR's feature work).
  • v2.1 — test-method randomization → no test-service change.
  • v2.0createSignal, runReturns, and the four await combinators are already implemented in the command interpreter; sleepConcurrently was removed from the suite → dropped its now-dead handler from test_utils.
  • v1.0 — persisted-timers fix → no test-service change.

Also simplified test-services/exclusions.yaml to {}: 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/build of the native extension against shared-core 7.0.1 ✓
  • Native FFI surface: sys_call arity 8, sys_send arity 9, Input#scope/#limit_key/#idempotency_key getters ✓
  • VMWrapper#sys_call/#sys_send forward scope/limit_key in the correct argument positions (default nil) ✓
  • VMWrapper#sys_input maps scope/limit_key/idempotency_key into Invocation
  • ScopedContext delegation for all six call/send methods + ctx.scope factory ✓
  • rubocop (all 57 files) clean; CI "Build, lint, typecheck & test" green ✓

🤖 Generated with Claude Code

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>
@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

Test Results

  8 files  ± 0    8 suites  ±0   4m 26s ⏱️ +37s
 60 tests +11   60 ✅ +11  0 💤 ±0  0 ❌ ±0 
267 runs  +51  267 ✅ +51  0 💤 ±0  0 ❌ ±0 

Results for commit a22e57b. ± Comparison against base commit 7bce9f6.

♻️ This comment has been updated with latest results.

slinkydeveloper and others added 2 commits July 16, 2026 16:34
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>
@slinkydeveloper slinkydeveloper changed the title Add scope and limit key API, bump shared core to 7.0.1 Add scope and limit key API, bump shared core to 7.0.1 and test suite to e2e v2.2 Jul 16, 2026
slinkydeveloper and others added 2 commits July 16, 2026 17:03
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>
@slinkydeveloper
slinkydeveloper merged commit 579e61f into main Jul 16, 2026
2 checks passed
@slinkydeveloper
slinkydeveloper deleted the scope-and-limit-key branch July 16, 2026 15:23
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