@@ -92,15 +92,21 @@ pub struct SubscriptionManager {
92
92
93
93
/// Keep the notification listener alive
94
94
listener : StoreEventListener ,
95
+
96
+ logger : Logger ,
95
97
}
96
98
97
99
impl SubscriptionManager {
98
100
pub fn new ( logger : Logger , postgres_url : String , registry : Arc < MetricsRegistry > ) -> Self {
99
- let ( listener, store_events) = StoreEventListener :: new ( logger, postgres_url, registry) ;
101
+ let logger = logger. new ( o ! ( "component" => "StoreEventListener" ) ) ;
102
+
103
+ let ( listener, store_events) =
104
+ StoreEventListener :: new ( logger. cheap_clone ( ) , postgres_url, registry) ;
100
105
101
106
let mut manager = SubscriptionManager {
102
107
subscriptions : Arc :: new ( RwLock :: new ( HashMap :: new ( ) ) ) ,
103
108
listener,
109
+ logger,
104
110
} ;
105
111
106
112
// Deal with store subscriptions
@@ -112,6 +118,32 @@ impl SubscriptionManager {
112
118
manager
113
119
}
114
120
121
+ async fn broadcast_event (
122
+ logger : & Logger ,
123
+ subscriptions : & Arc < RwLock < HashMap < usize , Sender < Arc < StoreEvent > > > > > ,
124
+ event : StoreEvent ,
125
+ ) {
126
+ let event = Arc :: new ( event) ;
127
+
128
+ // Send to `subscriptions`.
129
+ {
130
+ let senders = subscriptions. read ( ) . unwrap ( ) . clone ( ) ;
131
+
132
+ // Write change to all matching subscription streams; remove subscriptions
133
+ // whose receiving end has been dropped
134
+ for ( id, sender) in senders {
135
+ if let Err ( e) = sender. send ( event. cheap_clone ( ) ) . await {
136
+ error ! (
137
+ logger,
138
+ "Failed to send store event to subscriber {}: {}" , id, e
139
+ ) ;
140
+ // Receiver was dropped
141
+ subscriptions. write ( ) . unwrap ( ) . remove ( & id) ;
142
+ }
143
+ }
144
+ }
145
+ }
146
+
115
147
/// Receive store events from Postgres and send them to all active
116
148
/// subscriptions. Detect stale subscriptions in the process and
117
149
/// close them.
@@ -121,24 +153,22 @@ impl SubscriptionManager {
121
153
) {
122
154
let subscriptions = self . subscriptions . cheap_clone ( ) ;
123
155
let mut store_events = store_events. compat ( ) ;
156
+ let logger = self . logger . cheap_clone ( ) ;
124
157
125
158
// This channel is constantly receiving things and there are locks involved,
126
159
// so it's best to use a blocking task.
127
160
graph:: spawn_blocking ( async move {
128
- while let Some ( Ok ( event) ) = store_events. next ( ) . await {
129
- let event = Arc :: new ( event) ;
130
-
131
- // Send to `subscriptions`.
132
- {
133
- let senders = subscriptions. read ( ) . unwrap ( ) . clone ( ) ;
134
-
135
- // Write change to all matching subscription streams; remove subscriptions
136
- // whose receiving end has been dropped
137
- for ( id, sender) in senders {
138
- if sender. send ( event. cheap_clone ( ) ) . await . is_err ( ) {
139
- // Receiver was dropped
140
- subscriptions. write ( ) . unwrap ( ) . remove ( & id) ;
141
- }
161
+ loop {
162
+ match store_events. next ( ) . await {
163
+ Some ( Ok ( event) ) => {
164
+ Self :: broadcast_event ( & logger, & subscriptions, event) . await ;
165
+ }
166
+ Some ( Err ( _) ) => {
167
+ error ! ( logger, "Error receiving store event" ) ;
168
+ }
169
+ None => {
170
+ error ! ( logger, "Store event stream ended" ) ;
171
+ break ;
142
172
}
143
173
}
144
174
}
@@ -147,6 +177,7 @@ impl SubscriptionManager {
147
177
148
178
fn periodically_clean_up_stale_subscriptions ( & self ) {
149
179
let subscriptions = self . subscriptions . cheap_clone ( ) ;
180
+ let logger = self . logger . cheap_clone ( ) ;
150
181
151
182
// Clean up stale subscriptions every 5s
152
183
graph:: spawn ( async move {
@@ -169,6 +200,7 @@ impl SubscriptionManager {
169
200
170
201
// Remove all stale subscriptions
171
202
for id in stale_ids {
203
+ warn ! ( logger, "Removing stale subscription {}" , id) ;
172
204
subscriptions. remove ( & id) ;
173
205
}
174
206
}
0 commit comments