Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can the BackgroundService support a &mut self reference? #465

Open
aniaan opened this issue Nov 11, 2024 · 0 comments
Open

Can the BackgroundService support a &mut self reference? #465

aniaan opened this issue Nov 11, 2024 · 0 comments
Labels
ergonomics Ease of use, developer friendliness

Comments

@aniaan
Copy link

aniaan commented Nov 11, 2024

What is the problem your feature solves, or the need it fulfills?

The current signature of the start method in the BackgroundService trait is as follows.:

#[async_trait]
pub trait BackgroundService {
/// This function is called when the pingora server tries to start all the
/// services. The background service can return at anytime or wait for the
/// `shutdown` signal.
async fn start(&self, mut shutdown: ShutdownWatch);
}

The self parameter is immutable. Currently, I have a function that needs to run in the background and requires &mut self. The scenario is quite simple: it involves consuming from a channel, but because self is immutable, it cannot perform recv. Here’s an example of the code:

#[async_trait]
impl BackgroundService for Observer {
    async fn start(&self, mut shutdown: pingora::server::ShutdownWatch) {
        let mut traces = Vec::with_capacity(self.batch_size);
        let mut interval = tokio::time::interval(self.flush_interval);

        loop {
            tokio::select! {
                _ = interval.tick() => {
                    if !traces.is_empty() {
                        // self.flush(&traces).await;
                        traces.clear();
                    }
                }
                trace = self.rx.recv() => {
                    if let Some(trace) = trace {
                        traces.push(trace);
                        if traces.len() >= self.batch_size {
                            // self.flush(&traces).await;
                            traces.clear();
                        }
                    }
                }
                _ = shutdown.changed() => {
                    if !traces.is_empty() {
                        // self.flush(&traces).await;
                    }
                    break;
                }
            }
        }

        todo!()
    }
}

The following code shows that when the upper method calls start, self is &mut self. However, when it comes to the start method, self becomes &self, and these two signatures are not quite consistent. Is there a specific reason for this? I hope you can help clarify this for me. Thank you very much.

impl<A> Service for GenBackgroundService<A>
where
A: BackgroundService + Send + Sync + 'static,
{
async fn start_service(
&mut self,
#[cfg(unix)] _fds: Option<ListenFds>,
shutdown: ShutdownWatch,
) {
self.task.start(shutdown).await;
}

Describe the solution you'd like

Is it possible to change the method signature from &self to &mut self?

@eaufavor eaufavor added the ergonomics Ease of use, developer friendliness label Nov 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ergonomics Ease of use, developer friendliness
Projects
None yet
Development

No branches or pull requests

2 participants