use async_trait::async_trait;
use chrono::{DateTime, Utc};
use serde_json::Value;
use spectra_backend_remote_common::RemoteEventsBackend;
use spectra_core::{
EventAggregateResult, EventRow, EventStorageBackend, EventWriteRow, EventsAggregateFilter,
EventsQueryFilter, Result, StorageEngineType,
};
pub struct TensorBaseEventsBackend(RemoteEventsBackend);
impl TensorBaseEventsBackend {
pub async fn connect(url: &str) -> Result<Self> {
Ok(Self(
RemoteEventsBackend::connect(
url,
StorageEngineType::TensorBase,
&crate::ddl::events_ddl(),
)
.await?,
))
}
pub async fn connect_host(host: &str) -> Result<Self> {
Self::connect(&crate::ddl::default_url(host)).await
}
pub fn in_memory_stub() -> Self {
Self(RemoteEventsBackend::in_memory_for_test(
StorageEngineType::TensorBase,
))
}
#[cfg(test)]
pub fn in_memory_for_test() -> Self {
Self::in_memory_stub()
}
}
#[async_trait]
impl EventStorageBackend for TensorBaseEventsBackend {
fn engine_type(&self) -> StorageEngineType {
self.0.engine_type()
}
async fn append_row(
&self,
table: &str,
fields: &Value,
ts: DateTime<Utc>,
correlation_id: Option<&str>,
) -> Result<()> {
self.0.append_row(table, fields, ts, correlation_id).await
}
async fn append_rows_batch(&self, rows: &[EventWriteRow]) -> Result<()> {
self.0.append_rows_batch(rows).await
}
async fn query_rows(&self, filter: EventsQueryFilter) -> Result<Vec<EventRow>> {
self.0.query_rows(filter).await
}
async fn query_aggregate(&self, filter: EventsAggregateFilter) -> Result<EventAggregateResult> {
self.0.query_aggregate(filter).await
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[tokio::test]
async fn tensorbase_events_roundtrip_in_memory() {
let backend = TensorBaseEventsBackend::in_memory_for_test();
let ts = Utc::now();
backend
.append_row("req", &json!({"x": 1}), ts, None)
.await
.expect("write");
let rows = backend
.query_rows(EventsQueryFilter {
table: "req".into(),
..Default::default()
})
.await
.expect("query");
assert_eq!(rows.len(), 1);
}
#[tokio::test]
#[ignore = "requires SPECTRA_TENSORBASE_URL"]
async fn tensorbase_events_integration() {
let url = std::env::var("SPECTRA_TENSORBASE_URL").expect("SPECTRA_TENSORBASE_URL");
let backend = TensorBaseEventsBackend::connect(&url)
.await
.expect("connect");
let ts = Utc::now();
backend
.append_row("integration_req", &json!({"ok": true}), ts, None)
.await
.expect("write");
let rows = backend
.query_rows(EventsQueryFilter {
table: "integration_req".into(),
..Default::default()
})
.await
.expect("query");
assert!(!rows.is_empty());
}
}