pub struct Writer {
pub l0_manager: Arc<L0Manager>,
pub storage: Arc<StorageManager>,
pub schema_manager: Arc<SchemaManager>,
pub allocator: Arc<IdAllocator>,
pub config: UniConfig,
pub xervo_runtime: Option<Arc<ModelRuntime>>,
pub transaction_l0: Option<Arc<RwLock<L0Buffer>>>,
pub property_manager: Option<Arc<PropertyManager>>,
/* private fields */
}Fields§
§l0_manager: Arc<L0Manager>§storage: Arc<StorageManager>§schema_manager: Arc<SchemaManager>§allocator: Arc<IdAllocator>§config: UniConfig§xervo_runtime: Option<Arc<ModelRuntime>>§transaction_l0: Option<Arc<RwLock<L0Buffer>>>§property_manager: Option<Arc<PropertyManager>>Property manager for cache invalidation after flush
Implementations§
Source§impl Writer
impl Writer
pub async fn new( storage: Arc<StorageManager>, schema_manager: Arc<SchemaManager>, start_version: u64, ) -> Result<Self>
pub async fn new_with_config( storage: Arc<StorageManager>, schema_manager: Arc<SchemaManager>, start_version: u64, config: UniConfig, wal: Option<Arc<WriteAheadLog>>, allocator: Option<Arc<IdAllocator>>, ) -> Result<Self>
Sourcepub async fn replay_wal(&self, wal_high_water_mark: u64) -> Result<usize>
pub async fn replay_wal(&self, wal_high_water_mark: u64) -> Result<usize>
Replay WAL mutations into the current L0 buffer.
Sourcepub async fn allocate_vids(&self, count: usize) -> Result<Vec<Vid>>
pub async fn allocate_vids(&self, count: usize) -> Result<Vec<Vid>>
Allocates multiple VIDs at once for bulk operations. This is more efficient than calling next_vid() in a loop.
Sourcepub async fn next_eid(&self, _type_id: u32) -> Result<Eid>
pub async fn next_eid(&self, _type_id: u32) -> Result<Eid>
Allocates the next EID (pure auto-increment).
pub fn set_xervo_runtime(&mut self, runtime: Arc<ModelRuntime>)
pub fn xervo_runtime(&self) -> Option<Arc<ModelRuntime>>
pub fn begin_transaction(&mut self) -> Result<()>
pub async fn commit_transaction(&mut self) -> Result<()>
pub fn rollback_transaction(&mut self) -> Result<()>
Sourcepub fn force_rollback(&mut self)
pub fn force_rollback(&mut self)
Force-rollback any active transaction. Safe to call if no transaction active. Used by Transaction::Drop for cleanup.
Sourcepub async fn get_vertex_labels(&self, vid: Vid) -> Option<Vec<String>>
pub async fn get_vertex_labels(&self, vid: Vid) -> Option<Vec<String>>
Get vertex labels from all sources: current L0, pending L0s, and storage. This is the proper way to read vertex labels after a flush, as it checks both in-memory buffers and persisted storage.
Sourcepub fn get_edge_type_id_from_l0(&self, eid: Eid) -> Option<u32>
pub fn get_edge_type_id_from_l0(&self, eid: Eid) -> Option<u32>
Look up the edge type ID (u32) for an EID from the L0 buffer’s edge endpoints. Falls back to the transaction L0 if available.
Sourcepub fn set_edge_type(&self, eid: Eid, type_name: String)
pub fn set_edge_type(&self, eid: Eid, type_name: String)
Set the type name for an edge (used for schemaless edge types). This is called during CREATE for edge types not found in the schema.
pub async fn insert_vertex( &mut self, vid: Vid, properties: Properties, ) -> Result<()>
pub async fn insert_vertex_with_labels( &mut self, vid: Vid, properties: Properties, labels: &[String], ) -> Result<Properties>
Sourcepub async fn insert_vertices_batch(
&mut self,
vids: Vec<Vid>,
properties_batch: Vec<Properties>,
labels: Vec<String>,
) -> Result<Vec<Properties>>
pub async fn insert_vertices_batch( &mut self, vids: Vec<Vid>, properties_batch: Vec<Properties>, labels: Vec<String>, ) -> Result<Vec<Properties>>
Insert multiple vertices with batched operations.
This method uses batched operations to achieve O(N) complexity instead of O(N²) for bulk inserts with unique constraints.
§Performance Improvements
- Batch VID allocation: 1 call instead of N calls
- Batch constraint validation: O(N) instead of O(N²)
- Batch embedding generation: 1 API call per config instead of N calls
- Transaction wrapping: Automatic flush deferral, atomicity
§Arguments
vids- Pre-allocated VIDs for the verticesproperties_batch- Properties for each vertexlabels- Labels for all vertices (assumes single label for simplicity)
§Errors
Returns error if:
- VID/properties length mismatch
- Constraint violation detected
- Embedding generation fails
- Transaction commit fails
§Atomicity
If this method fails, all changes are rolled back (if transaction was started here).
Sourcepub async fn delete_vertex(
&mut self,
vid: Vid,
labels: Option<Vec<String>>,
) -> Result<()>
pub async fn delete_vertex( &mut self, vid: Vid, labels: Option<Vec<String>>, ) -> Result<()>
Delete a vertex by VID.
When labels is provided, uses them directly to populate L0 for
correct tombstone flushing. Otherwise discovers labels from L0
buffers and storage (which can be slow for many vertices).
§Errors
Returns an error if write pressure stalls, label lookup fails, or the L0 delete operation fails.
pub async fn insert_edge( &mut self, src_vid: Vid, dst_vid: Vid, edge_type: u32, eid: Eid, properties: Properties, edge_type_name: Option<String>, ) -> Result<()>
pub async fn delete_edge( &mut self, eid: Eid, src_vid: Vid, dst_vid: Vid, edge_type: u32, ) -> Result<()>
Sourcepub async fn check_flush(&mut self) -> Result<()>
pub async fn check_flush(&mut self) -> Result<()>
Check if flush should be triggered based on mutation count or time elapsed. This method is called after each write operation and can also be called by a background task for time-based flushing.
Sourcepub async fn flush_to_l1(&mut self, name: Option<String>) -> Result<String>
pub async fn flush_to_l1(&mut self, name: Option<String>) -> Result<String>
Flushes the current in-memory L0 buffer to L1 storage.
§Lock Ordering
To prevent deadlocks, locks must be acquired in the following order:
Writerlock (held by caller)L0Managerlock (viabegin_flush/get_current)L0Bufferlock (individual buffer RWLocks)Index/Storagelocks (during actual flush)
Sourcepub fn set_property_manager(&mut self, pm: Arc<PropertyManager>)
pub fn set_property_manager(&mut self, pm: Arc<PropertyManager>)
Set the property manager for cache invalidation.
Auto Trait Implementations§
impl Freeze for Writer
impl !RefUnwindSafe for Writer
impl Send for Writer
impl Sync for Writer
impl Unpin for Writer
impl UnsafeUnpin for Writer
impl !UnwindSafe for Writer
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.