use super::*;
pub struct Promotion<'a> {
pub origin: &'a str,
pub sender: &'a str,
pub session: &'a str,
pub title: &'a str,
pub workflow_key: &'a str,
pub workflow_title: &'a str,
}
impl Store {
pub fn promote(&self, id: &str, by: &Promotion) -> Result<Doc> {
let mut conn = self.conn.lock().unwrap();
let tx = conn.transaction()?;
let (project_id, source_path): (i64, Option<String>) = tx.query_row(
"SELECT project_id, source_path FROM docs WHERE id = ?1",
params![id],
|r| Ok((r.get(0)?, r.get(1)?)),
)?;
tx.execute(
"INSERT INTO workflows(project_id, key, title, created_at) VALUES(?1, ?2, ?3, ?4)
ON CONFLICT(project_id, key) DO NOTHING",
params![project_id, by.workflow_key, by.workflow_title, now()],
)?;
tx.execute(
"UPDATE docs SET unread = 1, origin = ?2, title = ?3, received_at = ?4,
sender = CASE WHEN ?5 = '' THEN sender ELSE ?5 END,
session = CASE WHEN ?6 = '' THEN session ELSE ?6 END,
workflow_id = (SELECT id FROM workflows WHERE project_id = ?7 AND key = ?8)
WHERE id = ?1",
params![
id,
by.origin,
by.title,
now(),
by.sender,
by.session,
project_id,
by.workflow_key
],
)?;
tx.execute(
"UPDATE docs_fts SET title = ?2 WHERE rowid = (SELECT rowid FROM docs WHERE id = ?1)",
params![id, by.title],
)?;
if let Some(sp) = &source_path {
rehead(&tx, project_id, sp)?;
}
tx.commit()?;
drop(conn);
self.get(id)?.context("promoted document vanished")
}
pub fn named_workflow(
&self,
project_root: &str,
session: &str,
) -> Result<Option<(String, String)>> {
if session.trim().is_empty() {
return Ok(None);
}
let conn = self.conn.lock().unwrap();
conn.query_row(
"SELECT w.key, w.title FROM live_docs d
JOIN projects p ON p.id = d.project_id JOIN workflows w ON w.id = d.workflow_id
WHERE p.root = ?1 AND d.session = ?2 AND d.origin = 'mcp' AND w.key != LOWER(?2)
ORDER BY d.received_at DESC, d.rowid DESC LIMIT 1",
params![project_root, session],
|r| Ok((r.get(0)?, r.get(1)?)),
)
.optional()
.map_err(Into::into)
}
}