apalis_core/backend/ext/
wake_on_push.rs1use std::{
2 pin::Pin,
3 task::{Context, Poll, Waker},
4};
5
6use futures_sink::Sink;
7use futures_util::SinkExt;
8
9use crate::{backend::*, task::Task, worker::context::WorkerContext};
10
11#[derive(Debug, Clone)]
26pub struct WakeOnPush<B> {
27 pub(super) backend: B,
28 pub(super) waker: Option<Waker>,
29}
30
31impl<B> WakeOnPush<B> {
32 pub fn new(backend: B) -> Self {
37 Self {
38 backend,
39 waker: None,
40 }
41 }
42}
43
44impl<B> Backend for WakeOnPush<B>
45where
46 B: Backend,
47{
48 type Task = B::Task;
49 type Error = B::Error;
50
51 fn poll_ready(
52 &mut self,
53 cx: &mut Context<'_>,
54 worker: &WorkerContext,
55 ) -> Poll<Result<(), Self::Error>> {
56 self.backend.poll_ready(cx, worker)
57 }
58
59 fn poll_next(
60 &mut self,
61 cx: &mut Context<'_>,
62 worker: &WorkerContext,
63 ) -> Poll<Option<Result<Self::Task, Self::Error>>> {
64 if self.waker.as_ref().is_none_or(|w| !w.will_wake(cx.waker())) {
65 self.waker = Some(cx.waker().clone());
66 }
67 self.backend.poll_next(cx, worker)
68 }
69
70 fn poll_close(
71 &mut self,
72 cx: &mut Context<'_>,
73 worker: &WorkerContext,
74 ) -> Poll<Result<(), Self::Error>> {
75 self.backend.poll_close(cx, worker)
76 }
77}
78
79impl<B, T, Err> Sink<T> for WakeOnPush<B>
80where
81 B: Sink<T, Error = Err> + Unpin,
82{
83 type Error = Err;
84 fn start_send(self: Pin<&mut Self>, item: T) -> Result<(), Self::Error> {
87 let this = self.get_mut();
88 this.backend.start_send_unpin(item).map(|_| {
89 if let Some(s) = this.waker.as_ref() {
90 s.wake_by_ref()
91 }
92 })
93 }
94 fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
95 self.get_mut().backend.poll_ready_unpin(cx)
96 }
97 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
98 self.get_mut().backend.poll_flush_unpin(cx)
99 }
100 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
101 self.get_mut().backend.poll_close_unpin(cx)
102 }
103}
104
105delegate_config!(WakeOnPush<B>, backend);
106
107delegate_codec!(WakeOnPush<B>, backend);
108
109delegate_deref!(WakeOnPush<B>, backend);
110
111delegate_expose!(
112 impl<B> for WakeOnPush<B>
113 where {
114 B: Send + Sync,
115 }
116 => backend
117);