feat(pubsub): Implement SubscribeTopicEventsAlpha1 for streaming PubSub subscriptions
- Dominant language
- JavaScript
- Stars
- 217
- Forks
- 104
- PR merge metrics
- No merged PRs in 30d
Description
## Description
Implement the SubscribeTopicEventsAlpha1 gRPC streaming RPC in the JS SDK to support programmatic streaming subscriptions for PubSub topics. This is a new feature that allows applications to subscribe to topics via a bidirectional gRPC stream directly from the client, rather than through the traditional app-callback (server-side) model.
Documentation: [https://docs.dapr.io/developing-applications/building-blocks/pubsub/subscription-methods/#programmatic-subscriptions](https://docs.dapr.io/developing-applications/building-blocks/pubsub/subscription-methods/#programmatic-subscriptions)
## Background
The Dapr runtime exposes a bidirectional streaming RPC:
```protobuf
rpc SubscribeTopicEventsAlpha1(stream SubscribeTopicEventsRequestAlpha1)
returns (stream SubscribeTopicEventsResponseAlpha1) {}
```
This allows the application to:
1. Initiate a subscription by sending a SubscribeTopicEventsRequestInitialAlpha1 message specifying pubsub_name, topic, metadata, and an optional dead_letter_topic.
2. Receive events as TopicEventRequest messages streamed back from the Dapr sidecar.
Acknowledge processing by sending SubscribeTopicEventsRequestProcessedAlpha1 messages back with the event id and a TopicEventResponse status (SUCCESS, RETRY, DROP).
3. This is fundamentally different from the existing subscription model in the SDK, which requires the app to run a server (HTTP or gRPC) that Dapr calls back into. The streaming model is client-initiated and doesn't require an app server, making it suitable for simpler applications, CLI tools, workers, and serverless scenarios.
## Current State in JS SDK
- The proto definition for SubscribeTopicEventsAlpha1 already exists in dapr/proto/runtime/v1/dapr.proto and src/proto/dapr/proto/runtime/v1/dapr.proto
- The ConnectRPC stubs in src/proto/dapr/proto/runtime/v1/dapr_connect.js already expose the method
- No implementation exists in the SDK — there is no client-side API to initiate a streaming subscription
## Proposed API
Add a subscribeWithStream (or similar) method to IClientPubSub / DaprClient.pubsub:
```ts
interface StreamingSubscription {
// Async iterator / callback for receiving events
on(event: 'message', handler: (event: TopicEventRequest) => Promise): void;
// Or async iterable pattern
[Symbol.asyncIterator](): AsyncIterator;
// Close the subscription stream
close(): Promise;
}
// On the client
client.pubsub.subscribeStream(
pubsubName: string,
topic: string,
options?: {
metadata?: Record;
deadLetterTopic?: string;
}
): Promise;
```
## Implementation Tasks
[ ] Add subscribeStream (or chosen name) to IClientPubSub interface
[ ] Implement in GRPCClient/pubsub.ts using the ConnectRPC bidirectional stream for SubscribeTopicEventsAlpha1
[ ] Handle the stream lifecycle:
- Send initial_request on open
- Await initial_response confirmation from Dapr
- Yield received event_message (TopicEventRequest) to the caller
- Send event_processed acknowledgements back on the stream
- Handle stream errors and reconnection (or surface errors to the caller)
[ ] Implement in HTTPClient/pubsub.ts — determine if HTTP supports this (likely gRPC-only; throw appropriate error for HTTP transport)
[ ] Define TypeScript types for the streaming subscription options and response
[ ] Add unit tests
[ ] Add E2E tests with a real Dapr sidecar
[ ] Add documentation/examples
## Notes
- This is an alpha1 API in the Dapr runtime, so it may change before becoming stable. The implementation should note this clearly in JSDoc.
- This is a gRPC-only feature — the bidirectional streaming pattern cannot be replicated over HTTP/1.1. The HTTP client implementation should throw a clear error indicating streaming subscriptions require the gRPC protocol.
- Consider how this interacts with the existing DaprServer-based subscription model — they serve different use cases and can coexist.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.