Skip to content

feat(iris): route actor RPC calls through proxy and decode responses#4161

Merged
ravwojdyla merged 1 commit intomainfrom
rav-rpc-actor-proxy-cli
Mar 26, 2026
Merged

feat(iris): route actor RPC calls through proxy and decode responses#4161
ravwojdyla merged 1 commit intomainfrom
rav-rpc-actor-proxy-cli

Conversation

@ravwojdyla-agent
Copy link
Copy Markdown
Contributor

Summary

  • iris rpc actor call --actor-name <full-name> --method-name <method> now automatically sets the x-iris-actor-endpoint header, routing the call through the controller's actor proxy to the correct actor server
  • ActorResponse serialized_value is auto-unpickled so the CLI prints human-readable JSON instead of opaque base64

Example

uv run iris --config lib/iris/examples/marin-dev.yaml rpc actor call \
  --actor-name "/rav/my-job/zephyr-coord-0" \
  --method-name get_counters

# Output:
{
  "minhash/documents": 7849813,
  "minhash/buckets": 204095138
}

Test plan

  • Tested live against a running zephyr dedup job on marin-dev
  • Add unit test for _format_actor_response

🤖 Generated with Claude Code

@ravwojdyla-agent ravwojdyla-agent added the agent-generated Created by automation/agent label Mar 26, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0ebd049413

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread lib/iris/src/iris/cli/rpc.py Outdated
Comment on lines +326 to +327
actor_name = field_values.get("actor_name")
if service_name == "actor" and actor_name:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive actor proxy header from parsed request body

actor_name is pulled only from field_values (CLI flags), so actor RPCs invoked via --json never set x-iris-actor-endpoint. In that path the proxy receives no routing header and returns 400 Missing x-iris-actor-endpoint, which makes the generic --json request mode unusable for actor methods (for example iris rpc actor call --json '{..."actor_name": ...}'). Read actor_name from the parsed request payload when --json is used.

Useful? React with 👍 / 👎.

@ravwojdyla ravwojdyla requested a review from rjpower March 26, 2026 01:10
Copy link
Copy Markdown
Collaborator

@rjpower rjpower left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems reasonable, but i might suggest that we special case actor calls as their own iris actor call <endpoint> <name> <args> instead. that would give us more flexibility to handle the serialization/pickle stuff and properly handle function arguments.

Comment thread lib/iris/src/iris/cli/rpc.py Outdated
which = response.WhichOneof("result")
if which == "serialized_value":
value = cloudpickle.loads(response.serialized_value)
return json.dumps(value, indent=2, default=str)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is value always json serializable? maybe just wrap in a try/except, fallback to repr

Copy link
Copy Markdown
Contributor

@ravwojdyla ravwojdyla Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

according to claude yes, but will introduce separate cli per request and try/except

def callback(ctx: click.Context, json_str: str | None, **kwargs):
controller_url = require_controller_url(ctx)
field_values = {k: v for k, v in kwargs.items() if v is not None}
request = build_request(method, json_str, field_values)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does build request do the right thing for actor calls?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It did in my local tests

@ravwojdyla ravwojdyla force-pushed the rav-rpc-actor-proxy-cli branch 2 times, most recently from 0a300f7 to 6afb6a0 Compare March 26, 2026 01:34
Dedicated CLI command for actor RPCs instead of bolting onto the generic
rpc infrastructure. Handles auth, proxy header injection, cloudpickle
deserialization, and JSON kwargs naturally:

  iris actor call /user/job/coord-0 get_counters
  iris actor call /user/job/coord-0 get_counters '{"worker_id": "w-3"}'

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ravwojdyla ravwojdyla force-pushed the rav-rpc-actor-proxy-cli branch from 6afb6a0 to 20704ec Compare March 26, 2026 02:11
@ravwojdyla-agent
Copy link
Copy Markdown
Contributor Author

🤖 Validated the CLI against a live fuzzy dedup job on marin-dev. Examples:

# Global counters (accumulated across all stages)
uv run iris --config lib/iris/examples/marin-dev.yaml actor call \
  /rav/iris-run-reference_counter_test-20260326-013741/zephyr-fuzzy-dedup-03c3ddd9-p0-a0/zephyr-fuzzy-dedup-03c3ddd9-p0-coord-0 \
  get_counters
# {"minhash/documents": 4039056, "minhash/buckets": 105015328}

# Per-worker counters (in-flight heartbeat snapshot)
uv run iris --config lib/iris/examples/marin-dev.yaml actor call \
  /rav/.../zephyr-fuzzy-dedup-03c3ddd9-p0-coord-0 \
  get_counters '{"worker_id": "zephyr-fuzzy-dedup-03c3ddd9-p0-workers-0"}'
# {"minhash/documents": 524288, "minhash/buckets": 13631488}

# Get job status
uv run iris --config lib/iris/examples/marin-dev.yaml actor call \
  /rav/.../zephyr-fuzzy-dedup-03c3ddd9-p0-coord-0 \
  get_status

Per-worker values diverge as expected (different shard sizes / processing speeds). Auth token is no longer leaked in logs.

@ravwojdyla ravwojdyla merged commit 2f7e90b into main Mar 26, 2026
41 checks passed
@ravwojdyla ravwojdyla deleted the rav-rpc-actor-proxy-cli branch March 26, 2026 02:33
Helw150 pushed a commit that referenced this pull request Apr 8, 2026
…4161)

## Summary
- `iris rpc actor call --actor-name <full-name> --method-name <method>`
now automatically sets the `x-iris-actor-endpoint` header, routing the
call through the controller's actor proxy to the correct actor server
- ActorResponse `serialized_value` is auto-unpickled so the CLI prints
human-readable JSON instead of opaque base64

### Example
```bash
uv run iris --config lib/iris/examples/marin-dev.yaml rpc actor call \
  --actor-name "/rav/my-job/zephyr-coord-0" \
  --method-name get_counters

# Output:
{
  "minhash/documents": 7849813,
  "minhash/buckets": 204095138
}
```

## Test plan
- [x] Tested live against a running zephyr dedup job on marin-dev
- [ ] Add unit test for `_format_actor_response`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Rafal Wojdyla <ravwojdyla@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-generated Created by automation/agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants