pingora_core/services/
background.rs

1// Copyright 2024 Cloudflare, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! The background service
16//!
17//! A [BackgroundService] can be run as part of a Pingora application to add supporting logic that
18//! exists outside of the request/response lifecycle.
19//! Examples might include service discovery (load balancing) and background updates such as
20//! push-style metrics.
21
22use async_trait::async_trait;
23use std::sync::Arc;
24
25use super::Service;
26#[cfg(unix)]
27use crate::server::ListenFds;
28use crate::server::ShutdownWatch;
29
30/// The background service interface
31#[async_trait]
32pub trait BackgroundService {
33    /// This function is called when the pingora server tries to start all the
34    /// services. The background service can return at anytime or wait for the
35    /// `shutdown` signal.
36    async fn start(&self, mut shutdown: ShutdownWatch);
37}
38
39/// A generic type of background service
40pub struct GenBackgroundService<A> {
41    // Name of the service
42    name: String,
43    // Task the service will execute
44    task: Arc<A>,
45    /// The number of threads. Default is 1
46    pub threads: Option<usize>,
47}
48
49impl<A> GenBackgroundService<A> {
50    /// Generates a background service that can run in the pingora runtime
51    pub fn new(name: String, task: Arc<A>) -> Self {
52        Self {
53            name,
54            task,
55            threads: Some(1),
56        }
57    }
58
59    /// Return the task behind [Arc] to be shared other logic.
60    pub fn task(&self) -> Arc<A> {
61        self.task.clone()
62    }
63}
64
65#[async_trait]
66impl<A> Service for GenBackgroundService<A>
67where
68    A: BackgroundService + Send + Sync + 'static,
69{
70    async fn start_service(
71        &mut self,
72        #[cfg(unix)] _fds: Option<ListenFds>,
73        shutdown: ShutdownWatch,
74    ) {
75        self.task.start(shutdown).await;
76    }
77
78    fn name(&self) -> &str {
79        &self.name
80    }
81
82    fn threads(&self) -> Option<usize> {
83        self.threads
84    }
85}
86
87// Helper function to create a background service with a human readable name
88pub fn background_service<SV>(name: &str, task: SV) -> GenBackgroundService<SV> {
89    GenBackgroundService::new(format!("BG {name}"), Arc::new(task))
90}