Event protocol for Scry SQL proxy - FlexBuffers serialization for query events.
This crate provides the event types and serialization/deserialization for query events captured by the Scry proxy. It's designed to be used both by the proxy itself and by downstream analytics services that consume events.
- Event Types:
QueryEventandQueryEventBuilderfor constructing events - FlexBuffers Serialization: Efficient, schema-less binary serialization
- FlexBuffers Deserialization: Deserialize event batches from binary format
- Batch Support: Serialize and deserialize multiple events in a single batch
- Schema Documentation: Canonical FlatBuffers schema in
schema/query_event.fbs
Events are serialized using FlexBuffers, a schema-less binary format from the FlatBuffers project. This provides:
- Compact binary representation: Smaller than JSON, efficient over the network
- Backward/forward compatibility: Schema evolution without breaking consumers
- Zero-copy capabilities: Efficient deserialization when needed
- Works seamlessly with serde: No code generation required
See schema/query_event.fbs for the canonical schema definition.
Represents a captured SQL query event from the proxy:
event_id: Unique identifier (UUID v4)timestamp: When the query was received (SystemTime)query: The SQL query text (raw or anonymized)normalized_query: Normalized query with placeholders (optional, if anonymization enabled)value_fingerprints: Fingerprints of literal values (optional, for hot data detection)duration: Query execution durationrows: Number of rows affected/returned (optional)success: Whether the query succeedederror: Error message if query failed (optional)database: Database nameconnection_id: Client connection identifier
A batch of query events sent together:
events: Array of QueryEventproxy_id: Unique proxy instance identifierbatch_seq: Batch sequence number (for ordering/deduplication)
use scry_protocol::{QueryEventBuilder, Duration};
let event = QueryEventBuilder::new("SELECT * FROM users")
.connection_id("conn-123")
.database("mydb")
.duration(Duration::from_millis(5))
.rows(42)
.build();use scry_protocol::FlatBuffersSerializer;
let events = vec![event1, event2, event3];
let bytes = FlatBuffersSerializer::serialize_batch(
&events,
"proxy-1", // proxy_id
0 // batch_seq
);
// Send bytes over the network...use scry_protocol::FlexBuffersDeserializer;
// Receive bytes from the network...
let batch = FlexBuffersDeserializer::deserialize_batch(&bytes)?;
println!("Proxy ID: {}", batch.proxy_id);
println!("Batch seq: {}", batch.batch_seq);
for event in batch.events {
println!("Query: {}", event.query);
println!("Duration: {:?}", event.duration);
println!("Success: {}", event.success);
}See the examples/ directory for complete examples:
serialize.rs- Creating and serializing eventsdeserialize.rs- Deserializing and reading events
Run examples with:
cargo run --example serialize
cargo run --example deserializeThis crate follows semantic versioning:
- Major version: Breaking changes to the event schema or API
- Minor version: New fields added (backward compatible)
- Patch version: Bug fixes, internal improvements
FlexBuffers provides forward/backward compatibility:
- Forward compatible: Old readers can read new data (unknown fields ignored)
- Backward compatible: New readers can read old data (missing fields use defaults)
- Serialization: ~1-2 microseconds per event
- Deserialization: ~2-3 microseconds per event
- Batch overhead: Minimal, amortized across events
- Binary size: ~200-400 bytes per event (varies with query length)
Run tests with:
cargo testThe test suite includes:
- Unit tests for serialization/deserialization
- Roundtrip tests (serialize → deserialize → verify)
- Edge cases (empty batches, large batches, special characters)
- Timestamp precision tests
Licensed under MIT OR Apache-2.0