|
1 | | -use crate::types::BundleEvent; |
| 1 | +use crate::types::{BundleEvent, UserOpEvent}; |
2 | 2 | use anyhow::Result; |
3 | 3 | use async_trait::async_trait; |
4 | 4 | use rdkafka::producer::{FutureProducer, FutureRecord}; |
@@ -104,3 +104,103 @@ impl BundleEventPublisher for LoggingBundleEventPublisher { |
104 | 104 | Ok(()) |
105 | 105 | } |
106 | 106 | } |
| 107 | + |
| 108 | +#[async_trait] |
| 109 | +pub trait UserOpEventPublisher: Send + Sync { |
| 110 | + async fn publish(&self, event: UserOpEvent) -> Result<()>; |
| 111 | + |
| 112 | + async fn publish_all(&self, events: Vec<UserOpEvent>) -> Result<()>; |
| 113 | +} |
| 114 | + |
| 115 | +#[derive(Clone)] |
| 116 | +pub struct KafkaUserOpEventPublisher { |
| 117 | + producer: FutureProducer, |
| 118 | + topic: String, |
| 119 | +} |
| 120 | + |
| 121 | +impl KafkaUserOpEventPublisher { |
| 122 | + pub fn new(producer: FutureProducer, topic: String) -> Self { |
| 123 | + Self { producer, topic } |
| 124 | + } |
| 125 | + |
| 126 | + async fn send_event(&self, event: &UserOpEvent) -> Result<()> { |
| 127 | + let user_op_hash = event.user_op_hash(); |
| 128 | + let key = event.generate_event_key(); |
| 129 | + let payload = serde_json::to_vec(event)?; |
| 130 | + |
| 131 | + let record = FutureRecord::to(&self.topic).key(&key).payload(&payload); |
| 132 | + |
| 133 | + match self |
| 134 | + .producer |
| 135 | + .send(record, tokio::time::Duration::from_secs(5)) |
| 136 | + .await |
| 137 | + { |
| 138 | + Ok(_) => { |
| 139 | + debug!( |
| 140 | + user_op_hash = %user_op_hash, |
| 141 | + topic = %self.topic, |
| 142 | + payload_size = payload.len(), |
| 143 | + "Successfully published user op event" |
| 144 | + ); |
| 145 | + Ok(()) |
| 146 | + } |
| 147 | + Err((err, _)) => { |
| 148 | + error!( |
| 149 | + user_op_hash = %user_op_hash, |
| 150 | + topic = %self.topic, |
| 151 | + error = %err, |
| 152 | + "Failed to publish user op event" |
| 153 | + ); |
| 154 | + Err(anyhow::anyhow!("Failed to publish user op event: {err}")) |
| 155 | + } |
| 156 | + } |
| 157 | + } |
| 158 | +} |
| 159 | + |
| 160 | +#[async_trait] |
| 161 | +impl UserOpEventPublisher for KafkaUserOpEventPublisher { |
| 162 | + async fn publish(&self, event: UserOpEvent) -> Result<()> { |
| 163 | + self.send_event(&event).await |
| 164 | + } |
| 165 | + |
| 166 | + async fn publish_all(&self, events: Vec<UserOpEvent>) -> Result<()> { |
| 167 | + for event in events { |
| 168 | + self.send_event(&event).await?; |
| 169 | + } |
| 170 | + Ok(()) |
| 171 | + } |
| 172 | +} |
| 173 | + |
| 174 | +#[derive(Clone)] |
| 175 | +pub struct LoggingUserOpEventPublisher; |
| 176 | + |
| 177 | +impl LoggingUserOpEventPublisher { |
| 178 | + pub fn new() -> Self { |
| 179 | + Self |
| 180 | + } |
| 181 | +} |
| 182 | + |
| 183 | +impl Default for LoggingUserOpEventPublisher { |
| 184 | + fn default() -> Self { |
| 185 | + Self::new() |
| 186 | + } |
| 187 | +} |
| 188 | + |
| 189 | +#[async_trait] |
| 190 | +impl UserOpEventPublisher for LoggingUserOpEventPublisher { |
| 191 | + async fn publish(&self, event: UserOpEvent) -> Result<()> { |
| 192 | + info!( |
| 193 | + user_op_hash = %event.user_op_hash(), |
| 194 | + event = ?event, |
| 195 | + "Received user op event" |
| 196 | + ); |
| 197 | + Ok(()) |
| 198 | + } |
| 199 | + |
| 200 | + async fn publish_all(&self, events: Vec<UserOpEvent>) -> Result<()> { |
| 201 | + for event in events { |
| 202 | + self.publish(event).await?; |
| 203 | + } |
| 204 | + Ok(()) |
| 205 | + } |
| 206 | +} |
0 commit comments