Add the table of pending approvals
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
//! The pending-approval table: whoever takes an entry out answers it, and everyone else finds it
|
||||
//! gone. In memory only.
|
||||
|
||||
use crate::policy::{Ask, Decision};
|
||||
use proto::{DenyReason, PendingApproval, Timestamp};
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||
use std::sync::{Mutex, MutexGuard};
|
||||
|
||||
/// What the waiting thread is told. Boxed: clippy's `large_enum_variant` rejects it unboxed.
|
||||
#[derive(Debug)]
|
||||
pub enum Verdict {
|
||||
Run(Box<Decision>),
|
||||
Denied(DenyReason),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Entry {
|
||||
pub info: PendingApproval,
|
||||
pub ask: Ask,
|
||||
pub reply: Sender<Verdict>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Table {
|
||||
entries: Mutex<BTreeMap<u64, Entry>>,
|
||||
}
|
||||
|
||||
impl Table {
|
||||
pub fn new() -> Table {
|
||||
Table {
|
||||
entries: Mutex::new(BTreeMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn lock(&self) -> MutexGuard<'_, BTreeMap<u64, Entry>> {
|
||||
self.entries
|
||||
.lock()
|
||||
.unwrap_or_else(|poisoned| poisoned.into_inner())
|
||||
}
|
||||
|
||||
pub fn insert(&self, info: PendingApproval, ask: Ask) -> Receiver<Verdict> {
|
||||
let (sender, receiver) = channel();
|
||||
self.lock().insert(
|
||||
info.approval,
|
||||
Entry {
|
||||
info,
|
||||
ask,
|
||||
reply: sender,
|
||||
},
|
||||
);
|
||||
receiver
|
||||
}
|
||||
|
||||
pub fn take(&self, id: u64) -> Option<Entry> {
|
||||
self.lock().remove(&id)
|
||||
}
|
||||
|
||||
pub fn take_expired(&self, now: Timestamp) -> Vec<Entry> {
|
||||
// One lock: taking it once per id would let an approve slip in between.
|
||||
let mut entries = self.lock();
|
||||
let ids: Vec<u64> = entries
|
||||
.values()
|
||||
.filter(|entry| now >= entry.info.expires)
|
||||
.map(|entry| entry.info.approval)
|
||||
.collect();
|
||||
ids.iter().filter_map(|id| entries.remove(id)).collect()
|
||||
}
|
||||
|
||||
pub fn list(&self) -> Vec<PendingApproval> {
|
||||
self.lock()
|
||||
.values()
|
||||
.map(|entry| entry.info.clone())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
//! The broker: the only role that holds authority.
|
||||
|
||||
pub mod approvals;
|
||||
pub mod args;
|
||||
pub mod audit;
|
||||
pub mod config;
|
||||
|
||||
Reference in New Issue
Block a user