Skip to main content

lfsx_server/
state.rs

1use std::sync::Arc;
2
3use tokio::sync::Semaphore;
4
5use crate::auth::Authorizer;
6use crate::config::Config;
7use crate::locks::LockStore;
8use crate::metrics::Metrics;
9use crate::storage::Store;
10
11pub struct AppState {
12    pub store: Store,
13    pub locks: LockStore,
14    pub config: Config,
15    pub authorizer: Authorizer,
16    pub forges: std::collections::HashMap<String, Authorizer>,
17    pub metrics: Metrics,
18    // None when the cap is configured off. A permit is held for as long as a
19    // transfer keeps bytes moving, which for a download means as long as the
20    // client keeps reading the body, so the permit travels with the stream.
21    pub transfers: Option<Arc<Semaphore>>,
22    pub started: std::time::Instant,
23    pub session_key: tokio::sync::OnceCell<Vec<u8>>,
24}
25
26impl AppState {
27    pub fn authorizer_for(
28        &self,
29        ns: &crate::namespace::Namespace,
30    ) -> Result<&Authorizer, crate::error::Error> {
31        match ns.forge() {
32            None => Ok(&self.authorizer),
33            Some(forge) => self.forges.get(forge).ok_or(crate::error::Error::NotServed),
34        }
35    }
36
37    // A permit, or the refusal that tells the client when to come back. Taken
38    // without waiting: a saturated server queueing acceptances would hold the
39    // connection open for the privilege of being slow later, and an immediate
40    // answer with Retry-After lets the client spend the wait on its side.
41    pub fn transfer_permit(
42        &self,
43    ) -> Result<Option<tokio::sync::OwnedSemaphorePermit>, crate::error::Error> {
44        match &self.transfers {
45            None => Ok(None),
46            Some(transfers) => match transfers.clone().try_acquire_owned() {
47                Ok(permit) => Ok(Some(permit)),
48                Err(_) => Err(crate::error::Error::TransfersSaturated { retry_after: 5 }),
49            },
50        }
51    }
52}
53
54pub type Shared = Arc<AppState>;