1use crate::api::Uni;
5use crate::api::locy_builder::{LocyBuilder, TxLocyBuilder};
6use crate::api::session::{QueryBuilder, Session, TransactionBuilder};
7use crate::api::transaction::{
8 ApplyBuilder, ApplyResult, CommitResult, Transaction, TxQueryBuilder,
9};
10use std::sync::Arc;
11use uni_common::core::schema::{DataType, Schema};
12use uni_common::{Result, UniError, Value};
13use uni_locy::DerivedFactSet;
14
15use crate::api::locy_result::LocyResult;
16use uni_query::{ExecuteResult, QueryResult, Row};
17
18pub struct UniSync {
20 inner: Option<Uni>,
21 rt: tokio::runtime::Runtime,
22}
23
24impl UniSync {
25 pub fn new(inner: Uni) -> Result<Self> {
26 let rt = tokio::runtime::Runtime::new().map_err(UniError::Io)?;
27 Ok(Self {
28 inner: Some(inner),
29 rt,
30 })
31 }
32
33 pub fn in_memory() -> Result<Self> {
35 let rt = tokio::runtime::Runtime::new().map_err(UniError::Io)?;
36 let inner = rt.block_on(Uni::in_memory().build())?;
37 Ok(Self {
38 inner: Some(inner),
39 rt,
40 })
41 }
42
43 fn inner(&self) -> &Uni {
44 self.inner.as_ref().expect("UniSync already shut down")
45 }
46
47 pub fn session(&self) -> SessionSync<'_> {
49 SessionSync {
50 session: self.inner().session(),
51 rt: &self.rt,
52 }
53 }
54
55 pub fn schema_meta(&self) -> Arc<Schema> {
56 self.inner().schema().current()
57 }
58
59 pub fn schema(&self) -> SchemaBuilderSync<'_> {
60 SchemaBuilderSync {
61 inner: self.inner().schema(),
62 rt: &self.rt,
63 }
64 }
65
66 pub fn shutdown(mut self) -> Result<()> {
71 if let Some(uni) = self.inner.take() {
73 let result = self.rt.block_on(uni.shutdown());
74
75 std::mem::forget(self);
78
79 result
80 } else {
81 Ok(()) }
83 }
84}
85
86impl Drop for UniSync {
87 fn drop(&mut self) {
88 if let Some(ref uni) = self.inner {
89 uni.inner.shutdown_handle.shutdown_blocking();
90 tracing::debug!("UniSync dropped");
91 }
92 }
93}
94
95pub struct SessionSync<'a> {
102 session: Session,
103 rt: &'a tokio::runtime::Runtime,
104}
105
106impl<'a> SessionSync<'a> {
107 pub fn query(&self, cypher: &str) -> Result<QueryResult> {
111 self.rt.block_on(self.session.query(cypher))
112 }
113
114 pub fn query_with<'s>(&'s self, cypher: &str) -> QueryBuilderSync<'s, 'a> {
116 QueryBuilderSync {
117 inner: self.session.query_with(cypher),
118 rt: self.rt,
119 }
120 }
121
122 pub fn locy(&self, program: &str) -> Result<LocyResult> {
126 self.rt.block_on(self.session.locy(program))
127 }
128
129 pub fn locy_with<'s>(&'s self, program: &str) -> LocyBuilderSync<'s, 'a> {
131 LocyBuilderSync {
132 inner: self.session.locy_with(program),
133 rt: self.rt,
134 }
135 }
136
137 pub fn rules(&self) -> crate::api::rule_registry::RuleRegistry<'_> {
141 self.session.rules()
142 }
143
144 pub fn compile_locy(&self, program: &str) -> Result<uni_locy::CompiledProgram> {
146 self.session.compile_locy(program)
147 }
148
149 pub fn tx(&self) -> Result<TransactionSync<'a>> {
155 let tx = self.rt.block_on(self.session.tx())?;
156 Ok(TransactionSync { tx, rt: self.rt })
157 }
158
159 pub fn tx_with(&self) -> TransactionBuilderSync<'_, 'a> {
161 TransactionBuilderSync {
162 inner: self.session.tx_with(),
163 rt: self.rt,
164 }
165 }
166
167 pub fn watch(&self) -> crate::api::notifications::CommitStream {
171 self.session.watch()
172 }
173
174 pub fn watch_with(&self) -> crate::api::notifications::WatchBuilder {
176 self.session.watch_with()
177 }
178
179 pub fn add_hook(
183 &mut self,
184 name: impl Into<String>,
185 hook: impl crate::api::hooks::SessionHook + 'static,
186 ) {
187 self.session.add_hook(name, hook)
188 }
189
190 pub fn remove_hook(&mut self, name: &str) -> bool {
192 self.session.remove_hook(name)
193 }
194
195 pub fn list_hooks(&self) -> Vec<String> {
197 self.session.list_hooks()
198 }
199
200 pub fn clear_hooks(&mut self) {
202 self.session.clear_hooks()
203 }
204
205 pub fn pin_to_version(&mut self, snapshot_id: &str) -> Result<()> {
209 self.rt.block_on(self.session.pin_to_version(snapshot_id))
210 }
211
212 pub fn pin_to_timestamp(&mut self, ts: chrono::DateTime<chrono::Utc>) -> Result<()> {
214 self.rt.block_on(self.session.pin_to_timestamp(ts))
215 }
216
217 pub fn refresh(&mut self) -> Result<()> {
219 self.rt.block_on(self.session.refresh())
220 }
221
222 pub fn prepare(&self, cypher: &str) -> Result<crate::api::prepared::PreparedQuery> {
226 self.rt.block_on(self.session.prepare(cypher))
227 }
228
229 pub fn prepare_locy(&self, program: &str) -> Result<crate::api::prepared::PreparedLocy> {
231 self.rt.block_on(self.session.prepare_locy(program))
232 }
233
234 pub fn params(&self) -> crate::api::session::Params<'_> {
238 self.session.params()
239 }
240
241 pub fn id(&self) -> &str {
245 self.session.id()
246 }
247
248 pub fn capabilities(&self) -> crate::api::session::SessionCapabilities {
250 self.session.capabilities()
251 }
252
253 pub fn metrics(&self) -> crate::api::session::SessionMetrics {
255 self.session.metrics()
256 }
257
258 pub fn cancel(&self) {
260 self.session.cancel()
261 }
262}
263
264pub struct QueryBuilderSync<'s, 'a> {
268 inner: QueryBuilder<'s>,
269 rt: &'a tokio::runtime::Runtime,
270}
271
272impl<'s, 'a> QueryBuilderSync<'s, 'a> {
273 pub fn param<K: Into<String>, V: Into<Value>>(mut self, key: K, value: V) -> Self {
275 self.inner = self.inner.param(key, value);
276 self
277 }
278
279 pub fn params<'p>(mut self, params: impl IntoIterator<Item = (&'p str, Value)>) -> Self {
281 self.inner = self.inner.params(params);
282 self
283 }
284
285 pub fn timeout(mut self, duration: std::time::Duration) -> Self {
287 self.inner = self.inner.timeout(duration);
288 self
289 }
290
291 pub fn max_memory(mut self, bytes: usize) -> Self {
293 self.inner = self.inner.max_memory(bytes);
294 self
295 }
296
297 pub fn fetch_all(self) -> Result<QueryResult> {
299 self.rt.block_on(self.inner.fetch_all())
300 }
301
302 pub fn fetch_one(self) -> Result<Option<Row>> {
304 self.rt.block_on(self.inner.fetch_one())
305 }
306}
307
308pub struct LocyBuilderSync<'s, 'a> {
312 inner: LocyBuilder<'s>,
313 rt: &'a tokio::runtime::Runtime,
314}
315
316impl<'s, 'a> LocyBuilderSync<'s, 'a> {
317 pub fn param(mut self, name: &str, value: impl Into<Value>) -> Self {
319 self.inner = self.inner.param(name, value);
320 self
321 }
322
323 pub fn params<'p>(mut self, params: impl IntoIterator<Item = (&'p str, Value)>) -> Self {
325 self.inner = self.inner.params(params);
326 self
327 }
328
329 pub fn timeout(mut self, duration: std::time::Duration) -> Self {
331 self.inner = self.inner.timeout(duration);
332 self
333 }
334
335 pub fn max_iterations(mut self, n: usize) -> Self {
337 self.inner = self.inner.max_iterations(n);
338 self
339 }
340
341 pub fn with_config(mut self, config: uni_locy::LocyConfig) -> Self {
343 self.inner = self.inner.with_config(config);
344 self
345 }
346
347 pub fn run(self) -> Result<LocyResult> {
349 self.rt.block_on(self.inner.run())
350 }
351}
352
353pub struct TransactionSync<'a> {
356 tx: Transaction,
357 rt: &'a tokio::runtime::Runtime,
358}
359
360impl<'a> TransactionSync<'a> {
361 pub fn query(&self, cypher: &str) -> Result<QueryResult> {
362 self.rt.block_on(self.tx.query(cypher))
363 }
364
365 pub fn query_with<'t>(&'t self, cypher: &str) -> TxQueryBuilderSync<'t, 'a> {
367 TxQueryBuilderSync {
368 inner: self.tx.query_with(cypher),
369 rt: self.rt,
370 }
371 }
372
373 pub fn execute(&self, cypher: &str) -> Result<ExecuteResult> {
374 self.rt.block_on(self.tx.execute(cypher))
375 }
376
377 pub fn execute_with<'t>(&'t self, cypher: &str) -> ExecuteBuilderSync<'t, 'a> {
379 ExecuteBuilderSync {
380 inner: self.tx.execute_with(cypher),
381 rt: self.rt,
382 }
383 }
384
385 pub fn locy(&self, program: &str) -> Result<LocyResult> {
387 self.rt.block_on(self.tx.locy(program))
388 }
389
390 pub fn locy_with<'t>(&'t self, program: &str) -> TxLocyBuilderSync<'t, 'a> {
392 TxLocyBuilderSync {
393 inner: self.tx.locy_with(program),
394 rt: self.rt,
395 }
396 }
397
398 pub fn apply(&self, derived: DerivedFactSet) -> Result<ApplyResult> {
400 self.rt.block_on(self.tx.apply(derived))
401 }
402
403 pub fn apply_with(&self, derived: DerivedFactSet) -> ApplyBuilderSync<'_, 'a> {
405 ApplyBuilderSync {
406 inner: self.tx.apply_with(derived),
407 rt: self.rt,
408 }
409 }
410
411 pub fn prepare(&self, cypher: &str) -> Result<crate::api::prepared::PreparedQuery> {
413 self.rt.block_on(self.tx.prepare(cypher))
414 }
415
416 pub fn prepare_locy(&self, program: &str) -> Result<crate::api::prepared::PreparedLocy> {
418 self.rt.block_on(self.tx.prepare_locy(program))
419 }
420
421 pub fn commit(self) -> Result<CommitResult> {
422 self.rt.block_on(self.tx.commit())
423 }
424
425 pub fn rollback(self) {
426 self.tx.rollback()
427 }
428
429 pub fn bulk_writer(&self) -> crate::api::bulk::BulkWriterBuilder {
431 self.tx.bulk_writer()
432 }
433
434 pub fn appender(&self, label: &str) -> crate::api::appender::AppenderBuilder {
436 self.tx.appender(label)
437 }
438
439 pub fn bulk_insert_vertices(
441 &self,
442 label: &str,
443 properties_list: Vec<uni_common::Properties>,
444 ) -> Result<Vec<uni_common::core::id::Vid>> {
445 self.rt
446 .block_on(self.tx.bulk_insert_vertices(label, properties_list))
447 }
448
449 pub fn bulk_insert_edges(
451 &self,
452 edge_type: &str,
453 edges: Vec<(
454 uni_common::core::id::Vid,
455 uni_common::core::id::Vid,
456 uni_common::Properties,
457 )>,
458 ) -> Result<()> {
459 self.rt
460 .block_on(self.tx.bulk_insert_edges(edge_type, edges))
461 }
462
463 pub fn is_dirty(&self) -> bool {
465 self.tx.is_dirty()
466 }
467
468 pub fn id(&self) -> &str {
470 self.tx.id()
471 }
472}
473
474pub struct ExecuteBuilderSync<'t, 'a> {
478 inner: crate::api::transaction::ExecuteBuilder<'t>,
479 rt: &'a tokio::runtime::Runtime,
480}
481
482impl<'t, 'a> ExecuteBuilderSync<'t, 'a> {
483 pub fn param<K: Into<String>, V: Into<Value>>(mut self, key: K, value: V) -> Self {
485 self.inner = self.inner.param(key, value);
486 self
487 }
488
489 pub fn params<'p>(mut self, params: impl IntoIterator<Item = (&'p str, Value)>) -> Self {
491 self.inner = self.inner.params(params);
492 self
493 }
494
495 pub fn timeout(mut self, duration: std::time::Duration) -> Self {
497 self.inner = self.inner.timeout(duration);
498 self
499 }
500
501 pub fn run(self) -> Result<ExecuteResult> {
503 self.rt.block_on(self.inner.run())
504 }
505}
506
507pub struct TransactionBuilderSync<'s, 'a> {
511 inner: TransactionBuilder<'s>,
512 rt: &'a tokio::runtime::Runtime,
513}
514
515impl<'s, 'a> TransactionBuilderSync<'s, 'a> {
516 pub fn timeout(mut self, d: std::time::Duration) -> Self {
518 self.inner = self.inner.timeout(d);
519 self
520 }
521
522 pub fn isolation(mut self, level: crate::api::transaction::IsolationLevel) -> Self {
524 self.inner = self.inner.isolation(level);
525 self
526 }
527
528 pub fn start(self) -> Result<TransactionSync<'a>> {
530 let tx = self.rt.block_on(self.inner.start())?;
531 Ok(TransactionSync { tx, rt: self.rt })
532 }
533}
534
535pub struct TxQueryBuilderSync<'t, 'a> {
539 inner: TxQueryBuilder<'t>,
540 rt: &'a tokio::runtime::Runtime,
541}
542
543impl<'t, 'a> TxQueryBuilderSync<'t, 'a> {
544 pub fn param(mut self, name: &str, value: impl Into<Value>) -> Self {
546 self.inner = self.inner.param(name, value);
547 self
548 }
549
550 pub fn execute(self) -> Result<ExecuteResult> {
552 self.rt.block_on(self.inner.execute())
553 }
554
555 pub fn fetch_all(self) -> Result<QueryResult> {
557 self.rt.block_on(self.inner.fetch_all())
558 }
559
560 pub fn fetch_one(self) -> Result<Option<Row>> {
562 self.rt.block_on(self.inner.fetch_one())
563 }
564}
565
566pub struct ApplyBuilderSync<'t, 'a> {
570 inner: ApplyBuilder<'t>,
571 rt: &'a tokio::runtime::Runtime,
572}
573
574impl<'t, 'a> ApplyBuilderSync<'t, 'a> {
575 pub fn require_fresh(mut self) -> Self {
577 self.inner = self.inner.require_fresh();
578 self
579 }
580
581 pub fn max_version_gap(mut self, n: u64) -> Self {
583 self.inner = self.inner.max_version_gap(n);
584 self
585 }
586
587 pub fn run(self) -> Result<ApplyResult> {
589 self.rt.block_on(self.inner.run())
590 }
591}
592
593pub struct TxLocyBuilderSync<'t, 'a> {
597 inner: TxLocyBuilder<'t>,
598 rt: &'a tokio::runtime::Runtime,
599}
600
601impl<'t, 'a> TxLocyBuilderSync<'t, 'a> {
602 pub fn param(mut self, name: &str, value: impl Into<Value>) -> Self {
604 self.inner = self.inner.param(name, value);
605 self
606 }
607
608 pub fn params<'p>(mut self, params: impl IntoIterator<Item = (&'p str, Value)>) -> Self {
610 self.inner = self.inner.params(params);
611 self
612 }
613
614 pub fn timeout(mut self, duration: std::time::Duration) -> Self {
616 self.inner = self.inner.timeout(duration);
617 self
618 }
619
620 pub fn max_iterations(mut self, n: usize) -> Self {
622 self.inner = self.inner.max_iterations(n);
623 self
624 }
625
626 pub fn with_config(mut self, config: uni_locy::LocyConfig) -> Self {
628 self.inner = self.inner.with_config(config);
629 self
630 }
631
632 pub fn run(self) -> Result<LocyResult> {
634 self.rt.block_on(self.inner.run())
635 }
636}
637
638pub struct SchemaBuilderSync<'a> {
641 inner: crate::api::schema::SchemaBuilder<'a>,
642 rt: &'a tokio::runtime::Runtime,
643}
644
645impl<'a> SchemaBuilderSync<'a> {
646 pub fn label(self, name: &str) -> LabelBuilderSync<'a> {
647 LabelBuilderSync {
648 inner: self.inner.label(name),
649 rt: self.rt,
650 }
651 }
652
653 pub fn edge_type(self, name: &str, from: &[&str], to: &[&str]) -> EdgeTypeBuilderSync<'a> {
654 EdgeTypeBuilderSync {
655 inner: self.inner.edge_type(name, from, to),
656 rt: self.rt,
657 }
658 }
659
660 pub fn apply(self) -> Result<()> {
661 self.rt.block_on(self.inner.apply())
662 }
663}
664
665pub struct LabelBuilderSync<'a> {
666 inner: crate::api::schema::LabelBuilder<'a>,
667 rt: &'a tokio::runtime::Runtime,
668}
669
670impl<'a> LabelBuilderSync<'a> {
671 pub fn property(mut self, name: &str, data_type: DataType) -> Self {
672 self.inner = self.inner.property(name, data_type);
673 self
674 }
675
676 pub fn property_nullable(mut self, name: &str, data_type: DataType) -> Self {
677 self.inner = self.inner.property_nullable(name, data_type);
678 self
679 }
680
681 pub fn vector(mut self, name: &str, dimensions: usize) -> Self {
682 self.inner = self.inner.vector(name, dimensions);
683 self
684 }
685
686 pub fn done(self) -> SchemaBuilderSync<'a> {
687 SchemaBuilderSync {
688 inner: self.inner.done(),
689 rt: self.rt,
690 }
691 }
692
693 pub fn label(self, name: &str) -> LabelBuilderSync<'a> {
694 self.done().label(name)
695 }
696
697 pub fn apply(self) -> Result<()> {
698 self.rt.block_on(self.inner.apply())
699 }
700}
701
702pub struct EdgeTypeBuilderSync<'a> {
703 inner: crate::api::schema::EdgeTypeBuilder<'a>,
704 rt: &'a tokio::runtime::Runtime,
705}
706
707impl<'a> EdgeTypeBuilderSync<'a> {
708 pub fn property(mut self, name: &str, data_type: DataType) -> Self {
709 self.inner = self.inner.property(name, data_type);
710 self
711 }
712
713 pub fn property_nullable(mut self, name: &str, data_type: DataType) -> Self {
714 self.inner = self.inner.property_nullable(name, data_type);
715 self
716 }
717
718 pub fn done(self) -> SchemaBuilderSync<'a> {
719 SchemaBuilderSync {
720 inner: self.inner.done(),
721 rt: self.rt,
722 }
723 }
724
725 pub fn apply(self) -> Result<()> {
726 self.rt.block_on(self.inner.apply())
727 }
728}