brokkr-broker::dal::work_orders
Rust
Data Access Layer for WorkOrder operations.
This module provides functionality to interact with the work_orders, work_order_log, and work_order_targets tables in the database. It includes methods for creating, claiming, completing, and managing work orders through their lifecycle.
Work Order Lifecycle
- Create: Work order is created with status PENDING
- Claim: Agent claims work order, status changes to CLAIMED
- Complete: Agent reports completion, record moves to work_order_log
- On failure with retries remaining: status changes to RETRY_PENDING
- After backoff: status resets to PENDING
Stale Claim Detection
Work orders that have been claimed but not completed within claim_timeout_seconds
are considered stale and can be reclaimed by other agents.
Structs
Section titled “Structs”struct WorkOrdersDAL<'a>
Section titled “struct WorkOrdersDAL<'a>”pub
Data Access Layer for WorkOrder operations.
Fields
Section titled “Fields”| Name | Type | Description |
|---|---|---|
dal |
&'a DAL |
Reference to the main DAL instance. |
Methods
Section titled “Methods”create
Section titled “create”pub
fn create( &self, new_work_order: &NewWorkOrder,) -> Result<WorkOrder, diesel::result::Error>Creates a new work order in the database.
Parameters:
| Name | Type | Description |
|---|---|---|
new_work_order |
&NewWorkOrder |
A reference to the NewWorkOrder struct. |
Returns:
Returns the created WorkOrder on success, or a diesel::result::Error on failure.
Source
pub fn create( &self, new_work_order: &NewWorkOrder, ) -> Result<WorkOrder, diesel::result::Error> { let conn = &mut self.dal.conn()?; let work_order: WorkOrder = diesel::insert_into(work_orders::table) .values(new_work_order) .get_result(conn)?;
// Emit workorder.created event let event_data = serde_json::json!({ "work_order_id": work_order.id, "work_type": work_order.work_type, "status": work_order.status, "created_at": work_order.created_at, }); event_bus::emit_event( self.dal, &BrokkrEvent::new(EVENT_WORKORDER_CREATED, event_data), );
Ok(work_order) }pub
fn get( &self, work_order_id: Uuid,) -> Result<Option<WorkOrder>, diesel::result::Error>Retrieves a work order by its UUID.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order to retrieve. |
Returns:
Returns an Option
Source
pub fn get(&self, work_order_id: Uuid) -> Result<Option<WorkOrder>, diesel::result::Error> { let conn = &mut self.dal.conn()?; work_orders::table .filter(work_orders::id.eq(work_order_id)) .first(conn) .optional() }pub
fn list(&self) -> Result<Vec<WorkOrder>, diesel::result::Error>Lists all work orders from the database.
Returns:
Returns a Vec of all WorkOrders on success, or a diesel::result::Error on failure.
Source
pub fn list(&self) -> Result<Vec<WorkOrder>, diesel::result::Error> { let conn = &mut self.dal.conn()?; work_orders::table .order(work_orders::created_at.desc()) .load::<WorkOrder>(conn) }list_filtered
Section titled “list_filtered”pub
fn list_filtered( &self, status: Option<&str>, work_type: Option<&str>,) -> Result<Vec<WorkOrder>, diesel::result::Error>Lists work orders filtered by status and/or work type.
Parameters:
| Name | Type | Description |
|---|---|---|
status |
Option<&str> |
Optional status filter (PENDING, CLAIMED, RETRY_PENDING). |
work_type |
Option<&str> |
Optional work type filter (e.g., “build”). |
Returns:
Returns a Vec of filtered WorkOrders on success, or a diesel::result::Error on failure.
Source
pub fn list_filtered( &self, status: Option<&str>, work_type: Option<&str>, ) -> Result<Vec<WorkOrder>, diesel::result::Error> { let conn = &mut self.dal.conn()?;
let mut query = work_orders::table.into_boxed();
if let Some(s) = status { query = query.filter(work_orders::status.eq(s)); }
if let Some(wt) = work_type { query = query.filter(work_orders::work_type.eq(wt)); }
query .order(work_orders::created_at.desc()) .load::<WorkOrder>(conn) }delete
Section titled “delete”pub
fn delete( &self, work_order_id: Uuid,) -> Result<usize, diesel::result::Error>Deletes a work order by its UUID (hard delete).
Note: This also deletes associated work_order_targets via CASCADE.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order to delete. |
Returns:
Returns the number of affected rows on success, or a diesel::result::Error on failure.
Source
pub fn delete(&self, work_order_id: Uuid) -> Result<usize, diesel::result::Error> { let conn = &mut self.dal.conn()?; diesel::delete(work_orders::table.filter(work_orders::id.eq(work_order_id))).execute(conn) }list_pending_for_agent
Section titled “list_pending_for_agent”pub
fn list_pending_for_agent( &self, agent_id: Uuid, work_type: Option<&str>,) -> Result<Vec<WorkOrder>, diesel::result::Error>Lists pending work orders that are claimable by a specific agent.
A work order is claimable if:
- Status is PENDING
- At least one of the following conditions is met (OR logic):
- Agent is in the work_order_targets (hard targets)
- Agent has a label matching any of the work order’s labels
- Agent has an annotation matching any of the work order’s annotations
Parameters:
| Name | Type | Description |
|---|---|---|
agent_id |
Uuid |
The UUID of the agent requesting claimable work orders. |
work_type |
Option<&str> |
Optional work type filter. |
Returns:
Returns a Vec of claimable WorkOrders on success, or a diesel::result::Error on failure.
Source
pub fn list_pending_for_agent( &self, agent_id: Uuid, work_type: Option<&str>, ) -> Result<Vec<WorkOrder>, diesel::result::Error> { let conn = &mut self.dal.conn()?;
// Get agent's labels let agent_label_list: Vec<String> = agent_labels::table .filter(agent_labels::agent_id.eq(agent_id)) .select(agent_labels::label) .load::<String>(conn)?;
// Get agent's annotations let agent_annotation_list: Vec<(String, String)> = agent_annotations::table .filter(agent_annotations::agent_id.eq(agent_id)) .select((agent_annotations::key, agent_annotations::value)) .load::<(String, String)>(conn)?;
let mut matching_work_order_ids: HashSet<Uuid> = HashSet::new();
// 1. Get work orders where agent is a hard target let hard_target_ids: Vec<Uuid> = work_order_targets::table .inner_join(work_orders::table) .filter(work_order_targets::agent_id.eq(agent_id)) .filter(work_orders::status.eq(WORK_ORDER_STATUS_PENDING)) .select(work_orders::id) .load::<Uuid>(conn)?;
matching_work_order_ids.extend(hard_target_ids);
// 2. Get work orders with labels matching agent's labels (OR logic) if !agent_label_list.is_empty() { let label_matched_ids: Vec<Uuid> = work_order_labels::table .inner_join(work_orders::table) .filter(work_order_labels::label.eq_any(&agent_label_list)) .filter(work_orders::status.eq(WORK_ORDER_STATUS_PENDING)) .select(work_orders::id) .load::<Uuid>(conn)?;
matching_work_order_ids.extend(label_matched_ids); }
// 3. Get work orders with annotations matching agent's annotations (OR logic) if !agent_annotation_list.is_empty() { for (key, value) in &agent_annotation_list { let annotation_matched_ids: Vec<Uuid> = work_order_annotations::table .inner_join(work_orders::table) .filter(work_order_annotations::key.eq(key)) .filter(work_order_annotations::value.eq(value)) .filter(work_orders::status.eq(WORK_ORDER_STATUS_PENDING)) .select(work_orders::id) .load::<Uuid>(conn)?;
matching_work_order_ids.extend(annotation_matched_ids); } }
if matching_work_order_ids.is_empty() { return Ok(vec![]); }
// Load and filter the matching work orders let ids: Vec<Uuid> = matching_work_order_ids.into_iter().collect();
let mut query = work_orders::table .filter(work_orders::id.eq_any(&ids)) .filter(work_orders::status.eq(WORK_ORDER_STATUS_PENDING)) .into_boxed();
if let Some(wt) = work_type { query = query.filter(work_orders::work_type.eq(wt)); }
query .order(work_orders::created_at.asc()) .load::<WorkOrder>(conn) }claimed_counts_by_agent
Section titled “claimed_counts_by_agent”pub
fn claimed_counts_by_agent( &self) -> Result<Vec<(Uuid, i64,) -> Result<Vec<(Uuid, i64)>, diesel::result::Error>Returns the number of CLAIMED work orders per claiming agent in a single grouped query (no per-agent fan-out).
Counts rows WHERE status='CLAIMED' AND claimed_by IS NOT NULL grouped
by claimed_by. Agents with no claims are absent from the result.
Returns:
Returns a Vec of (agent_id, claimed_count) pairs, or a
diesel::result::Error on failure.
Source
pub fn claimed_counts_by_agent(&self) -> Result<Vec<(Uuid, i64)>, diesel::result::Error> { let conn = &mut self.dal.conn()?; work_orders::table .filter(work_orders::status.eq(WORK_ORDER_STATUS_CLAIMED)) .filter(work_orders::claimed_by.is_not_null()) .group_by(work_orders::claimed_by) .select(( work_orders::claimed_by.assume_not_null(), diesel::dsl::count_star(), )) .load::<(Uuid, i64)>(conn) }pending_counts_by_agent
Section titled “pending_counts_by_agent”pub
fn pending_counts_by_agent( &self) -> Result<Vec<(Uuid, i64,) -> Result<Vec<(Uuid, i64)>, diesel::result::Error>Returns, per agent, the number of distinct PENDING work orders that agent is eligible to claim — computed with a handful of bounded set-based queries rather than calling list_pending_for_agent once per agent.
The matching semantics exactly mirror list_pending_for_agent (the
per-agent ground truth): an agent matches a PENDING work order if ANY of
the following hold (OR logic):
- the agent is a hard target (
work_order_targets), OR - the agent shares a label with the work order, OR
- the agent shares a
(key, value)annotation with the work order.
Each matched (agent_id, work_order_id) pair is de-duplicated before
counting so a work order matched by multiple mechanisms is counted once
per agent.
Returns:
Returns a Vec of (agent_id, pending_count) pairs, or a
diesel::result::Error on failure.
Source
pub fn pending_counts_by_agent(&self) -> Result<Vec<(Uuid, i64)>, diesel::result::Error> { let conn = &mut self.dal.conn()?;
// Accumulate the distinct set of (agent_id, work_order_id) matches. let mut matches: HashSet<(Uuid, Uuid)> = HashSet::new();
// 1. Hard targets: every (agent, pending work order) target pair. let target_pairs: Vec<(Uuid, Uuid)> = work_order_targets::table .inner_join(work_orders::table) .filter(work_orders::status.eq(WORK_ORDER_STATUS_PENDING)) .select((work_order_targets::agent_id, work_orders::id)) .load::<(Uuid, Uuid)>(conn)?; matches.extend(target_pairs);
// 2. Label matches: join agent_labels to work_order_labels on equal // label text, restricted to pending work orders. let label_pairs: Vec<(Uuid, Uuid)> = agent_labels::table .inner_join( work_order_labels::table.on(work_order_labels::label.eq(agent_labels::label)), ) .inner_join(work_orders::table.on(work_orders::id.eq(work_order_labels::work_order_id))) .filter(work_orders::status.eq(WORK_ORDER_STATUS_PENDING)) .select((agent_labels::agent_id, work_orders::id)) .load::<(Uuid, Uuid)>(conn)?; matches.extend(label_pairs);
// 3. Annotation matches: join agent_annotations to // work_order_annotations on equal (key, value), restricted to // pending work orders. let annotation_pairs: Vec<(Uuid, Uuid)> = agent_annotations::table .inner_join( work_order_annotations::table.on(work_order_annotations::key .eq(agent_annotations::key) .and(work_order_annotations::value.eq(agent_annotations::value))), ) .inner_join( work_orders::table.on(work_orders::id.eq(work_order_annotations::work_order_id)), ) .filter(work_orders::status.eq(WORK_ORDER_STATUS_PENDING)) .select((agent_annotations::agent_id, work_orders::id)) .load::<(Uuid, Uuid)>(conn)?; matches.extend(annotation_pairs);
// Aggregate distinct matches into per-agent counts. let mut counts: std::collections::HashMap<Uuid, i64> = std::collections::HashMap::new(); for (agent_id, _work_order_id) in matches { *counts.entry(agent_id).or_insert(0) += 1; }
Ok(counts.into_iter().collect()) }pub
fn claim( &self, work_order_id: Uuid, agent_id: Uuid,) -> Result<WorkOrder, diesel::result::Error>Atomically claims a work order for an agent.
This operation will only succeed if:
- The work order exists
- The work order status is PENDING
- At least one of the following conditions is met (OR logic):
- Agent is in the work_order_targets (hard targets)
- Agent has a label matching any of the work order’s labels
- Agent has an annotation matching any of the work order’s annotations
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order to claim. |
agent_id |
Uuid |
The UUID of the agent claiming the work order. |
Returns:
Returns the updated WorkOrder on success, or a diesel::result::Error on failure. Returns NotFound if the work order doesn’t exist or can’t be claimed.
Source
pub fn claim( &self, work_order_id: Uuid, agent_id: Uuid, ) -> Result<WorkOrder, diesel::result::Error> { let conn = &mut self.dal.conn()?;
// Check if agent is authorized via any targeting mechanism (OR logic) let is_authorized = self.is_agent_authorized_for_work_order(conn, work_order_id, agent_id)?;
if !is_authorized { return Err(diesel::result::Error::NotFound); }
// Atomically update the work order status to CLAIMED let now = Utc::now(); let work_order: WorkOrder = diesel::update( work_orders::table .filter(work_orders::id.eq(work_order_id)) .filter(work_orders::status.eq(WORK_ORDER_STATUS_PENDING)), ) .set(( work_orders::status.eq(WORK_ORDER_STATUS_CLAIMED), work_orders::claimed_by.eq(agent_id), work_orders::claimed_at.eq(now), )) .get_result(conn)?;
// Emit workorder.claimed event let event_data = serde_json::json!({ "work_order_id": work_order.id, "work_type": work_order.work_type, "agent_id": agent_id, "claimed_at": now, }); event_bus::emit_event( self.dal, &BrokkrEvent::new(EVENT_WORKORDER_CLAIMED, event_data), );
Ok(work_order) }release
Section titled “release”pub
fn release( &self, work_order_id: Uuid, agent_id: Uuid,) -> Result<WorkOrder, diesel::result::Error>Releases a claimed work order back to PENDING status.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order to release. |
agent_id |
Uuid |
The UUID of the agent releasing the work order (must match claimed_by). |
Returns:
Returns the updated WorkOrder on success, or a diesel::result::Error on failure.
Source
pub fn release( &self, work_order_id: Uuid, agent_id: Uuid, ) -> Result<WorkOrder, diesel::result::Error> { let conn = &mut self.dal.conn()?;
diesel::update( work_orders::table .filter(work_orders::id.eq(work_order_id)) .filter(work_orders::status.eq(WORK_ORDER_STATUS_CLAIMED)) .filter(work_orders::claimed_by.eq(agent_id)), ) .set(( work_orders::status.eq(WORK_ORDER_STATUS_PENDING), work_orders::claimed_by.eq(None::<Uuid>), work_orders::claimed_at.eq(None::<chrono::DateTime<Utc>>), )) .get_result(conn) }complete_success
Section titled “complete_success”pub
fn complete_success( &self, work_order_id: Uuid, result_message: Option<String>,) -> Result<WorkOrderLog, diesel::result::Error>Completes a work order successfully and moves it to the log.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order to complete. |
result_message |
Option<String> |
Optional result message (e.g., image digest). |
Returns:
Returns the created WorkOrderLog entry on success, or a diesel::result::Error on failure.
Source
pub fn complete_success( &self, work_order_id: Uuid, result_message: Option<String>, ) -> Result<WorkOrderLog, diesel::result::Error> { let conn = &mut self.dal.conn()?;
let log_result: WorkOrderLog = conn.transaction(|conn| { // Get the work order let work_order: WorkOrder = work_orders::table .filter(work_orders::id.eq(work_order_id)) .first(conn)?;
// Create log entry let log_entry = NewWorkOrderLog::from_work_order(&work_order, true, result_message); let log_result: WorkOrderLog = diesel::insert_into(work_order_log::table) .values(&log_entry) .get_result(conn)?;
// Delete work order (cascade deletes targets) diesel::delete(work_orders::table.filter(work_orders::id.eq(work_order_id))) .execute(conn)?;
Ok::<WorkOrderLog, diesel::result::Error>(log_result) })?;
// Emit completion event self.emit_completion_event(&log_result);
Ok(log_result) }complete_failure
Section titled “complete_failure”pub
fn complete_failure( &self, work_order_id: Uuid, error_message: String, retryable: bool,) -> Result<Option<WorkOrderLog>, diesel::result::Error>Completes a work order with failure.
If retryable is true and retries remain, the work order is marked as RETRY_PENDING.
If retryable is false or max retries exceeded, the work order is moved to the log.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order that failed. |
error_message |
String |
The error message describing the failure. |
retryable |
bool |
Whether this failure type can be retried. |
Returns:
Returns either:
Ok(None)if the work order was scheduled for retryOk(Some(WorkOrderLog))if not retryable or max retries exceededErron database error
Source
pub fn complete_failure( &self, work_order_id: Uuid, error_message: String, retryable: bool, ) -> Result<Option<WorkOrderLog>, diesel::result::Error> { let conn = &mut self.dal.conn()?;
let result: Option<WorkOrderLog> = conn.transaction(|conn| { // Get the work order let work_order: WorkOrder = work_orders::table .filter(work_orders::id.eq(work_order_id)) .first(conn)?;
let new_retry_count = work_order.retry_count + 1;
// Move to log immediately if not retryable, or if max retries exceeded if !retryable || new_retry_count > work_order.max_retries { // Move to log let log_entry = NewWorkOrderLog::from_work_order(&work_order, false, Some(error_message)); let log_result: WorkOrderLog = diesel::insert_into(work_order_log::table) .values(&log_entry) .get_result(conn)?;
// Delete work order diesel::delete(work_orders::table.filter(work_orders::id.eq(work_order_id))) .execute(conn)?;
Ok::<Option<WorkOrderLog>, diesel::result::Error>(Some(log_result)) } else { // Schedule retry with exponential backoff let backoff_multiplier = 2_i64.pow(new_retry_count as u32); let backoff_duration = Duration::seconds(work_order.backoff_seconds as i64 * backoff_multiplier); let now = Utc::now(); let next_retry = now + backoff_duration;
diesel::update(work_orders::table.filter(work_orders::id.eq(work_order_id))) .set(( work_orders::status.eq(WORK_ORDER_STATUS_RETRY_PENDING), work_orders::retry_count.eq(new_retry_count), work_orders::next_retry_after.eq(next_retry), work_orders::claimed_by.eq(None::<Uuid>), work_orders::claimed_at.eq(None::<chrono::DateTime<Utc>>), work_orders::last_error.eq(&error_message), work_orders::last_error_at.eq(now), )) .execute(conn)?;
Ok(None) } })?;
// Emit completion event if work order was moved to log if let Some(ref log) = result { self.emit_completion_event(log); }
Ok(result) }process_retry_pending
Section titled “process_retry_pending”pub
fn process_retry_pending(&self) -> Result<usize, diesel::result::Error>Resets RETRY_PENDING work orders to PENDING if their backoff period has elapsed.
This should be called periodically by a background job.
Returns:
Returns the number of work orders reset on success, or a diesel::result::Error on failure.
Source
pub fn process_retry_pending(&self) -> Result<usize, diesel::result::Error> { let conn = &mut self.dal.conn()?; let now = Utc::now();
diesel::update( work_orders::table .filter(work_orders::status.eq(WORK_ORDER_STATUS_RETRY_PENDING)) .filter(work_orders::next_retry_after.le(now)), ) .set(( work_orders::status.eq(WORK_ORDER_STATUS_PENDING), work_orders::next_retry_after.eq(None::<chrono::DateTime<Utc>>), )) .execute(conn) }process_stale_claims
Section titled “process_stale_claims”pub
fn process_stale_claims(&self) -> Result<usize, diesel::result::Error>Resets stale claimed work orders to PENDING.
A claim is stale if: claimed_at + claim_timeout_seconds < NOW()
This should be called periodically by a background job.
Returns:
Returns the number of work orders reset on success, or a diesel::result::Error on failure.
Source
pub fn process_stale_claims(&self) -> Result<usize, diesel::result::Error> { let conn = &mut self.dal.conn()?; let now = Utc::now();
// We need to use raw SQL for this because Diesel doesn't support // arithmetic with columns in WHERE clauses easily diesel::sql_query( "UPDATE work_orders SET status = 'PENDING', claimed_by = NULL, claimed_at = NULL, updated_at = NOW() WHERE status = 'CLAIMED' AND claimed_at + (claim_timeout_seconds || ' seconds')::INTERVAL < $1", ) .bind::<diesel::sql_types::Timestamptz, _>(now) .execute(conn) }add_target
Section titled “add_target”pub
fn add_target( &self, new_target: &NewWorkOrderTarget,) -> Result<WorkOrderTarget, diesel::result::Error>Adds an agent as a target for a work order.
Parameters:
| Name | Type | Description |
|---|---|---|
new_target |
&NewWorkOrderTarget |
The new target to add. |
Returns:
Returns the created WorkOrderTarget on success, or a diesel::result::Error on failure.
Source
pub fn add_target( &self, new_target: &NewWorkOrderTarget, ) -> Result<WorkOrderTarget, diesel::result::Error> { let conn = &mut self.dal.conn()?; diesel::insert_into(work_order_targets::table) .values(new_target) .get_result(conn) }add_targets
Section titled “add_targets”pub
fn add_targets( &self, work_order_id: Uuid, agent_ids: &[Uuid],) -> Result<usize, diesel::result::Error>Adds multiple agents as targets for a work order.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order. |
agent_ids |
&[Uuid] |
A slice of agent UUIDs to add as targets. |
Returns:
Returns the number of targets added on success, or a diesel::result::Error on failure.
Source
pub fn add_targets( &self, work_order_id: Uuid, agent_ids: &[Uuid], ) -> Result<usize, diesel::result::Error> { let conn = &mut self.dal.conn()?;
let targets: Vec<NewWorkOrderTarget> = agent_ids .iter() .filter_map(|&agent_id| NewWorkOrderTarget::new(work_order_id, agent_id).ok()) .collect();
diesel::insert_into(work_order_targets::table) .values(&targets) .execute(conn) }list_targets
Section titled “list_targets”pub
fn list_targets( &self, work_order_id: Uuid,) -> Result<Vec<WorkOrderTarget>, diesel::result::Error>Lists all targets for a work order.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order. |
Returns:
Returns a Vec of WorkOrderTargets on success, or a diesel::result::Error on failure.
Source
pub fn list_targets( &self, work_order_id: Uuid, ) -> Result<Vec<WorkOrderTarget>, diesel::result::Error> { let conn = &mut self.dal.conn()?; work_order_targets::table .filter(work_order_targets::work_order_id.eq(work_order_id)) .load::<WorkOrderTarget>(conn) }remove_target
Section titled “remove_target”pub
fn remove_target( &self, work_order_id: Uuid, agent_id: Uuid,) -> Result<usize, diesel::result::Error>Removes a target from a work order.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order. |
agent_id |
Uuid |
The UUID of the agent to remove. |
Returns:
Returns the number of targets removed on success, or a diesel::result::Error on failure.
Source
pub fn remove_target( &self, work_order_id: Uuid, agent_id: Uuid, ) -> Result<usize, diesel::result::Error> { let conn = &mut self.dal.conn()?; diesel::delete( work_order_targets::table .filter(work_order_targets::work_order_id.eq(work_order_id)) .filter(work_order_targets::agent_id.eq(agent_id)), ) .execute(conn) }get_log
Section titled “get_log”pub
fn get_log( &self, log_id: Uuid,) -> Result<Option<WorkOrderLog>, diesel::result::Error>Retrieves a work order log entry by its UUID.
Parameters:
| Name | Type | Description |
|---|---|---|
log_id |
Uuid |
The UUID of the log entry to retrieve. |
Returns:
Returns an Option
Source
pub fn get_log(&self, log_id: Uuid) -> Result<Option<WorkOrderLog>, diesel::result::Error> { let conn = &mut self.dal.conn()?; work_order_log::table .filter(work_order_log::id.eq(log_id)) .first(conn) .optional() }list_log
Section titled “list_log”pub
fn list_log( &self, work_type: Option<&str>, success: Option<bool>, agent_id: Option<Uuid>, limit: Option<i64>,) -> Result<Vec<WorkOrderLog>, diesel::result::Error>Lists work order log entries with optional filtering.
Parameters:
| Name | Type | Description |
|---|---|---|
work_type |
Option<&str> |
Optional work type filter. |
success |
Option<bool> |
Optional success status filter. |
agent_id |
Option<Uuid> |
Optional agent ID filter. |
limit |
Option<i64> |
Optional limit on number of results. |
Returns:
Returns a Vec of WorkOrderLog entries on success, or a diesel::result::Error on failure.
Source
pub fn list_log( &self, work_type: Option<&str>, success: Option<bool>, agent_id: Option<Uuid>, limit: Option<i64>, ) -> Result<Vec<WorkOrderLog>, diesel::result::Error> { let conn = &mut self.dal.conn()?;
let mut query = work_order_log::table.into_boxed();
if let Some(wt) = work_type { query = query.filter(work_order_log::work_type.eq(wt)); }
if let Some(s) = success { query = query.filter(work_order_log::success.eq(s)); }
if let Some(aid) = agent_id { query = query.filter(work_order_log::claimed_by.eq(aid)); }
query = query.order(work_order_log::completed_at.desc());
if let Some(l) = limit { query = query.limit(l); }
query.load::<WorkOrderLog>(conn) }add_label
Section titled “add_label”pub
fn add_label( &self, new_label: &NewWorkOrderLabel,) -> Result<WorkOrderLabel, diesel::result::Error>Adds a label to a work order.
Parameters:
| Name | Type | Description |
|---|---|---|
new_label |
&NewWorkOrderLabel |
The new label to add. |
Returns:
Returns the created WorkOrderLabel on success, or a diesel::result::Error on failure.
Source
pub fn add_label( &self, new_label: &NewWorkOrderLabel, ) -> Result<WorkOrderLabel, diesel::result::Error> { let conn = &mut self.dal.conn()?; diesel::insert_into(work_order_labels::table) .values(new_label) .get_result(conn) }add_labels
Section titled “add_labels”pub
fn add_labels( &self, work_order_id: Uuid, labels: &[String],) -> Result<usize, diesel::result::Error>Adds multiple labels to a work order.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order. |
labels |
&[String] |
A slice of label strings to add. |
Returns:
Returns the number of labels added on success, or a diesel::result::Error on failure.
Source
pub fn add_labels( &self, work_order_id: Uuid, labels: &[String], ) -> Result<usize, diesel::result::Error> { let conn = &mut self.dal.conn()?;
let new_labels: Vec<NewWorkOrderLabel> = labels .iter() .filter_map(|label| NewWorkOrderLabel::new(work_order_id, label.clone()).ok()) .collect();
diesel::insert_into(work_order_labels::table) .values(&new_labels) .execute(conn) }list_labels
Section titled “list_labels”pub
fn list_labels( &self, work_order_id: Uuid,) -> Result<Vec<WorkOrderLabel>, diesel::result::Error>Lists all labels for a work order.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order. |
Returns:
Returns a Vec of WorkOrderLabels on success, or a diesel::result::Error on failure.
Source
pub fn list_labels( &self, work_order_id: Uuid, ) -> Result<Vec<WorkOrderLabel>, diesel::result::Error> { let conn = &mut self.dal.conn()?; work_order_labels::table .filter(work_order_labels::work_order_id.eq(work_order_id)) .load::<WorkOrderLabel>(conn) }remove_label
Section titled “remove_label”pub
fn remove_label( &self, work_order_id: Uuid, label: &str,) -> Result<usize, diesel::result::Error>Removes a label from a work order.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order. |
label |
&str |
The label to remove. |
Returns:
Returns the number of labels removed on success, or a diesel::result::Error on failure.
Source
pub fn remove_label( &self, work_order_id: Uuid, label: &str, ) -> Result<usize, diesel::result::Error> { let conn = &mut self.dal.conn()?; diesel::delete( work_order_labels::table .filter(work_order_labels::work_order_id.eq(work_order_id)) .filter(work_order_labels::label.eq(label)), ) .execute(conn) }add_annotation
Section titled “add_annotation”pub
fn add_annotation( &self, new_annotation: &NewWorkOrderAnnotation,) -> Result<WorkOrderAnnotation, diesel::result::Error>Adds an annotation to a work order.
Parameters:
| Name | Type | Description |
|---|---|---|
new_annotation |
&NewWorkOrderAnnotation |
The new annotation to add. |
Returns:
Returns the created WorkOrderAnnotation on success, or a diesel::result::Error on failure.
Source
pub fn add_annotation( &self, new_annotation: &NewWorkOrderAnnotation, ) -> Result<WorkOrderAnnotation, diesel::result::Error> { let conn = &mut self.dal.conn()?; diesel::insert_into(work_order_annotations::table) .values(new_annotation) .get_result(conn) }add_annotations
Section titled “add_annotations”pub
fn add_annotations( &self, work_order_id: Uuid, annotations: &std::collections::HashMap<String, String>,) -> Result<usize, diesel::result::Error>Adds multiple annotations to a work order.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order. |
annotations |
&std::collections::HashMap<String, String> |
A HashMap of key-value pairs to add. |
Returns:
Returns the number of annotations added on success, or a diesel::result::Error on failure.
Source
pub fn add_annotations( &self, work_order_id: Uuid, annotations: &std::collections::HashMap<String, String>, ) -> Result<usize, diesel::result::Error> { let conn = &mut self.dal.conn()?;
let new_annotations: Vec<NewWorkOrderAnnotation> = annotations .iter() .filter_map(|(key, value)| { NewWorkOrderAnnotation::new(work_order_id, key.clone(), value.clone()).ok() }) .collect();
diesel::insert_into(work_order_annotations::table) .values(&new_annotations) .execute(conn) }list_annotations
Section titled “list_annotations”pub
fn list_annotations( &self, work_order_id: Uuid,) -> Result<Vec<WorkOrderAnnotation>, diesel::result::Error>Lists all annotations for a work order.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order. |
Returns:
Returns a Vec of WorkOrderAnnotations on success, or a diesel::result::Error on failure.
Source
pub fn list_annotations( &self, work_order_id: Uuid, ) -> Result<Vec<WorkOrderAnnotation>, diesel::result::Error> { let conn = &mut self.dal.conn()?; work_order_annotations::table .filter(work_order_annotations::work_order_id.eq(work_order_id)) .load::<WorkOrderAnnotation>(conn) }remove_annotation
Section titled “remove_annotation”pub
fn remove_annotation( &self, work_order_id: Uuid, key: &str, value: &str,) -> Result<usize, diesel::result::Error>Removes an annotation from a work order.
Parameters:
| Name | Type | Description |
|---|---|---|
work_order_id |
Uuid |
The UUID of the work order. |
key |
&str |
The annotation key. |
value |
&str |
The annotation value. |
Returns:
Returns the number of annotations removed on success, or a diesel::result::Error on failure.
Source
pub fn remove_annotation( &self, work_order_id: Uuid, key: &str, value: &str, ) -> Result<usize, diesel::result::Error> { let conn = &mut self.dal.conn()?; diesel::delete( work_order_annotations::table .filter(work_order_annotations::work_order_id.eq(work_order_id)) .filter(work_order_annotations::key.eq(key)) .filter(work_order_annotations::value.eq(value)), ) .execute(conn) }