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 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}