pub struct GoalStore { /* private fields */ }Expand description
Persistence layer for long-horizon goals.
Thin wrapper around DbPool. All methods are async and return typed errors.
§Invariants
- At most one row with
status = 'active'may exist at any time (enforced by theidx_zeph_goals_single_activepartial unique index + transactionalcreate). - Stale transitions (wrong
expected_updated_at) returnGoalError::StaleUpdate.
§TODO(critic): cross-process goal cache invalidation; not handled in v1
Implementations§
Source§impl GoalStore
impl GoalStore
Sourcepub async fn create(
&self,
text: &str,
token_budget: Option<u64>,
max_chars: usize,
) -> Result<Goal, GoalError>
pub async fn create( &self, text: &str, token_budget: Option<u64>, max_chars: usize, ) -> Result<Goal, GoalError>
Create a new goal, atomically pausing any existing Active goal in the same transaction.
Uses BEGIN IMMEDIATE on SQLite / BEGIN + SELECT FOR UPDATE on Postgres to prevent
a race between two concurrent /goal create calls.
§Errors
Returns GoalError::TextTooLong when text exceeds max_chars.
Returns GoalError::Db on database failure.
Sourcepub async fn list(&self, limit: u32) -> Result<Vec<Goal>, GoalError>
pub async fn list(&self, limit: u32) -> Result<Vec<Goal>, GoalError>
Return up to limit goals ordered by created_at DESC.
§Errors
Returns GoalError::Db on database failure.
Sourcepub async fn transition(
&self,
id: &str,
to: GoalStatus,
expected_updated_at: DateTime<Utc>,
) -> Result<Goal, GoalError>
pub async fn transition( &self, id: &str, to: GoalStatus, expected_updated_at: DateTime<Utc>, ) -> Result<Goal, GoalError>
Attempt a CAS-guarded FSM transition.
Returns GoalError::StaleUpdate if the goal was concurrently modified (i.e. the
stored updated_at does not match expected_updated_at). The caller should refetch
and report the current state without surfacing an error to the user.
Returns GoalError::InvalidTransition for non-FSM-allowed transitions.
§Errors
Returns GoalError::NotFound, GoalError::InvalidTransition,
GoalError::StaleUpdate, or GoalError::Db.
Sourcepub async fn record_turn(
&self,
id: &str,
turn_tokens: u64,
) -> Result<Goal, GoalError>
pub async fn record_turn( &self, id: &str, turn_tokens: u64, ) -> Result<Goal, GoalError>
Increment turns_used by 1 and tokens_used by turn_tokens.
Called once per turn by crate::goal::GoalAccounting::on_turn_complete. Returns the updated goal.
§Errors
Returns GoalError::Db on database failure.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for GoalStore
impl !RefUnwindSafe for GoalStore
impl Send for GoalStore
impl Sync for GoalStore
impl Unpin for GoalStore
impl UnsafeUnpin for GoalStore
impl !UnwindSafe for GoalStore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request