apalis_core/backend/ext/
interleave.rs1use std::{
2 pin::Pin,
3 task::{Context, Poll},
4};
5
6use futures_core::Stream;
7use futures_sink::Sink;
8use futures_util::SinkExt;
9
10use crate::{backend::*, task::Task, worker::context::WorkerContext};
11
12#[derive(Debug, Clone)]
22pub struct Interleave<B, S> {
23 pub(super) backend: B,
24 pub(super) stream: S,
25 pub(super) stream_done: bool,
27}
28
29impl<B, S> Interleave<B, S> {
30 pub fn new(backend: B, stream: S) -> Self {
36 Self {
37 backend,
38 stream,
39 stream_done: false,
40 }
41 }
42}
43
44impl<B, S> Backend for Interleave<B, S>
45where
46 B: Backend,
47 S: Stream<Item = Result<B::Task, B::Error>> + Unpin,
48{
49 type Task = B::Task;
50 type Error = B::Error;
51
52 fn poll_ready(
53 &mut self,
54 cx: &mut Context<'_>,
55 worker: &WorkerContext,
56 ) -> Poll<Result<(), Self::Error>> {
57 self.backend.poll_ready(cx, worker)
58 }
59
60 fn poll_next(
61 &mut self,
62 cx: &mut Context<'_>,
63 worker: &WorkerContext,
64 ) -> Poll<Option<Result<Self::Task, Self::Error>>> {
65 if !self.stream_done {
66 match Pin::new(&mut self.stream).poll_next(cx) {
67 Poll::Ready(Some(item)) => return Poll::Ready(Some(item)),
68 Poll::Ready(None) => {
69 self.stream_done = true;
70 }
71 Poll::Pending => {}
72 }
73 }
74
75 self.backend.poll_next(cx, worker)
76 }
77
78 fn poll_close(
79 &mut self,
80 cx: &mut Context<'_>,
81 worker: &WorkerContext,
82 ) -> Poll<Result<(), Self::Error>> {
83 self.backend.poll_close(cx, worker)
84 }
85}
86
87delegate_sink!(Interleave<B, S>, backend);
88
89delegate_deref!(Interleave<B, S>, backend);
90
91delegate_config!(Interleave<B, S>, backend);
92
93delegate_codec!(Interleave<B, S>, backend);
94
95delegate_expose!(
96 impl<B, S> for Interleave<B, S>
97 where {
98 B: Send + Sync,
99 S: Stream<Item = Result<B::Task, B::Error>> + Send + Sync + Unpin,
100 }
101 => backend
102);