Publish a message to a topic. Returns `(sequence_number, receivers)` where `receivers` is the count of broadcast subscribers + consumer groups that received the message.
(
&self,
topic_name: &str,
payload: String,
publisher: &str,
)
| 178 | /// Returns `(sequence_number, receivers)` where `receivers` is the count of |
| 179 | /// broadcast subscribers + consumer groups that received the message. |
| 180 | pub fn publish( |
| 181 | &self, |
| 182 | topic_name: &str, |
| 183 | payload: String, |
| 184 | publisher: &str, |
| 185 | ) -> Result<(u64, usize), TopicError> { |
| 186 | let topics = super::lock_utils::read_or_recover(self.topics.read(), "topics"); |
| 187 | let topic_mutex = topics |
| 188 | .get(topic_name) |
| 189 | .ok_or_else(|| TopicError::NotFound(topic_name.to_string()))?; |
| 190 | let mut topic = super::lock_utils::lock_or_recover(topic_mutex.lock(), "topic"); |
| 191 | |
| 192 | let seq = topic.next_seq; |
| 193 | topic.next_seq += 1; |
| 194 | |
| 195 | let msg = PubSubMessage { |
| 196 | seq, |
| 197 | payload, |
| 198 | timestamp_ms: std::time::SystemTime::now() |
| 199 | .duration_since(std::time::UNIX_EPOCH) |
| 200 | .map(|d| d.as_millis() as u64) |
| 201 | .unwrap_or(0), |
| 202 | publisher: publisher.to_string(), |
| 203 | }; |
| 204 | |
| 205 | if topic.messages.len() >= topic.max_messages { |
| 206 | topic.messages.remove(0); |
| 207 | } |
| 208 | topic.messages.push(msg.clone()); |
| 209 | |
| 210 | // Deliver to broadcast subscribers. Remove dead channels. |
| 211 | let mut dead = Vec::new(); |
| 212 | for (&sub_id, sender) in &topic.subscribers { |
| 213 | if sender.try_send(msg.clone()).is_err() { |
| 214 | debug!( |
| 215 | topic = topic_name, |
| 216 | sub_id, "subscriber channel full or closed; removing" |
| 217 | ); |
| 218 | dead.push(sub_id); |
| 219 | } |
| 220 | } |
| 221 | for sub_id in dead { |
| 222 | topic.subscribers.remove(&sub_id); |
| 223 | } |
| 224 | |
| 225 | // Count live broadcast subscribers (after removing dead ones). |
| 226 | let broadcast_count = topic.subscribers.len(); |
| 227 | |
| 228 | // Deliver to consumer groups (one member per group, round-robin). |
| 229 | let group_count = topic.consumer_groups.len(); |
| 230 | for group in topic.consumer_groups.values_mut() { |
| 231 | group.deliver(&msg); |
| 232 | } |
| 233 | |
| 234 | let receivers = broadcast_count + group_count; |
| 235 | debug!(topic = topic_name, seq, receivers, "message published"); |
| 236 | Ok((seq, receivers)) |
| 237 | } |