photon_backend/models/subscribe_opts.rs
1//! Options and handle for typed subscribe.
2
3use super::SubscriptionMode;
4
5/// Options specific to consumer-group subscriptions.
6///
7/// Used with [`SubscribeOpts::consumer_group`]. Checkpoints are owned by `group_id` × shard,
8/// not per-instance subscription names.
9#[derive(Debug, Clone)]
10pub struct GroupOpts {
11 /// Stable consumer group identifier (shared across replicas).
12 pub group_id: String,
13 /// Override virtual shard count (defaults to topic `#[photon::topic(shards = ...)]`).
14 pub shard_count: Option<u32>,
15 /// Fleet member id for lease coordination (static env assignment when unset).
16 pub instance_id: Option<String>,
17}
18
19impl GroupOpts {
20 /// Create group options with the given `group_id`.
21 pub fn new(group_id: impl Into<String>) -> Self {
22 Self {
23 group_id: group_id.into(),
24 shard_count: None,
25 instance_id: None,
26 }
27 }
28
29 /// Override virtual shard count for this subscription.
30 #[must_use]
31 pub const fn shards(mut self, count: u32) -> Self {
32 self.shard_count = Some(count);
33 self
34 }
35
36 /// Set fleet member instance id for lease-based assignment.
37 #[must_use]
38 pub fn instance_id(mut self, id: impl Into<String>) -> Self {
39 self.instance_id = Some(id.into());
40 self
41 }
42}
43
44/// Options for subscribing to a topic.
45///
46/// # Examples
47///
48/// Ephemeral stream with partition filter (see `keyed_topic` example):
49///
50/// ```rust,no_run
51/// use photon_backend::SubscribeOpts;
52///
53/// # async fn demo() -> photon_backend::Result<()> {
54/// let opts = SubscribeOpts::default_ephemeral().topic_key_filter("alice");
55/// # Ok(())
56/// # }
57/// ```
58///
59/// Durable broadcast by subscription name:
60///
61/// ```rust,no_run
62/// use photon_backend::SubscribeOpts;
63///
64/// let opts = SubscribeOpts::broadcast().subscription_name("my-worker");
65/// ```
66#[derive(Debug, Clone, Default)]
67pub struct SubscribeOpts {
68 /// Subscription name (required for durable broadcast mode).
69 pub subscription_name: Option<String>,
70 /// Filter by topic key (for keyed topics).
71 pub topic_key_filter: Option<String>,
72 /// Durable or ephemeral mode.
73 pub mode: SubscriptionMode,
74 /// Consumer group (load-balanced); mutually exclusive with durable subscription name.
75 pub consumer_group: Option<GroupOpts>,
76}
77
78impl SubscribeOpts {
79 /// Create default options (ephemeral, no key filter).
80 #[must_use]
81 pub const fn default_ephemeral() -> Self {
82 Self {
83 subscription_name: None,
84 topic_key_filter: None,
85 mode: SubscriptionMode::Ephemeral,
86 consumer_group: None,
87 }
88 }
89
90 /// Broadcast durable subscription (today's default).
91 #[must_use]
92 pub fn broadcast() -> Self {
93 Self {
94 mode: SubscriptionMode::Durable,
95 ..Self::default_ephemeral()
96 }
97 }
98
99 /// Load-balanced consumer group subscription.
100 #[must_use]
101 pub fn consumer_group(mut self, opts: GroupOpts) -> Self {
102 self.subscription_name = None;
103 self.topic_key_filter = None;
104 self.mode = SubscriptionMode::Durable;
105 self.consumer_group = Some(opts);
106 self
107 }
108
109 /// Set subscription name (for durable mode).
110 #[must_use]
111 pub fn subscription_name(mut self, name: impl Into<String>) -> Self {
112 self.subscription_name = Some(name.into());
113 self
114 }
115
116 /// Set topic key filter.
117 #[must_use]
118 pub fn topic_key_filter(mut self, key: impl Into<String>) -> Self {
119 self.topic_key_filter = Some(key.into());
120 self
121 }
122
123 /// Set mode.
124 #[must_use]
125 pub const fn mode(mut self, mode: SubscriptionMode) -> Self {
126 self.mode = mode;
127 self
128 }
129}
130
131/// Placeholder for future subscription lifecycle control (cancel, pause).
132///
133/// v0.1 returns a no-op handle; dropping the subscribe stream task is the supported way to
134/// stop an ephemeral subscription today.
135#[derive(Debug, Default)]
136pub struct SubscriptionHandle {
137 _private: (),
138}
139
140impl SubscriptionHandle {
141 /// Create a new handle (reserved for future cancel/pause APIs).
142 #[must_use]
143 pub const fn new() -> Self {
144 Self { _private: () }
145 }
146}