pub struct QueryDenyList { /* private fields */ }Expand description
Owns the Postgres-backed rule store and the compiled, in-memory snapshot every query is
checked against. One instance is owned by LakehouseContext, mirroring AudienceIndex.
ctx is a bare SessionContext::new() – no lakehouse tables or catalog registered against
it, just DataFusion’s parser and name resolution – held only so compile_match_expr can be
called against it. Both refresh and deny_queries’s call_with_args compile through this
same context, so rule compilation produces the same result regardless of whose session
triggered it.
Implementations§
Source§impl QueryDenyList
impl QueryDenyList
pub fn new(pool: Pool<Postgres>) -> QueryDenyList
Sourcepub fn with_snapshot(
pool: Pool<Postgres>,
snapshot: Arc<[Arc<QueryDenyRule>]>,
) -> QueryDenyList
pub fn with_snapshot( pool: Pool<Postgres>, snapshot: Arc<[Arc<QueryDenyRule>]>, ) -> QueryDenyList
Builds a QueryDenyList around an already-compiled snapshot, bypassing Postgres
entirely – for tests exercising Self::check’s in-memory semantics without a live DB
(pool is unused by check; a connect_lazy pool that never touches the network is
enough). Production code should use Self::new plus Self::refresh.
Sourcepub fn compile_ctx(&self) -> &SessionContext
pub fn compile_ctx(&self) -> &SessionContext
A bare SessionContext with no lakehouse tables or catalog registered, for compiling a
match_expr outside this QueryDenyList (e.g. from deny_queries’s call_with_args,
which is handed the caller’s own session and needs a SQL-expression parser instead).
Sourcepub fn rule_count(&self) -> usize
pub fn rule_count(&self) -> usize
The number of rules currently compiled into the snapshot – what deny_queries checks
against max_rules before inserting one more.
Sourcepub fn check(&self, q: &QueryAttribution<'_>) -> Option<Arc<QueryDenyRule>>
pub fn check(&self, q: &QueryAttribution<'_>) -> Option<Arc<QueryDenyRule>>
Checks q against every compiled rule, in order, returning the first (oldest) match.
Returns immediately on an empty snapshot – the steady state of a deployment that is not
mid-incident – before building the one-row batch every non-empty check needs.
Sourcepub async fn list(&self) -> Result<Vec<QueryDenyRow>, Error>
pub async fn list(&self) -> Result<Vec<QueryDenyRow>, Error>
Every rule currently in force, read fresh from Postgres (not the in-memory snapshot) –
what list_query_denials() returns.
Sourcepub async fn insert(
&self,
match_expr: &str,
compiled: Arc<dyn PhysicalExpr>,
reason: &str,
created_by: &str,
) -> Result<QueryDenyRow, Error>
pub async fn insert( &self, match_expr: &str, compiled: Arc<dyn PhysicalExpr>, reason: &str, created_by: &str, ) -> Result<QueryDenyRow, Error>
Inserts a new rule: compiled must already be the result of a successful
compile_match_expr call against match_expr (typically the same call
deny_queries’s call_with_args just made to validate it) – insert stores
match_expr verbatim and does not re-validate it. Refreshes the local snapshot
synchronously before returning, so the admin who created the rule sees it in their own
list_query_denials() immediately; other replicas pick it up within one refresh tick.
Sourcepub async fn delete(&self, rule_id: Uuid) -> Result<bool, Error>
pub async fn delete(&self, rule_id: Uuid) -> Result<bool, Error>
Deletes a rule by id, refreshing the local snapshot synchronously. Returns true if a row
was actually deleted – false lets the caller (remove_query_denial) return a clear
“no such rule” message rather than a silent no-op.
Sourcepub async fn refresh(&self) -> Result<(), Error>
pub async fn refresh(&self) -> Result<(), Error>
Flushes each rule’s accumulated last_hit, then reloads the table and recompiles every
match_expr. A rule that fails to compile is skipped, never fatal – dropped from the
snapshot with a warn! and a query_deny_compile_error_count metric, so an older replica
that cannot compile a newer rule declines to enforce it rather than denying everything or
crashing. Fail-open on a failed reload: the previous snapshot is kept, with a warn!
and a query_deny_refresh_error_count metric – the deny list is an availability valve,
not a security control, and failing closed would deny every query on a Postgres blip.
Sourcepub fn spawn_refresh_task(
self: Arc<QueryDenyList>,
shutdown: impl Future<Output = ()> + Send + 'static,
)
pub fn spawn_refresh_task( self: Arc<QueryDenyList>, shutdown: impl Future<Output = ()> + Send + 'static, )
Spawns the background task that calls Self::refresh once immediately and then on
every MICROMEGAS_QUERY_DENY_REFRESH_SECONDS tick, until shutdown resolves. Only the
FlightSQL server builder spawns this; other LakehouseContext holders (maintenance
daemon, tests) keep an empty snapshot and never deny anything.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for QueryDenyList
impl !RefUnwindSafe for QueryDenyList
impl !UnwindSafe for QueryDenyList
impl Send for QueryDenyList
impl Sync for QueryDenyList
impl Unpin for QueryDenyList
impl UnsafeUnpin for QueryDenyList
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> 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 more§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request§impl<L> LayerExt<L> for L
impl<L> LayerExt<L> for L
§fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
Layered].