Skip to main content

sofie_http/
queue.rs

1use sofie_db::{Call, Context, Jobs, Resolve};
2use std::sync::Arc;
3
4use http::Method;
5use serde_json::Value;
6use sofie_core::{Error, Result};
7use sofie_db::worker::JobContext;
8
9use crate::handler::{Endpoint, committed, instrumented};
10use crate::routes::{ActionRoute, RouteRules, View};
11use crate::trace::handler_name;
12use crate::{Area, RequestContext, Routes};
13
14impl<A: Area> Routes<A> {
15    /// Queues `job` with the input and path parameters, which bind its records as an action's.
16    /// It runs as the requester but reaches every record, so an area whose principals own their
17    /// records cannot queue.
18    pub fn queue<Args: 'static, J: Call<JobContext, Args>>(
19        &mut self,
20        path: &str,
21        job: J,
22    ) -> ActionRoute<'_, A> {
23        let endpoint: Endpoint = Arc::new(move |db, matched| {
24            let job = job.clone();
25            instrumented(handler_name::<J>(), matched.route, async move {
26                let mut context = RequestContext::<A>::new(db, matched);
27                let queued = queued(&mut context, job).await?;
28                committed(context.db(), &context.matched, Box::new(queued)).await
29            })
30        });
31        let rules = RouteRules {
32            queues: true,
33            ..RouteRules::default()
34        };
35        ActionRoute::new(self.push(Method::POST, path, endpoint, View::Json, rules))
36    }
37}
38
39async fn queued<A: Area, Args, J: Call<JobContext, Args>>(
40    context: &mut RequestContext<A>,
41    job: J,
42) -> Result<sofie_db::Queued> {
43    let Value::Object(mut payload) = context.input()? else {
44        return Err(Error::BadRequest(
45            "a queued job takes an object of fields".to_owned(),
46        ));
47    };
48    for (name, value) in &context.matched.parameters {
49        payload.insert(name.clone(), Value::String(value.clone()));
50    }
51    Jobs::resolve(context).await?.queue(job, &payload)
52}