-
Notifications
You must be signed in to change notification settings - Fork 40
Adds 20250117-actors-pubsub.md #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
# Actor PubSub Implementation Proposal | ||
|
||
- Author(s): @joshvanl | ||
|
||
## Overview | ||
|
||
This proposal introduces PubSub capabilities for Dapr Actors, enabling actors to subscribe to messages within their type for a particular topic. | ||
Additionally, actors of a specific type will have the ability to publish messages to a topic. | ||
A single designated PubSub component will be marked as the actor PubSub, similar to how an actor state store is defined. | ||
There can be only one actor PubSub state store per Dapr deployment. | ||
|
||
## Background | ||
|
||
Currently, Dapr provides PubSub functionality for applications but lacks native PubSub integration for actors. | ||
This limitation means that actors cannot communicate efficiently via publish-subscribe messaging patterns within their type. | ||
By enabling Actor PubSub, actors can directly subscribe to and publish messages to specific topics, improving scalability and communication efficiency. | ||
|
||
## Implementation Details | ||
|
||
### Actor PubSub Registration | ||
|
||
A single PubSub component will be designated as the actor PubSub, similar to how an actor state store is configured. | ||
The metadata configuration will follow the existing pattern: | ||
|
||
```yaml | ||
metadata: | ||
- name: actorpubsub | ||
value: "true" | ||
``` | ||
|
||
Only one PubSub component can be marked as the actor PubSub. | ||
|
||
### Actor Subscriptions | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we don't need a special subscription. If you add the actor type and id in the cloudevent payload, routing can be done automatically from sidecar without the need of a new API. |
||
|
||
Actors will be able to subscribe to messages within their type for a particular topic. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like to see this supplemented with support for content-based routing. While a general broadcast is certainly a much-needed feature, I can easily imagine a chatty topic activating actors unnecessarily. Limiting such activations to only those actors registered to receive that subset would be a solid (and likely expected) part of this functionality. |
||
Subscriptions will be dynamically declared, and messages for that topic will be routed through the established bi-directional gRPC stream. | ||
|
||
Upon deactivation, either during shutdown or actor rebalancing, the subscription to all topics by the actor will be removed. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is not clear how rebalancing will work with the subscription. If the subscription is per actor type, how do you handle redirecting the message to the right actor instance? Also, how to handle subscription to all actorIds (fanout) vs to a single actor ID? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The same way this is handled with proxying existing requests today. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe a diagram can help explain this better. Each sidecar instance will read from the message broker, so will they compete for messages and redirect to the right sidecar for each actor id? |
||
Similarly, if an actor expires via it's idling window, actor is deactivated, and all subscriptions are removed. | ||
The idling timeout is reset on every subscription message received by the actor. | ||
|
||
```proto | ||
message ActorSubscriptionRequest { | ||
// The pubsub topic | ||
string topic = 1; | ||
|
||
// The metadata passing to pub components | ||
// | ||
// metadata property: | ||
// - key : the key of the message. | ||
map<string, string> metadata = 2; | ||
|
||
// dead_letter_topic is the topic to which messages that fail to be processed | ||
// are sent. | ||
optional string dead_letter_topic = 3; | ||
} | ||
``` | ||
|
||
When an actor subscribes to a topic, Dapr will internally create a subscription to: | ||
|
||
``` | ||
dapr.actors||$namespace||$actortype||$topic-name | ||
``` | ||
|
||
### Actor Publishing | ||
|
||
Actors will be able to publish messages to topics within their type. | ||
The following API will be used for message publishing: | ||
|
||
```proto | ||
message ActorPublishRequest { | ||
// The pubsub topic | ||
string topic = 1; | ||
|
||
// The data which will be published to topic. | ||
bytes data = 2; | ||
|
||
// The content type for the data (optional). | ||
string data_content_type = 3; | ||
|
||
// The metadata passing to pub components | ||
// | ||
// metadata property: | ||
// - key : the key of the message. | ||
map<string, string> metadata = 4; | ||
} | ||
``` | ||
|
||
Publishing follows the same topic naming convention: | ||
|
||
``` | ||
dapr.actors||$namespace||$actortype||$topic-name | ||
``` | ||
|
||
Messages published by an actor will be delivered to all actors of the same type that are subscribed to the given topic. | ||
yaron2 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Actor PubSub Message Handling | ||
|
||
Subscriptions and message handling will be processed through the existing bi-directional gRPC stream for actor communication. | ||
Messages delivered to subscribed actors will be sent over the established stream with the same payload as [today](https://github.com/dapr/dapr/blob/8cefe6a312867d8517a750d2dc300e10821bdf3a/dapr/proto/runtime/v1/appcallback.proto#L96). | ||
|
||
The client response is similarly the same format as [today](https://github.com/dapr/dapr/blob/8cefe6a312867d8517a750d2dc300e10821bdf3a/dapr/proto/runtime/v1/appcallback.proto#L136). | ||
|
||
### Non-Actor Publishing | ||
|
||
Non-actor clients are able to publish messages to actor subscribers via a new `PublishActorEvent` RPC. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've just realised this is the only way for an Actor to get a message - I had thought that actors could also subscribe to any pubsub topic for a fan out. Not sure how big a deal this is? With current design something would have to rebroadcast a message to the actor pubsub. An extra hop i guess but it in it defence may stop bad actors (pardon the pun) oversubscribing |
||
This RPC is close to the existing `PublishEvent` rpc, accept that it takes an `actor_type` field rather than a `pubsub_name` field. | ||
This is because their is 1. only one pubsub associated with actors in that namespace, and 2. the fully qualified topic name is derived via the actor type. | ||
|
||
Publishing messages to actors will not invoke, and therefore initialize the existence of an actor, since an actor needs to be subscribing to a topic to receive messages. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can see a requirement to also initialise an actor - could we have a flag that enables initialisation of an actor first. |
||
|
||
```proto | ||
rpc PublishActorEvent(PublishActorEventRequest) returns (google.protobuf.Empty) {} | ||
} | ||
|
||
message PublishActorEventRequest { | ||
// actor_type is the type of actor to which the message is sent. | ||
string actor_type = 1; | ||
|
||
// The pubsub topic | ||
string topic = 2; | ||
|
||
// The data which will be published to topic. | ||
bytes data = 3; | ||
|
||
// The content type for the data (optional). | ||
string data_content_type = 4; | ||
|
||
// The metadata passing to pub components | ||
// | ||
// metadata property: | ||
// - key : the key of the message. | ||
map<string, string> metadata = 5; | ||
} | ||
``` | ||
|
||
## Feature Lifecycle Outline | ||
|
||
This feature should be implemented after the actor bi-directional streaming feature is completed. | ||
The bi-directional stream will serve as the transport mechanism for delivering messages to actors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the advantage to have a single pubsub for actors vs allow it to be configured when registering the actor type, so different actor types can run with different pubsubs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens when two hosts with the same actor types have different pubsubs?