use nodedb_types::result::QueryResult;
use crate::error::LiteError;
use crate::query::engine::LiteQueryEngine;
use crate::storage::engine::StorageEngine;
pub async fn handle_apply<S: StorageEngine>(
engine: &LiteQueryEngine<S>,
collection: &str,
delta: &[u8],
mutation_id: u64,
) -> Result<QueryResult, LiteError> {
handle_apply_coordinated(engine, None, collection, delta, mutation_id).await
}
pub(crate) async fn handle_apply_coordinated<S: StorageEngine>(
engine: &LiteQueryEngine<S>,
permit: Option<&crate::engine::fts::coordinator::TextMutationPermit>,
collection: &str,
delta: &[u8],
mutation_id: u64,
) -> Result<QueryResult, LiteError> {
if let Some(permit) = permit {
return handle_apply_admitted(engine, permit, collection, delta, mutation_id).await;
}
let guard = engine.fts_state.admit_mutation().await;
let result =
handle_apply_admitted(engine, guard.permit(), collection, delta, mutation_id).await;
guard.finish(result)
}
pub(crate) async fn handle_apply_admitted<S: StorageEngine>(
engine: &LiteQueryEngine<S>,
permit: &crate::engine::fts::coordinator::TextMutationPermit,
collection: &str,
delta: &[u8],
mutation_id: u64,
) -> Result<QueryResult, LiteError> {
let _permit = permit;
let result = {
let mut crdt = engine.crdt.lock().map_err(|_| LiteError::LockPoisoned)?;
crdt.import_remote(collection, delta)
};
match result {
Ok(imported) => {
crate::engine::fts::maintain::reindex_crdt_documents(
&engine.fts_state,
&engine.crdt,
None::<&crate::engine::fts::maintain::FtsOutbound<S>>,
collection,
imported.changed_rows.iter().map(String::as_str),
)?;
let mut crdt = engine.crdt.lock().map_err(|_| LiteError::LockPoisoned)?;
crdt.acknowledge(mutation_id);
Ok(QueryResult {
columns: vec![],
rows: vec![],
rows_affected: 1,
command: None,
})
}
Err(import_err) => {
let mut crdt = engine.crdt.lock().map_err(|_| LiteError::LockPoisoned)?;
crdt.reject_delta(mutation_id);
Err(import_err)
}
}
}
pub async fn handle_import_snapshot<S: StorageEngine>(
engine: &LiteQueryEngine<S>,
collection: &str,
bytes: &[u8],
) -> Result<QueryResult, LiteError> {
handle_import_snapshot_coordinated(engine, None, collection, bytes).await
}
pub(crate) async fn handle_import_snapshot_coordinated<S: StorageEngine>(
engine: &LiteQueryEngine<S>,
permit: Option<&crate::engine::fts::coordinator::TextMutationPermit>,
collection: &str,
bytes: &[u8],
) -> Result<QueryResult, LiteError> {
if let Some(permit) = permit {
return handle_import_snapshot_admitted(engine, permit, collection, bytes).await;
}
let guard = engine.fts_state.admit_mutation().await;
let result = handle_import_snapshot_admitted(engine, guard.permit(), collection, bytes).await;
guard.finish(result)
}
pub(crate) async fn handle_import_snapshot_admitted<S: StorageEngine>(
engine: &LiteQueryEngine<S>,
permit: &crate::engine::fts::coordinator::TextMutationPermit,
collection: &str,
bytes: &[u8],
) -> Result<QueryResult, LiteError> {
let _permit = permit;
let imported = engine
.crdt
.lock()
.map_err(|_| LiteError::LockPoisoned)?
.import_local_tracked(collection, bytes)?;
crate::engine::fts::maintain::reindex_crdt_documents(
&engine.fts_state,
&engine.crdt,
None::<&crate::engine::fts::maintain::FtsOutbound<S>>,
collection,
imported.changed_rows.iter().map(String::as_str),
)?;
Ok(QueryResult {
columns: vec![],
rows: vec![],
rows_affected: 1,
command: None,
})
}
pub async fn handle_set_policy<S: StorageEngine>(
engine: &LiteQueryEngine<S>,
collection: &str,
policy_json: &str,
) -> Result<QueryResult, LiteError> {
let policy: nodedb_crdt::CollectionPolicy =
sonic_rs::from_str(policy_json).map_err(|e| LiteError::BadRequest {
detail: format!("invalid CollectionPolicy JSON: {e}"),
})?;
let mut crdt = engine.crdt.lock().map_err(|_| LiteError::LockPoisoned)?;
crdt.set_policy(collection, policy);
Ok(QueryResult {
columns: vec![],
rows: vec![],
rows_affected: 1,
command: None,
})
}