web.rs
Overview
This file implements a GraphQL web server interface that serves queries against a SQLite database and integrates with an SDK client context. It provides two main GraphQL endpoints: a legacy playground (/graphql_old) and a modern GraphiQL interface (/graphql). The server is built using the Warp web framework and supports two modes controlled by a feature flag: an "extended" API mode with enhanced query capabilities, and a "standard" API mode with basic query support.
The file handles asynchronous connections to a SQLite database, GraphQL schema construction with data loaders for efficient batch loading, HTTP routing for GraphQL requests and UIs, and error recovery. It is designed for efficient operation in a multi-threaded asynchronous environment.
Functions
open_db
async fn open_db(db_path: PathBuf) -> anyhow::Result<Pool<Sqlite>>
Purpose
Attempts to asynchronously open a read-only connection pool to a SQLite database file located at db_path. It retries up to three times with a 3-second interval between attempts if the connection fails.
Parameters
db_path: PathBuf— The file path to the SQLite database.
Returns
anyhow::Result<Pool<Sqlite>>— On success, returns a connection pool to the SQLite database. On failure, returns an error wrapped inanyhow::Result.
Implementation Details
Constructs a connection string that opens the database in read-only mode (
?mode=ro).Uses a
tokio::time::intervalto retry connection attempts every 3 seconds.Logs errors on failure and aborts after 3 failed attempts.
Uses
sqlx::SqlitePool::connectfor asynchronous connection pooling.Uses
anyhow::Contextto provide contextual error messages.
Usage Example
let db_path = PathBuf::from("data/mydb.sqlite");
let pool = open_db(db_path).await?;
start
pub async fn start(
bind_to: String,
db_path: PathBuf,
sdk_client: Arc<ClientContext>,
) -> anyhow::Result<()>
Purpose
Starts the Warp-based HTTP server that serves the GraphQL API and UI endpoints. It binds to the specified socket address and serves GraphQL requests against the database and SDK client context.
Parameters
bind_to: String— The socket address to bind the server to, e.g.,"127.0.0.1:8080".db_path: PathBuf— The SQLite database file path.sdk_client: Arc<ClientContext>— Shared reference to an SDK client context used for queries.
Returns
anyhow::Result<()>— ReturnsOk(())once the server has been started and runs indefinitely, or an error if startup fails.
Implementation Details
Opens the SQLite connection pool by calling
open_db.Parses the bind address into a
SocketAddr.Defines two HTTP GET endpoints:
/graphql_old: Serves the GraphQL Playground HTML UI./graphql: Serves the GraphiQL HTML UI.
Conditionally builds one of two GraphQL schemas based on the
store_events_onlyfeature flag:If disabled (extended mode):
Uses
graphql_ext::QueryRootas the root query.Attaches three data loaders:
BlockLoader,MessageLoader, andTransactionLoaderfor batch loading of related entities.Includes the SDK client context as shared data.
If enabled (standard mode):
Uses
graphql_std::QueryRootas the root query.Does not include data loaders or SDK client context.
Wraps the schema with Warp filters to handle GraphQL POST requests.
Provides error recovery for bad requests and internal server errors.
Logs the active API mode and bind address.
Runs the Warp server asynchronously on the specified address.
Usage Example
let bind_address = "127.0.0.1:8000".to_string();
let db_path = PathBuf::from("data/mydb.sqlite");
let sdk_client = Arc::new(ClientContext::new(...));
start(bind_address, db_path, sdk_client).await?;
Important Implementation Details and Algorithms
Database Connection Retry Logic:
Theopen_dbfunction implements a retry mechanism usingtokio::time::intervalto handle transient failures when opening the SQLite database. It tries three times with a delay of 3 seconds between attempts before giving up.GraphQL Schema Construction:
The file conditionally builds two different GraphQL schemas (graphql_extorgraphql_std) depending on the feature flagstore_events_only. This enables switching between a richer API with data loaders and a simpler standard API.DataLoader Usage for Efficiency:
In extended mode, the schema is enriched withDataLoaderinstances for blocks, messages, and transactions. These loaders batch and cache database queries to optimize GraphQL query performance and reduce redundant calls.Warp Filters for Routing and Error Handling:
The Warp filter combinators elegantly compose the HTTP routes for GraphQL queries, playground UI, and error recovery. This modular approach supports asynchronous request handling and clean error responses.Integration with SDK Client:
The SDK client context (ClientContext) is passed into the GraphQL schema as shared data, allowing resolvers to invoke SDK functionality as part of query execution.
Interactions with Other Parts of the System
GraphQL Schema Modules:
The file references two schema modules:graphql_extandgraphql_std, representing extended and standard GraphQL APIs, respectively. These schemas define the GraphQL query roots and types used here.DataLoader Modules:
It importsBlockLoader,MessageLoader, andTransactionLoaderfrom theschema::graphqlsubmodules for batch loading of blockchain-related data entities.SDK Client:
Thetvm_client::ClientContextis injected into the schema to enable GraphQL resolvers to access blockchain or SDK-related data and operations.Warp Web Framework:
The file uses Warp for HTTP server functionality, filter routing, and response handling.SQLx Database Pool:
The SQLite connection pool is created and managed usingsqlx::SqlitePool, enabling asynchronous database access.
Visual Diagram
flowchart TD
A[Start Function] --> B[open_db]
B --> C{Feature Flag: store_events_only}
C -- false --> D[Build Extended Schema]
C -- true --> E[Build Standard Schema]
D --> F[Attach DataLoaders & SDK Client]
E --> G[Attach Pool Only]
F & G --> H[Create GraphQL POST Filter]
H --> I[Define /graphql_old Playground Endpoint]
H --> J[Define /graphql GraphiQL Endpoint]
I & J --> K[Compose Routes with Error Handling]
K --> L[Run Warp Server Bind to Address]
Summary of Components
Component | Description |
|---|---|
| Opens and retries connection to SQLite database. |
| Configures GraphQL schema, HTTP routes, and runs the Warp server. |
| Warp filter serving legacy GraphQL Playground UI at |
| Warp filter serving modern GraphiQL UI at |
| Warp filter handling GraphQL POST requests. |
| Batch loaders for blocks, messages, and transactions in extended API mode. |
| GraphQL schemas built with |
| Shared SDK client context passed to schema for extended API. |
References to Relevant Topics
The GraphQL schema roots and data loaders are defined under the
schema.graphqltopic.Database connection pooling and SQLx usage follow patterns described in database.connection.
Warp web server routing and filters are detailed in
web.warp.The SDK client context and its usage can be found in sdk.client.
Error handling patterns follow the error.handling standards.