Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

45 linesCodeBlameRaw
1//! A workspace's sequence of numbers (`work_counters`), which its work
2//! items and its repositories' new pull requests share.
3
4use worker::Result;
5use worker::wasm_bindgen::JsValue;
6
7use crate::Work;
8use crate::rows::{NumberRow, ValueRow};
9
10/// The next number of workspace `?1`'s sequence, taken in one statement so
11/// two openings never get the same one. A pull request of repository `?2`
12/// never takes a number one of that repository's has (a repository moved
13/// in from another workspace brings its own), and a workspace's first
14/// number comes after every number its repositories used before work
15/// items moved to the workspace.
16pub(crate) const NEXT_NUMBER: &str = "INSERT INTO work_counters (workspace, last)
17 SELECT ?1, MAX(COALESCE(MAX(c.last), 0), COALESCE((SELECT MAX(number) FROM pulls WHERE repo_id = ?2), 0)) + 1
18 FROM counters c
19 WHERE c.repo_id = ?2 OR c.repo_id IN (SELECT repo_id FROM repo_workspaces WHERE workspace = ?1)
20 ON CONFLICT (workspace) DO UPDATE SET last = MAX(work_counters.last + 1, excluded.last)
21 RETURNING last AS n";
22
23impl Work {
24 /// The next number of `workspace`'s sequence, for a work item, or for
25 /// a pull request of `repo_id` ([`NEXT_NUMBER`]).
26 pub(super) async fn next_number(&self, workspace: &str, repo_id: Option<&str>) -> Result<u32> {
27 let row = self
28 .db
29 .prepare(NEXT_NUMBER)
30 .bind(&[workspace.to_lowercase().into(), repo_id.map_or(JsValue::NULL, JsValue::from)])?
31 .first::<NumberRow>(None)
32 .await?;
33 row.map(|row| row.n).ok_or_else(|| worker::Error::RustError("no number was assigned".into()))
34 }
35
36 /// Whether the job that moved issues into work items is done.
37 pub(super) async fn items_moved(&self) -> Result<bool> {
38 Ok(self
39 .db
40 .prepare("SELECT done_at AS value FROM work_jobs WHERE name = 'work_items' AND done_at IS NOT NULL")
41 .first::<ValueRow>(None)
42 .await?
43 .is_some())
44 }
45}