8 releases
| new 0.1.7 | Mar 5, 2026 |
|---|---|
| 0.1.6 | Feb 13, 2026 |
| 0.1.2 | Jan 23, 2026 |
#688 in Testing
898 downloads per month
1MB
15K
SLoC
NoOp Bootstrap Provider
A lightweight bootstrap provider plugin for Drasi that returns no data. This provider is useful when sources don't require bootstrap support or when you want to disable initial data loading while maintaining continuous change streaming.
Overview
The NoOp Bootstrap Provider implements the BootstrapProvider trait but intentionally returns zero elements. This makes it ideal for scenarios where:
- No historical data is needed: Queries should only process new changes, not existing data
- Source doesn't support bootstrap: The data source only provides streaming updates without snapshot capabilities
- Testing streaming logic: You want to test continuous query processing without bootstrap complexity
- Performance optimization: Skipping bootstrap reduces startup time when historical data isn't required
Key Capabilities
- Zero-overhead implementation: No data processing, minimal resource usage
- Consistent logging: Reports bootstrap completion with element count of 0
- Builder pattern support: Provides standard builder API for consistency with other providers
- Thread-safe: Can be safely shared across threads (implements
Send + Sync) - Zero-sized type (ZST): No memory overhead when instantiated
Configuration
YAML Configuration
sources:
- id: my_source
source_type: http # Any source type
bootstrap_provider:
type: noop # No additional configuration needed
properties:
# Source-specific properties
Programmatic Configuration
The NoOp provider can be instantiated using either the constructor or builder pattern:
use drasi_bootstrap_noop::NoOpBootstrapProvider;
// Option 1: Direct instantiation
let provider = NoOpBootstrapProvider::new();
// Option 2: Builder pattern (for API consistency)
let provider = NoOpBootstrapProvider::builder()
.build();
Usage Examples
Example 1: HTTP Source Without Bootstrap
Stream changes from an HTTP endpoint without loading historical data:
use drasi_lib::{DrasiLib, DrasiLibConfig, Query};
use drasi_bootstrap_noop::NoOpBootstrapProvider;
use drasi_source_http::HttpSourceBuilder;
let source = HttpSourceBuilder::new("api_source")
.with_endpoint("http://api.example.com/events")
.with_bootstrap_provider(Box::new(NoOpBootstrapProvider::new()))
.build()
.await?;
let mut drasi = DrasiLib::new(config);
drasi.initialize().await?;
drasi.add_source(source).await?;
// Query will only process new changes, no historical data
let query = Query::cypher("recent_changes")
.query("MATCH (n:Event) WHERE n.timestamp > datetime() RETURN n")
.from_source("api_source")
.build();
drasi.add_query(query).await?;
drasi.start().await?;
Example 2: Testing with Mock Source
Disable bootstrap when testing continuous query logic:
use drasi_lib::sources::mock::MockSource;
use drasi_bootstrap_noop::NoOpBootstrapProvider;
let mock_source = MockSource::builder()
.with_id("test_source")
.with_bootstrap_provider(Box::new(NoOpBootstrapProvider::new()))
.build();
// Mock source will only process injected changes, no bootstrap
mock_source.inject_change(my_test_change).await?;
Example 3: PostgreSQL Streaming Only
Stream PostgreSQL WAL changes without loading existing table data:
use drasi_source_postgres::PostgresReplicationSource;
use drasi_bootstrap_noop::NoOpBootstrapProvider;
let source = PostgresReplicationSource::builder()
.with_id("pg_stream")
.with_host("localhost")
.with_database("mydb")
.with_bootstrap_provider(Box::new(NoOpBootstrapProvider::new()))
.build()
.await?;
// Only new inserts/updates/deletes will be processed
// Existing rows in the database are ignored
Example 4: Mix-and-Match Providers
Use different bootstrap providers for different sources:
use drasi_bootstrap_noop::NoOpBootstrapProvider;
use drasi_bootstrap_postgres::PostgresBootstrapProvider;
// Source 1: Full bootstrap from PostgreSQL
let source1 = build_source_with_bootstrap(
Box::new(PostgresBootstrapProvider::new())
);
// Source 2: No bootstrap, streaming only
let source2 = build_source_with_bootstrap(
Box::new(NoOpBootstrapProvider::new())
);
// Different bootstrap strategies for different sources
drasi.add_source(source1).await?;
drasi.add_source(source2).await?;
API Reference
NoOpBootstrapProvider
pub struct NoOpBootstrapProvider;
The main provider struct. This is a zero-sized type (ZST) with no fields.
Methods
impl NoOpBootstrapProvider {
/// Create a new NoOp bootstrap provider
pub fn new() -> Self;
/// Create a builder for NoOpBootstrapProvider
/// Returns NoOpBootstrapProviderBuilder for API consistency
pub fn builder() -> NoOpBootstrapProviderBuilder;
}
Trait Implementations
impl BootstrapProvider for NoOpBootstrapProvider {
async fn bootstrap(
&self,
request: BootstrapRequest,
context: &BootstrapContext,
event_tx: BootstrapEventSender,
) -> Result<usize>;
}
Behavior: Logs the bootstrap request for the query and immediately returns Ok(0) without sending any events.
Returns: Result<usize> - Always returns Ok(0) indicating zero elements were sent.
NoOpBootstrapProviderBuilder
pub struct NoOpBootstrapProviderBuilder;
Builder for creating NoOpBootstrapProvider instances. Provided for API consistency with other bootstrap providers, though no configuration options are available.
Methods
impl NoOpBootstrapProviderBuilder {
/// Create a new builder
pub fn new() -> Self;
/// Build the NoOpBootstrapProvider
pub fn build(self) -> NoOpBootstrapProvider;
}
Logging
The NoOp provider logs bootstrap operations at the info level:
INFO No-op bootstrap for query my_query: returning no data
This helps confirm that bootstrap was intentionally skipped rather than failed.
Performance Characteristics
- Memory: Zero bytes (ZST optimization)
- CPU: Minimal (single log statement)
- Latency: Sub-microsecond bootstrap completion
- Throughput: Not applicable (no data processing)
Comparison with Other Providers
| Provider | Use Case | Data Source | Performance |
|---|---|---|---|
| NoOp | No historical data needed | None | Instant |
| PostgreSQL | Bootstrap from database snapshot | PostgreSQL DB | Depends on table size |
| ScriptFile | Bootstrap from JSONL files | Local files | Depends on file size |
| Platform | Bootstrap from remote Drasi | HTTP API | Depends on network/data |
| Application | Bootstrap from in-memory storage | Application state | Depends on stored data |
When to Use NoOp Provider
Use the NoOp provider when:
- You only care about new changes, not historical data
- The data source doesn't support snapshots
- You're testing continuous query logic
- You want to minimize startup time
- The source will be populated dynamically
Don't use the NoOp provider when:
- Queries need initial state to function correctly
- You're implementing aggregations that require historical data
- The source has existing data that should be processed
- You need to compare current state with changes
Architecture Notes
Universal Bootstrap Provider System
The NoOp provider is part of Drasi's universal pluggable bootstrap architecture where ALL sources support configurable bootstrap providers. This means:
- Any source can use the NoOp provider (PostgreSQL, HTTP, gRPC, Mock, etc.)
- Bootstrap logic is completely separate from source streaming logic
- You can mix and match providers across different sources
- Enables powerful use cases like "stream from HTTP, no bootstrap" or "stream from gRPC, bootstrap from file"
Integration with Sources
Sources that integrate the NoOp provider:
- PostgresReplicationSource: Skips snapshot, only streams WAL changes
- HttpSource: Skips initial data fetch, only processes new events
- GrpcSource: Skips initial streaming, only processes new messages
- MockSource: Skips stored events, only processes new injections
- PlatformSource: Skips initial Redis stream replay, only processes new events
- ApplicationSource: Skips stored inserts, only processes new API calls
Implementation Details
The NoOp provider is intentionally minimal:
#[async_trait]
impl BootstrapProvider for NoOpBootstrapProvider {
async fn bootstrap(
&self,
request: BootstrapRequest,
_context: &BootstrapContext,
_event_tx: BootstrapEventSender,
) -> Result<usize> {
info!(
"No-op bootstrap for query {}: returning no data",
request.query_id
);
Ok(0)
}
}
Key design decisions:
- No data processing:
_contextand_event_txare unused (prefixed with_) - Informative logging: Confirms bootstrap was intentional, not a failure
- Zero-sized type: No memory allocation overhead
- Builder pattern: Maintains API consistency despite no configuration
Dependencies
The NoOp provider has minimal dependencies:
[dependencies]
drasi-lib = { path = "../../../lib" }
anyhow = "1.0"
async-trait = "0.1"
log = "0.4"
Note: The current Cargo.toml includes unnecessary dependencies (tokio-postgres, redis, etc.) that should be removed in a future cleanup. The provider only actually uses the four dependencies listed above.
License
Licensed under the Apache License, Version 2.0. See LICENSE file for details.
Contributing
Contributions are welcome! The NoOp provider is intentionally simple, but improvements could include:
- Additional documentation
- More usage examples
- Performance benchmarks
- Integration tests
Please see the main Drasi contributing guidelines for more information.
Plugin Packaging
This bootstrap provider is compiled as a dynamic plugin (cdylib) that can be loaded by drasi-server at runtime.
Key files:
Cargo.toml— includescrate-type = ["lib", "cdylib"]src/descriptor.rs— implementsBootstrapPluginDescriptorwith kind"noop", configuration DTO, and OpenAPI schema generationsrc/lib.rs— invokesdrasi_plugin_sdk::export_plugin!to export the plugin entry point
Building:
cargo build -p drasi-bootstrap-noop
The compiled .so (Linux) / .dylib (macOS) / .dll (Windows) is placed in target/debug/ and can be copied to the server's plugins/ directory.
For more details on the plugin descriptor pattern and configuration DTOs, see the Bootstrap Provider Developer Guide.
See Also
- Bootstrap Provider Architecture - Overview of the bootstrap system
- PostgreSQL Bootstrap Provider - Database snapshot bootstrap
- ScriptFile Bootstrap Provider - File-based bootstrap
- Platform Bootstrap Provider - Remote Drasi bootstrap
- Application Bootstrap Provider - In-memory bootstrap
Dependencies
~39–56MB
~756K SLoC