ai_crew_sync/tools/
locks.rs1use rmcp::{
2 ErrorData, Json, handler::server::wrapper::Parameters, service::RequestContext, tool,
3 tool_router,
4};
5use schemars::JsonSchema;
6use serde::Deserialize;
7
8use super::{Bus, auth_of};
9use crate::{
10 model::{Ack, LockList, LockResult},
11 store::locks,
12};
13
14#[derive(Debug, Deserialize, JsonSchema)]
15pub struct AcquireLockArgs {
16 pub name: String,
19 #[serde(default)]
22 pub ttl_seconds: Option<i64>,
23 #[serde(default)]
25 pub purpose: Option<String>,
26}
27
28#[derive(Debug, Deserialize, JsonSchema)]
29pub struct LockNameArgs {
30 pub name: String,
32}
33
34#[tool_router(router = locks_router, vis = "pub")]
35impl Bus {
36 #[tool(
37 description = "Take an advisory lock on a shared resource (a deploy target, a schema, \
38 a file) before touching it. Returns acquired=false with the holder's name \
39 if someone else has it — in that case wait_for_updates will wake you when \
40 it frees. Locks expire on their own, so a crashed agent cannot jam the \
41 team. Re-acquiring your own lock extends it."
42 )]
43 async fn acquire_lock(
44 &self,
45 ctx: RequestContext<rmcp::RoleServer>,
46 Parameters(args): Parameters<AcquireLockArgs>,
47 ) -> Result<Json<LockResult>, ErrorData> {
48 let auth = auth_of(&ctx)?;
49 Ok(Json(
50 locks::acquire_lock(&self.db, &auth, &args.name, args.ttl_seconds, args.purpose)
51 .await?,
52 ))
53 }
54
55 #[tool(
56 description = "Release a lock you hold, waking anyone waiting on it. Releasing a lock \
57 you do not hold is an error."
58 )]
59 async fn release_lock(
60 &self,
61 ctx: RequestContext<rmcp::RoleServer>,
62 Parameters(args): Parameters<LockNameArgs>,
63 ) -> Result<Json<Ack>, ErrorData> {
64 let auth = auth_of(&ctx)?;
65 Ok(Json(
66 locks::release_lock(&self.db, &auth, &args.name).await?,
67 ))
68 }
69
70 #[tool(description = "List the team's currently held locks: who holds what, why, until when.")]
71 async fn list_locks(
72 &self,
73 ctx: RequestContext<rmcp::RoleServer>,
74 ) -> Result<Json<LockList>, ErrorData> {
75 let auth = auth_of(&ctx)?;
76 Ok(Json(locks::list_locks(&self.db, &auth).await?))
77 }
78}