1use std::any::Any;
11use std::cell::RefCell;
12use std::ops::DerefMut;
13use std::rc::Rc;
14
15use differential_dataflow::consolidation::consolidate_updates;
16use differential_dataflow::{AsCollection, VecCollection};
17use mz_compute_client::protocol::response::{SubscribeBatch, SubscribeResponse};
18use mz_compute_types::sinks::{ComputeSinkDesc, SubscribeSinkConnection};
19use mz_expr::{ColumnOrder, compare_columns};
20use mz_ore::iter;
21use mz_repr::{Diff, GlobalId, Row, Timestamp, UpdateCollection};
22use mz_storage_types::controller::CollectionMetadata;
23use mz_timely_util::probe::{Handle, ProbeNotify};
24use timely::PartialOrder;
25use timely::dataflow::channels::pact::Pipeline;
26use timely::dataflow::operators::generic::builder_rc::OperatorBuilder;
27use timely::progress::Antichain;
28use timely::progress::timestamp::Timestamp as TimelyTimestamp;
29
30use crate::render::StartSignal;
31use crate::render::errors::DataflowErrorSer;
32use crate::render::sinks::SinkRender;
33
34impl<'scope> SinkRender<'scope> for SubscribeSinkConnection {
35 fn render_sink(
36 &self,
37 compute_state: &mut crate::compute_state::ComputeState,
38 sink: &ComputeSinkDesc<CollectionMetadata>,
39 sink_id: GlobalId,
40 as_of: Antichain<Timestamp>,
41 _start_signal: StartSignal,
42 sinked_collection: VecCollection<'scope, Timestamp, Row, Diff>,
43 err_collection: VecCollection<'scope, Timestamp, DataflowErrorSer, Diff>,
44 output_probe: &Handle<Timestamp>,
45 ) -> Option<Rc<dyn Any>> {
46 let subscribe_protocol_handle = Rc::new(RefCell::new(Some(SubscribeProtocol {
50 sink_id,
51 sink_as_of: as_of.clone(),
52 subscribe_response_buffer: Some(Rc::clone(&compute_state.subscribe_response_buffer)),
53 prev_upper: Antichain::from_elem(Timestamp::minimum()),
54 output: self.output.clone(),
55 poison: None,
56 })));
57 let subscribe_protocol_weak = Rc::downgrade(&subscribe_protocol_handle);
58 let sinked_collection = sinked_collection
59 .inner
60 .probe_notify_with(vec![output_probe.clone()])
61 .as_collection();
62 subscribe(
63 sinked_collection,
64 err_collection,
65 sink_id,
66 sink.with_snapshot,
67 as_of,
68 sink.up_to.clone(),
69 subscribe_protocol_handle,
70 );
71
72 Some(Rc::new(scopeguard::guard((), move |_| {
76 if let Some(subscribe_protocol_handle) = subscribe_protocol_weak.upgrade() {
77 std::mem::drop(subscribe_protocol_handle.borrow_mut().take())
78 }
79 })))
80 }
81}
82
83fn subscribe<'scope>(
84 sinked_collection: VecCollection<'scope, Timestamp, Row, Diff>,
85 err_collection: VecCollection<'scope, Timestamp, DataflowErrorSer, Diff>,
86 sink_id: GlobalId,
87 with_snapshot: bool,
88 as_of: Antichain<Timestamp>,
89 up_to: Antichain<Timestamp>,
90 subscribe_protocol_handle: Rc<RefCell<Option<SubscribeProtocol>>>,
91) {
92 let name = format!("subscribe-{}", sink_id);
93 let mut op = OperatorBuilder::new(name, sinked_collection.scope());
94 let mut ok_input = op.new_input(sinked_collection.inner, Pipeline);
95 let mut err_input = op.new_input(err_collection.inner, Pipeline);
96
97 op.build(|_cap| {
98 let mut rows_to_emit = Vec::new();
99 let mut errors_to_emit = Vec::new();
100 let mut finished = false;
101
102 move |frontiers| {
103 if finished {
104 ok_input.for_each(|_, _| {});
106 err_input.for_each(|_, _| {});
107 return;
108 }
109
110 let mut frontier = Antichain::new();
111 for input_frontier in frontiers {
112 frontier.extend(input_frontier.frontier().iter().copied());
113 }
114
115 let should_emit = |time: &Timestamp| {
116 let beyond_as_of = if with_snapshot {
117 as_of.less_equal(time)
118 } else {
119 as_of.less_than(time)
120 };
121 let before_up_to = !up_to.less_equal(time);
122 beyond_as_of && before_up_to
123 };
124
125 ok_input.for_each(|_, data| {
126 for (row, time, diff) in data.drain(..) {
127 if should_emit(&time) {
128 rows_to_emit.push((time, row, diff));
129 }
130 }
131 });
132 err_input.for_each(|_, data| {
133 for (error, time, diff) in data.drain(..) {
134 if should_emit(&time) {
135 errors_to_emit.push((time, error, diff));
136 }
137 }
138 });
139
140 if let Some(subscribe_protocol) = subscribe_protocol_handle.borrow_mut().deref_mut() {
141 subscribe_protocol.send_batch(
142 frontier.clone(),
143 &mut rows_to_emit,
144 &mut errors_to_emit,
145 );
146 }
147
148 if PartialOrder::less_equal(&up_to, &frontier) {
149 finished = true;
150 if let Some(subscribe_protocol) = subscribe_protocol_handle.borrow_mut().deref_mut()
153 {
154 subscribe_protocol.send_batch(
155 Antichain::default(),
156 &mut Vec::new(),
157 &mut Vec::new(),
158 );
159 }
160 }
161 }
162 });
163}
164
165struct SubscribeProtocol {
172 pub sink_id: GlobalId,
173 pub sink_as_of: Antichain<Timestamp>,
174 pub subscribe_response_buffer: Option<Rc<RefCell<Vec<(GlobalId, SubscribeResponse)>>>>,
175 pub prev_upper: Antichain<Timestamp>,
176 pub output: Vec<ColumnOrder>,
177 pub poison: Option<String>,
183}
184
185impl SubscribeProtocol {
186 fn send_batch(
199 &mut self,
200 upper: Antichain<Timestamp>,
201 rows: &mut Vec<(Timestamp, Row, Diff)>,
202 errors: &mut Vec<(Timestamp, DataflowErrorSer, Diff)>,
203 ) {
204 if !PartialOrder::less_equal(&self.sink_as_of, &upper) || upper == self.prev_upper {
208 return;
209 }
210
211 let order = self.output.as_slice();
213 if order.is_empty() {
214 rows.sort_unstable_by(|(t0, r0, _), (t1, r1, _)| {
215 t0.cmp(t1).then_with(|| r0.cmp(r1)).reverse()
217 });
218 } else {
219 let mut left_datum_vec = mz_repr::DatumVec::new();
220 let mut right_datum_vec = mz_repr::DatumVec::new();
221 rows.sort_unstable_by(|(t0, r0, _), (t1, r1, _)| {
222 t0.cmp(t1)
224 .then_with(|| {
225 let dv0 = left_datum_vec.borrow_with(r0.as_row_ref());
226 let dv1 = right_datum_vec.borrow_with(r1.as_row_ref());
227 compare_columns(order, &dv0, &dv1, || r0.cmp(r1))
228 })
229 .reverse()
230 });
231 }
232 consolidate_updates(errors);
233
234 let ship_rows = {
235 let split_at = rows.partition_point(|(t, _, _)| upper.less_equal(t));
238 let ship_updates = rows[split_at..]
239 .iter()
240 .rev()
241 .map(|(t, r, d)| (r.as_row_ref(), t, *d));
242 let len = rows[split_at..].len();
243 let byte_len = len * 32;
246 let mut builder = UpdateCollection::builder(byte_len, len);
247 for update in iter::consolidate_update_iter(ship_updates) {
248 builder.push(update);
249 }
250 rows.truncate(split_at);
251 builder.build()
252 };
253 let (keep_errors, ship_errors) = errors.drain(..).partition(|u| upper.less_equal(&u.0));
254 *errors = keep_errors;
255
256 let updates = match (&self.poison, ship_errors.first()) {
257 (Some(error), _) => {
258 Err(error.clone())
260 }
261 (None, Some((_, error, _))) => {
262 let error = error.to_string();
264 self.poison = Some(error.clone());
265 Err(error)
266 }
267 (None, None) => {
268 Ok(vec![ship_rows])
270 }
271 };
272
273 let buffer = self
274 .subscribe_response_buffer
275 .as_mut()
276 .expect("The subscribe response buffer is only cleared on drop.");
277
278 buffer.borrow_mut().push((
279 self.sink_id,
280 SubscribeResponse::Batch(SubscribeBatch {
281 lower: self.prev_upper.clone(),
282 upper: upper.clone(),
283 updates,
284 }),
285 ));
286
287 let input_exhausted = upper.is_empty();
288 self.prev_upper = upper;
289 if input_exhausted {
290 self.subscribe_response_buffer = None;
293 }
294 }
295}
296
297impl Drop for SubscribeProtocol {
298 fn drop(&mut self) {
299 if let Some(buffer) = self.subscribe_response_buffer.take() {
300 buffer.borrow_mut().push((
301 self.sink_id,
302 SubscribeResponse::DroppedAt(self.prev_upper.clone()),
303 ));
304 }
305 }
306}