Skip to content

feat(iris): add actor proxy service for external access to cluster actors#4126

Merged
ravwojdyla merged 4 commits intomainfrom
claude/issue-4109-20260325-0332
Mar 25, 2026
Merged

feat(iris): add actor proxy service for external access to cluster actors#4126
ravwojdyla merged 4 commits intomainfrom
claude/issue-4109-20260325-0332

Conversation

@ravwojdyla
Copy link
Copy Markdown
Contributor

Adds an actor proxy route on the controller HTTP server that forwards ActorService RPCs to actors on worker VMs. External clients use ProxyResolver to route calls through the controller instead of connecting directly to internal IPs.

Closes #4109

Generated with Claude Code

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

ℹ️ 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".


self._actor_proxy = ActorProxy(self._service._db)
# Auth policy: proxy route requires authentication (checked by _RouteAuthMiddleware).
requires_auth(self._actor_proxy.handle)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P0 Badge Apply auth annotation to the handler function object

Calling requires_auth(self._actor_proxy.handle) attempts setattr on a bound method, which raises AttributeError ('method' object has no attribute ...) in Python. This happens during ControllerDashboard._create_app(), so controller startup fails before serving any routes. Annotate the underlying function (or wrap the handler in an annotated function) instead of mutating the bound method instance.

Useful? React with 👍 / 👎.

github-actions Bot and others added 2 commits March 25, 2026 12:09
…tors

Add a proxy route on the controller HTTP server that forwards ActorService
RPCs to actors on worker VMs. External clients use ProxyResolver to route
calls through the controller instead of connecting directly to internal IPs.

- ActorProxy: resolves endpoint from DB, forwards raw HTTP to actor server
- ProxyResolver: returns controller URL with X-Iris-Actor-Endpoint header
- ActorClient: passes endpoint metadata as headers on all RPC calls
- Dashboard: mounts proxy route with auth enforcement
- Integration tests: full round-trip, missing header, unknown endpoint

Closes #4109

Co-authored-by: Rafal Wojdyla <ravwojdyla@users.noreply.github.com>
setattr fails on bound methods in Python, so requires_auth() on
self._actor_proxy.handle raised AttributeError at controller startup.
Wrap in a local function decorated with @requires_auth instead.

Co-Authored-By: Rafal Wojdyla <ravwojdyla@gmail.com>
@ravwojdyla ravwojdyla force-pushed the claude/issue-4109-20260325-0332 branch from c761dd3 to e8caa03 Compare March 25, 2026 19:14
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.

lgtm!

i have this vague hand-wavy anxiety about actor -> cluster dependencies, but i don't think it's worth trying to address. (the only thing i could think of would be to define the proxyservice in the actor code, and then have some kind of generic route registration in the controller, but ultimately that doesn't feel worth the extra complexity.)

:shipit:

Comment thread lib/iris/src/iris/actor/client.py Outdated
def do_call():
client = self.rpc_client()
return client.start_operation(call)
return client.start_operation(call, headers=self._rpc_headers or None)
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.

it looks like rpc_headers is always set, so maybe we don't need the None part

from starlette.requests import Request
from starlette.responses import JSONResponse, Response

from iris.actor.resolver import ACTOR_ENDPOINT_HEADER
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.

nit: let's define the magic header constant here, we've been trying to avoid having cluster -> actor dependencies

- Remove unnecessary `or None` on _rpc_headers (always initialized as {})
- Define ACTOR_ENDPOINT_HEADER locally in actor_proxy.py to avoid
  cluster → actor import dependency

Co-Authored-By: Rafal Wojdyla <ravwojdyla@gmail.com>
@ravwojdyla ravwojdyla enabled auto-merge (squash) March 25, 2026 21:28
@ravwojdyla ravwojdyla merged commit 509fbac into main Mar 25, 2026
39 of 40 checks passed
@ravwojdyla ravwojdyla deleted the claude/issue-4109-20260325-0332 branch March 25, 2026 21:35
Helw150 pushed a commit that referenced this pull request Apr 8, 2026
…tors (#4126)

Adds an actor proxy route on the controller HTTP server that forwards
ActorService RPCs to actors on worker VMs. External clients use
ProxyResolver to route calls through the controller instead of
connecting directly to internal IPs.

Closes #4109

Generated with [Claude Code](https://claude.ai/code)

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Rafal Wojdyla <ravwojdyla@users.noreply.github.com>
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.

[iris] Actor proxy service for external access to cluster actors

2 participants