Skip to main content

Server

Struct Server 

Source
pub struct Server<A: DatabaseAdapter> { /* private fields */ }
Expand description

FraiseQL HTTP Server.

Server<A> is generic over a DatabaseAdapter implementation, which allows swapping database backends and injecting mock adapters in tests.

§Feature: observers

When compiled with the observers Cargo feature, the server mounts observer management and runtime-health API endpoints under /api/observers. These endpoints require a live PostgreSQL connection pool (sqlx::PgPool).

Pass Some(pg_pool) as the db_pool argument to Server::new when the observers feature is enabled. Passing None causes the observer routes to be skipped at startup (an error is logged) rather than panicking, but the rest of the server continues to function normally.

The PostgreSQL pool is distinct from the generic DatabaseAdapter: the adapter handles application queries, while the pool is used exclusively by the observer subsystem to store and retrieve reactive rule metadata.

Implementations§

Source§

impl<A: DatabaseAdapter + Clone + Send + Sync + 'static> Server<CachedDatabaseAdapter<A>>

Source

pub async fn new( config: ServerConfig, schema: CompiledSchema, adapter: Arc<A>, db_pool: Option<PgPool>, ) -> Result<Self>

Create new server.

Relay pagination queries will return a Validation error at runtime. Use Server::with_relay_pagination when the adapter implements RelayDatabaseAdapter and relay support is required.

§Arguments
  • config - Server configuration
  • schema - Compiled GraphQL schema
  • adapter - Database adapter
  • db_pool — forwarded to the observer runtime; None when observers are disabled.
§Errors

Returns error if OIDC validator initialization fails (e.g., unable to fetch discovery document or JWKS).

§Panics

Panics if the adapter Arc has been cloned before calling this constructor (refcount > 1). The builder must have exclusive ownership to unwrap the adapter for CachedDatabaseAdapter construction.

§Example
// Requires: running PostgreSQL database and compiled schema file.
let config = ServerConfig::default();
let schema = CompiledSchema::from_json(schema_json, false)?;
let adapter = Arc::new(PostgresAdapter::new(db_url).await?);

let server = Server::new(config, schema, adapter, None).await?;
server.serve().await?;
Source§

impl<A: DatabaseAdapter + Clone + Send + Sync + 'static> Server<A>

Source

pub fn with_subscription_lifecycle( self, lifecycle: Arc<dyn SubscriptionLifecycle>, ) -> Self

Set lifecycle hooks for WebSocket subscriptions.

Source

pub const fn with_max_subscriptions_per_connection(self, max: u32) -> Self

Set maximum subscriptions allowed per WebSocket connection.

Source

pub fn with_tenant_executor_factory( self, factory: TenantExecutorFactory<A>, ) -> Self

Attach the per-tenant executor factory used to provision tenants at runtime (PUT /api/v1/admin/tenants/{key}).

Build it with make_executor_factory from the concrete adapter type (which must implement FromPoolConfig). When the multi-tenant runtime is enabled ([tenancy.runtime] enabled = true), build_app_state installs it into AppState. Call this before serve.

Source

pub fn with_pool_tuning( self, config: PoolPressureMonitorConfig, ) -> Result<Self, String>

Enable adaptive connection pool sizing.

When config.enabled is true, the server will spawn a background polling task that samples pool metrics and recommends or applies resizes.

§Errors

Returns an error string if the configuration fails validation (e.g. min >= max).

Source

pub fn with_social_login(self, social_login: Arc<SocialLoginState>) -> Self

Attach a unified social-login provider registry.

When set, the server mounts GET /auth/v1/authorize which redirects users to the specified OAuth provider’s authorization URL with a CSRF state token.

§Example
ⓘ
use fraiseql_auth::social::{SocialLoginState, SocialProviderRegistry};
let state = Arc::new(SocialLoginState { ... });
let server = server.with_social_login(state);
Source

pub fn with_anon_signup(self, state: Arc<AnonSignupState>) -> Self

Attach anonymous signup state to mount POST /auth/v1/signup.

When set, any client can obtain a guest session without credentials. The returned user_id carries an anon_ prefix and the session lasts 7 days. Signups are rate-limited per client IP.

Source

pub fn with_mfa(self, mfa_state: Arc<MfaRouteState>) -> Self

Attach TOTP MFA state to mount the /auth/v1/mfa/ endpoints.

Mounts four routes:

  • POST /auth/v1/mfa/enroll — begin enrollment, returns otpauth:// URI
  • POST /auth/v1/mfa/confirm — confirm enrollment with a live TOTP code
  • POST /auth/v1/mfa/challenge — issue a short-lived challenge token
  • POST /auth/v1/mfa/verify — verify code and issue session
  • POST /auth/v1/mfa/unenroll — remove MFA from an account
Source

pub fn with_storage(self, backend: Arc<dyn StorageBackend>) -> Self

Attach an object storage backend and mount /storage/v1/ routes.

When set, the server mounts GET, POST, DELETE /storage/v1/object/*key and GET /storage/v1/object/sign/*key endpoints backed by the given backend.

Use StorageConfig and create_backend to construct the backend from a TOML configuration block.

Source

pub const fn with_storage_max_upload_bytes(self, bytes: usize) -> Self

Override the maximum allowed upload size for storage endpoints.

Defaults to 100 MiB. Uploads exceeding this size are rejected with HTTP 413 before the body is forwarded to the storage backend.

Source

pub fn with_storage_state(self, state: StorageState) -> Self

Attach a pre-built StorageState and mount the bucket-scoped /storage/v1/* routes (object upload/download/ delete, list, presign) with per-bucket access policy and RLS.

This is the full storage path (metadata-backed, bucket-aware); it differs from with_storage, which mounts the simpler legacy object router. Authentication is applied by mount_storage_state: a configured storage_token acts as an admin bearer and, when an OIDC validator is present, per-user tokens populate the request’s StorageUser for RLS.

Source

pub fn with_revocation_manager( self, manager: Arc<TokenRevocationManager>, ) -> Self

Install a pre-built token-revocation manager, replacing whatever the generic construction path produced.

Used by the PostgreSQL runtime path to install the Postgres-backed store (#357): revocation_manager_from_schema defers the postgres backend because it needs a database connection, so main.rs builds it with build_postgres_revocation_manager and installs it here.

Source§

impl<A: DatabaseAdapter + RelayDatabaseAdapter + Clone + Send + Sync + 'static> Server<CachedDatabaseAdapter<A>>

Source

pub async fn with_relay_pagination( config: ServerConfig, schema: CompiledSchema, adapter: Arc<A>, db_pool: Option<PgPool>, ) -> Result<Self>

Create a server with relay pagination support enabled.

The adapter must implement RelayDatabaseAdapter. Currently, only PostgresAdapter and CachedDatabaseAdapter<PostgresAdapter> satisfy this bound.

Relay queries issued against a server created with Server::new return a Validation error at runtime; those issued against a server created with this constructor succeed.

§Arguments
  • config - Server configuration
  • schema - Compiled GraphQL schema
  • adapter - Database adapter (must implement RelayDatabaseAdapter)
  • db_pool - Database connection pool (optional, required for observers)
§Errors

Returns error if OIDC validator initialization fails.

§Panics

Panics if the adapter Arc has been cloned before calling this constructor (refcount > 1). The builder must have exclusive ownership to unwrap the adapter for CachedDatabaseAdapter construction.

§Example
// Requires: running PostgreSQL database and compiled schema file.
let adapter = Arc::new(PostgresAdapter::new(db_url).await?);
let server = Server::with_relay_pagination(config, schema, adapter, None).await?;
server.serve().await?;
Source§

impl<A: DatabaseAdapter + Clone + Send + Sync + 'static> Server<A>

Source

pub async fn serve(self) -> Result<()>

Start server and listen for requests.

Uses SIGUSR1-aware shutdown signal when a schema path is configured, enabling zero-downtime schema reloads via kill -USR1 <pid>.

§Errors

Returns error if server fails to bind or encounters runtime errors.

Source

pub async fn serve_with_shutdown<F>(self, shutdown: F) -> Result<()>
where F: Future<Output = ()> + Send + 'static,

Start server with a custom shutdown future.

Enables programmatic shutdown (e.g., for --watch hot-reload) by accepting any future that resolves when the server should stop.

§Errors

Returns error if server fails to bind or encounters runtime errors.

Source

pub async fn serve_on_listener<F>( self, listener: TcpListener, shutdown: F, ) -> Result<()>
where F: Future<Output = ()> + Send + 'static,

Start server on an externally created listener.

Used in tests to discover the bound port before serving. Skips TLS, Flight, and observer startup — suitable for unit/integration tests only.

§Errors

Returns error if the server encounters a runtime error.

Source

pub async fn shutdown_signal()

Listen for shutdown signals (Ctrl+C or SIGTERM)

Auto Trait Implementations§

§

impl<A> !RefUnwindSafe for Server<A>

§

impl<A> !UnwindSafe for Server<A>

§

impl<A> Freeze for Server<A>

§

impl<A> Send for Server<A>

§

impl<A> Sync for Server<A>

§

impl<A> Unpin for Server<A>

§

impl<A> UnsafeUnpin for Server<A>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more