pub struct PgExperimentChangeRepository { /* private fields */ }Expand description
The generated repository.
Implementations§
Source§impl PgExperimentChangeRepository
impl PgExperimentChangeRepository
Sourcepub fn from_shard(db: &ShardedDb) -> Self
pub fn from_shard(db: &ShardedDb) -> Self
Construct this repository from a ShardedDb
extractor, preserving the full request instrumentation — statement
timeout, slow-query threshold, and route metric label — from the
shard context:
#[post("/bookmarks")]
async fn create(db: ShardedDb, Json(body): Json<Body>) -> AutumnResult<Json<Bookmark>> {
let repo = BookmarkRepository::from_shard(&db);
// repo carries the same timeout / slow-query / route label as `db`
let bookmark = repo.save(&body.into()).await?;
Ok(Json(bookmark))
}Read-only methods route to the shard’s read replica when one is configured and healthy (honoring the shard’s replica_fallback policy); mutating methods always use the shard’s primary. Pin a single call chain to the primary with on_primary.
Use this constructor as the standard way to build a repository on
a shard; prefer with_pool_untracked
only when you intentionally want to bypass request instrumentation.
Sourcepub fn with_pool_untracked(pool: Pool<RuntimeConnection>) -> Self
pub fn with_pool_untracked(pool: Pool<RuntimeConnection>) -> Self
Construct this repository over an explicit pool, bypassing request instrumentation.
Statement timeout, slow-query threshold, and route metric labels
are reset to framework defaults (no timeout, 500 ms threshold,
no route label). Prefer from_shard when
you have a ShardedDb
available; use this constructor only when you need an explicit
pool without any request context:
let repo = BookmarkRepository::with_pool_untracked(pool.clone());Sourcepub async fn recompute_counter_caches(&self) -> AutumnResult<usize>
pub async fn recompute_counter_caches(&self) -> AutumnResult<usize>
Recompute every counter cache this model maintains, for all parent rows, from the source of truth (#1325).
Idempotent: running it twice leaves the same values. Returns the number of parent rows updated, summed across every counter-cached association (0 when the model declares none).
§Errors
Propagates any database error from the recompute UPDATEs.
Sourcepub async fn recompute_counter_caches_for(
&self,
parent_id: i64,
) -> AutumnResult<usize>
pub async fn recompute_counter_caches_for( &self, parent_id: i64, ) -> AutumnResult<usize>
Recompute every counter cache this model maintains for a single parent row (#1325), leaving every other parent untouched.
§Errors
Propagates any database error from the recompute UPDATEs.
Sourcepub fn on_primary(&self) -> Self
pub fn on_primary(&self) -> Self
Returns a clone of this repository whose generated read methods are pinned to the primary pool for the rest of the call chain — the read-your-writes escape hatch (#971).
Use immediately after a write when replication lag would make a replica read stale:
let created = repo.save(&new).await?;
let fresh = repo.on_primary().find_by_id(created.id).await?;Mutating methods are unaffected — they always run on the primary.
Sourcepub fn find_in_batches(&self, batch_size: usize) -> FindInBatches<'_, Self>
pub fn find_in_batches(&self, batch_size: usize) -> FindInBatches<'_, Self>
Iterate the whole table in bounded-memory chunks of at most
batch_size rows, using a primary-key keyset cursor (not
LIMIT/OFFSET), so deep iteration stays flat and is stable under
concurrent inserts of rows ordered after the current position.
Soft-delete filtering, tenant scoping and read routing match
find_all. Drive the returned handle with next_batch() in a
while let loop; drop each chunk before requesting the next to hold
at most batch_size models at a time.
Iteration ends at the first short batch; rows inserted after that
point require a new iteration. Errors are retryable: the cursor
only advances on success, so calling next_batch() again after an
Err retries the same batch (Ok(None) always means completion).
A batch_size of 0 yields an error on every next_batch().
let mut batches = repo.find_in_batches(1_000);
while let Some(chunk) = batches.next_batch().await? {
repo.upsert_many(&recompute(chunk)).await?;
}(upsert_many is not generated on repositories with hooks
configured; use per-row update there.)
Sourcepub fn find_each(&self, batch_size: usize) -> FindEach<'_, Self>
pub fn find_each(&self, batch_size: usize) -> FindEach<'_, Self>
Iterate the whole table one model at a time while still fetching in
bounded batch_size chunks — a convenience over
find_in_batches.
let mut each = repo.find_each(500);
while let Some(row) = each.next().await? {
repo.update(row.id, &patch).await?;
}Sourcepub fn count_grouped_by_experiment<'__agg>(
&'__agg self,
) -> GroupedAggregate<'__agg, String, i64>
pub fn count_grouped_by_experiment<'__agg>( &'__agg self, ) -> GroupedAggregate<'__agg, String, i64>
Grouped aggregate count_grouped_by_experiment → lazy GroupedAggregate<'_, K, V> builder (issue #1364).
Chain .order_by_aggregate_desc()/.limit(n) for top-N, .filter_eq(..)/.filter_range(lo, hi) to scope before grouping, or .bucket(DateBucket::Day) for a time series, then .load().await.
Sourcepub async fn preload<__Model, __Spec>(
&self,
records: Vec<__Model>,
spec: __Spec,
) -> AutumnResult<Vec<Preloaded<__Model>>>
pub async fn preload<__Model, __Spec>( &self, records: Vec<__Model>, spec: __Spec, ) -> AutumnResult<Vec<Preloaded<__Model>>>
Eager-load associations for records returned by a finder.
Wraps each record in Preloaded
and loads every association named in spec with at most one
batched WHERE ... IN (...) query per association level (plus
one per nested level). No per-row fetches, and no implicit lazy
loading — an un-preloaded association accessor returns
NotLoaded.
Preload SQL runs on the same read role as the finder (the
repository’s snapshotted ReadRoute),
so a replica-routed list keeps its preloads on the replica.
let posts = repo.find_by_subreddit_id(id).await?;
let posts = repo
.preload(posts, Post::preload().author().comments_with(Comment::preload().author()))
.await?;
for post in &posts {
let author = post.author()?; // typed accessor
for comment in post.comments()? { /* ... */ }
}Sourcepub async fn with_lock<F, T>(&self, id: i64, f: F) -> AutumnResult<T>where
F: for<'c> FnOnce(ExperimentChange, &'c mut RuntimeConnection) -> ScopedBoxFuture<'c, 'c, AutumnResult<T>> + Send + 'static,
T: Send + 'static,
pub async fn with_lock<F, T>(&self, id: i64, f: F) -> AutumnResult<T>where
F: for<'c> FnOnce(ExperimentChange, &'c mut RuntimeConnection) -> ScopedBoxFuture<'c, 'c, AutumnResult<T>> + Send + 'static,
T: Send + 'static,
Pessimistic lock helper: SELECT FOR UPDATE the row with
the given id inside a transaction, then call f with
the locked record and the transaction connection.
Returns 404 Not Found if no row with id exists.
Trait Implementations§
Source§impl BatchSource for PgExperimentChangeRepository
impl BatchSource for PgExperimentChangeRepository
Source§type Model = ExperimentChange
type Model = ExperimentChange
Source§async fn fetch_batch_after(
&self,
after_id: Option<i64>,
limit: i64,
) -> AutumnResult<Vec<ExperimentChange>>
async fn fetch_batch_after( &self, after_id: Option<i64>, limit: i64, ) -> AutumnResult<Vec<ExperimentChange>>
limit models with id > after_id (or from the start of
the table when after_id is None), ordered by id ascending.Source§fn batch_key(model: &ExperimentChange) -> i64
fn batch_key(model: &ExperimentChange) -> i64
Source§impl Clone for PgExperimentChangeRepository
impl Clone for PgExperimentChangeRepository
Source§impl ExperimentChangeRepository for PgExperimentChangeRepository
impl ExperimentChangeRepository for PgExperimentChangeRepository
async fn find_by_id(&self, id: i64) -> AutumnResult<Option<ExperimentChange>>
async fn find_all(&self) -> AutumnResult<Vec<ExperimentChange>>
async fn save( &self, new: &NewExperimentChange, ) -> AutumnResult<ExperimentChange>
async fn update( &self, id: i64, changes: &UpdateExperimentChange, ) -> AutumnResult<ExperimentChange>
async fn delete_by_id(&self, id: i64) -> AutumnResult<()>
async fn count(&self) -> AutumnResult<i64>
async fn exists_by_id(&self, id: i64) -> AutumnResult<bool>
Source§async fn page(&self, req: &PageRequest) -> AutumnResult<Page<ExperimentChange>>
async fn page(&self, req: &PageRequest) -> AutumnResult<Page<ExperimentChange>>
Source§async fn list(
&self,
query: &ListQuery,
req: &PageRequest,
) -> AutumnResult<Page<ExperimentChange>>
async fn list( &self, query: &ListQuery, req: &PageRequest, ) -> AutumnResult<Page<ExperimentChange>>
::autumn_web::pagination::ListQuery, with offset
pagination from a ::autumn_web::pagination::PageRequest. Read moreSource§async fn list_rows(
&self,
query: &ListQuery,
limit: usize,
) -> AutumnResult<Vec<ExperimentChange>>
async fn list_rows( &self, query: &ListQuery, limit: usize, ) -> AutumnResult<Vec<ExperimentChange>>
async fn save_many( &self, new: &[NewExperimentChange], ) -> AutumnResult<Vec<ExperimentChange>>
async fn save_many_skip_invalid( &self, new: &[NewExperimentChange], ) -> AutumnResult<(Vec<ExperimentChange>, Vec<(usize, AutumnError)>)>
async fn update_many( &self, ids: &[i64], changes: &UpdateExperimentChange, ) -> AutumnResult<Vec<ExperimentChange>>
Source§async fn delete_many(&self, ids: &[i64]) -> AutumnResult<()>
async fn delete_many(&self, ids: &[i64]) -> AutumnResult<()>
async fn upsert_many( &self, records: &[ExperimentChange], ) -> AutumnResult<Vec<ExperimentChange>>
Auto Trait Implementations§
impl !RefUnwindSafe for PgExperimentChangeRepository
impl !UnwindSafe for PgExperimentChangeRepository
impl Freeze for PgExperimentChangeRepository
impl Send for PgExperimentChangeRepository
impl Sync for PgExperimentChangeRepository
impl Unpin for PgExperimentChangeRepository
impl UnsafeUnpin for PgExperimentChangeRepository
Blanket Implementations§
Source§impl<T> AggregateExpressionMethods for T
impl<T> AggregateExpressionMethods for T
Source§fn aggregate_distinct(self) -> Self::Outputwhere
Self: DistinctDsl,
fn aggregate_distinct(self) -> Self::Outputwhere
Self: DistinctDsl,
DISTINCT modifier for aggregate functions Read moreSource§fn aggregate_all(self) -> Self::Outputwhere
Self: AllDsl,
fn aggregate_all(self) -> Self::Outputwhere
Self: AllDsl,
ALL modifier for aggregate functions Read moreSource§fn aggregate_filter<P>(self, f: P) -> Self::Output
fn aggregate_filter<P>(self, f: P) -> Self::Output
Source§fn aggregate_order<O>(self, o: O) -> Self::Outputwhere
Self: OrderAggregateDsl<O>,
fn aggregate_order<O>(self, o: O) -> Self::Outputwhere
Self: OrderAggregateDsl<O>,
Source§impl<T> AutumnCounterCaches for Twhere
T: 'static,
impl<T> AutumnCounterCaches for Twhere
T: 'static,
Source§const HAS_COUNTER_CACHES: bool = false
const HAS_COUNTER_CACHES: bool = false
Source§fn counter_caches() -> &'static [CounterCacheSpec<Self>]
fn counter_caches() -> &'static [CounterCacheSpec<Self>]
Source§impl<T> AutumnDependents for Twhere
T: ?Sized,
impl<T> AutumnDependents for Twhere
T: ?Sized,
Source§fn dependents() -> &'static [RuntimeDependentSpec]
fn dependents() -> &'static [RuntimeDependentSpec]
#[model] overrides via an inherent shadow when dependents exist.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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<S, T> FromRequest<S, ViaParts> for T
impl<S, T> FromRequest<S, ViaParts> for T
Source§type Rejection = <T as FromRequestParts<S>>::Rejection
type Rejection = <T as FromRequestParts<S>>::Rejection
Source§fn from_request(
req: Request<Body>,
state: &S,
) -> impl Future<Output = Result<T, <T as FromRequest<S, ViaParts>>::Rejection>>
fn from_request( req: Request<Body>, state: &S, ) -> impl Future<Output = Result<T, <T as FromRequest<S, ViaParts>>::Rejection>>
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> IntoSql for T
impl<T> IntoSql for T
Source§fn into_sql<T>(self) -> Self::Expression
fn into_sql<T>(self) -> Self::Expression
self to an expression for Diesel’s query builder. Read moreSource§fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expression
fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expression
&self to an expression for Diesel’s query builder. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> RepositoryHooksClone for Twhere
T: Clone,
impl<T> RepositoryHooksClone for Twhere
T: Clone,
Source§fn autumn_clone(&self) -> T
fn autumn_clone(&self) -> T
Source§impl<T, Conn> RunQueryDsl<Conn> for T
impl<T, Conn> RunQueryDsl<Conn> for T
Source§fn execute<'conn, 'query>(
self,
conn: &'conn mut Conn,
) -> <Conn as AsyncConnectionCore>::ExecuteFuture<'conn, 'query>
fn execute<'conn, 'query>( self, conn: &'conn mut Conn, ) -> <Conn as AsyncConnectionCore>::ExecuteFuture<'conn, 'query>
Source§fn load<'query, 'conn, U>(
self,
conn: &'conn mut Conn,
) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
fn load<'query, 'conn, U>( self, conn: &'conn mut Conn, ) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
Source§fn load_stream<'conn, 'query, U>(
self,
conn: &'conn mut Conn,
) -> Self::LoadFuture<'conn>where
Conn: AsyncConnectionCore,
U: 'conn,
Self: LoadQuery<'query, Conn, U> + 'query,
fn load_stream<'conn, 'query, U>(
self,
conn: &'conn mut Conn,
) -> Self::LoadFuture<'conn>where
Conn: AsyncConnectionCore,
U: 'conn,
Self: LoadQuery<'query, Conn, U> + 'query,
Stream] with the returned rows. Read moreSource§fn get_result<'query, 'conn, U>(
self,
conn: &'conn mut Conn,
) -> AndThen<Self::LoadFuture<'conn>, LoadNext<Pin<Box<Self::Stream<'conn>>>>>
fn get_result<'query, 'conn, U>( self, conn: &'conn mut Conn, ) -> AndThen<Self::LoadFuture<'conn>, LoadNext<Pin<Box<Self::Stream<'conn>>>>>
Source§fn get_results<'query, 'conn, U>(
self,
conn: &'conn mut Conn,
) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
fn get_results<'query, 'conn, U>( self, conn: &'conn mut Conn, ) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
Vec with the affected rows. Read moreSource§impl<T> Scoped for T
impl<T> Scoped for T
Source§fn scope(ctx: &PolicyContext) -> ScopeQuery<'_, Self>
fn scope(ctx: &PolicyContext) -> ScopeQuery<'_, Self>
ScopeQuery for this type. Resolves the
registered scope at .load() time, not here.