slatedb 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +31 -0
- data/ext/slatedb/Cargo.toml +1 -1
- data/ext/slatedb/src/admin.rs +21 -0
- data/ext/slatedb/src/database.rs +118 -40
- data/ext/slatedb/src/transaction.rs +21 -8
- data/ext/slatedb/src/write_batch.rs +2 -2
- data/lib/slatedb/admin.rb +28 -0
- data/lib/slatedb/database.rb +58 -0
- data/lib/slatedb/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dd1077018f7a8738545fc60b626a0e51d3240ae4141d9616787bf642489a22bc
|
|
4
|
+
data.tar.gz: 7aea1d1d0f9e1e3ee349d742246b7f89353ab8af39a6aca12d3167d7064d9023
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2fcbdc5f116120c4d06bb857407047505a5ca5c526a9c8209cb06411635adc506b9a634024db9152c23f5b98f46d9600d2cf21d4826cf5a947b335cb72449eb2
|
|
7
|
+
data.tar.gz: e40b8fde694ca637e5ab80d529e161eefe8901cf478a768ebbc2ddd35b9cc16f42e8858feb4cd149333e7e3db6f4ee977770485390c56303ba8dba3fd88803ff
|
data/README.md
CHANGED
|
@@ -561,8 +561,19 @@ admin.run_gc(min_age: 3600_000) # Set min age for all directorie
|
|
|
561
561
|
admin.run_gc(manifest_min_age: 86400_000) # Custom age for manifest (1 day)
|
|
562
562
|
admin.run_gc(wal_min_age: 60_000) # Custom age for WAL (1 minute)
|
|
563
563
|
admin.run_gc(compacted_min_age: 60_000) # Custom age for compacted (1 minute)
|
|
564
|
+
|
|
565
|
+
# Delete a database (SlateDB >= 0.16.0)
|
|
566
|
+
would_delete = admin.delete_db # Dry run: returns the object paths
|
|
567
|
+
# that *would* be deleted, deleting nothing
|
|
568
|
+
deleted = admin.delete_db(confirm: true) # Actually delete; returns the removed paths
|
|
564
569
|
```
|
|
565
570
|
|
|
571
|
+
`delete_db` is idempotent, and a confirmed delete of a directory that is not a
|
|
572
|
+
SlateDB database (no manifest and no in-progress deletion marker) is refused, so
|
|
573
|
+
a mistyped path cannot wipe an unrelated directory. For a cloned database, any
|
|
574
|
+
checkpoints it pinned in parent databases are stripped before its own objects
|
|
575
|
+
are removed.
|
|
576
|
+
|
|
566
577
|
### Flushing
|
|
567
578
|
|
|
568
579
|
Ensure all writes are persisted:
|
|
@@ -572,6 +583,26 @@ db.put("key", "value")
|
|
|
572
583
|
db.flush
|
|
573
584
|
```
|
|
574
585
|
|
|
586
|
+
By default, `flush` flushes the write-ahead log (WAL) if enabled, otherwise the
|
|
587
|
+
memtable. You can choose explicitly with `flush_type:` (SlateDB >= 0.16.0):
|
|
588
|
+
|
|
589
|
+
```ruby
|
|
590
|
+
db.flush(flush_type: :wal) # Flush the write-ahead log
|
|
591
|
+
db.flush(flush_type: :memtable) # Freeze and flush memtable entries to object storage
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
### Closing
|
|
595
|
+
|
|
596
|
+
Closing flushes the active memtable first by default, so durable writes are not
|
|
597
|
+
lost. You can control the final flush when closing (SlateDB >= 0.16.0):
|
|
598
|
+
|
|
599
|
+
```ruby
|
|
600
|
+
db.close # Flush the memtable, then close (default)
|
|
601
|
+
db.close(flush_type: :wal) # Flush the WAL before closing
|
|
602
|
+
db.close(flush: false) # Close without a final flush; writes that are not
|
|
603
|
+
# yet durable may be lost
|
|
604
|
+
```
|
|
605
|
+
|
|
575
606
|
## Thread Safety
|
|
576
607
|
|
|
577
608
|
**SlateDB is fully thread-safe and optimized for concurrent access.**
|
data/ext/slatedb/Cargo.toml
CHANGED
|
@@ -11,7 +11,7 @@ name = "slatedb"
|
|
|
11
11
|
crate-type = ["cdylib"]
|
|
12
12
|
|
|
13
13
|
[dependencies]
|
|
14
|
-
slatedb = "0.
|
|
14
|
+
slatedb = "0.16.0"
|
|
15
15
|
magnus = { version = "0.8.2", features = ["rb-sys"] }
|
|
16
16
|
rb-sys = { version = "0.9.128", features = ["stable-api-compiled-fallback"] }
|
|
17
17
|
tokio = { version = "1.52.3", features = ["rt-multi-thread", "sync"] }
|
data/ext/slatedb/src/admin.rs
CHANGED
|
@@ -265,6 +265,26 @@ impl Admin {
|
|
|
265
265
|
|
|
266
266
|
Ok(())
|
|
267
267
|
}
|
|
268
|
+
|
|
269
|
+
/// Delete a database, stripping any checkpoints it pinned in parent
|
|
270
|
+
/// databases (for clones) before removing its own objects (SlateDB >= 0.16.0).
|
|
271
|
+
///
|
|
272
|
+
/// # Arguments
|
|
273
|
+
/// * `confirm` - When `false` (the default), performs a dry run and returns
|
|
274
|
+
/// the list of object paths that *would* be deleted without touching
|
|
275
|
+
/// anything. When `true`, actually deletes and returns the object paths
|
|
276
|
+
/// that were removed.
|
|
277
|
+
///
|
|
278
|
+
/// A `confirm` delete of a directory with neither a manifest nor a leftover
|
|
279
|
+
/// `.deleting` marker is refused, so an incorrect path cannot wipe an
|
|
280
|
+
/// unrelated directory. The operation is idempotent.
|
|
281
|
+
///
|
|
282
|
+
/// # Returns
|
|
283
|
+
/// An array of object paths (deleted, or that would be deleted for a dry run).
|
|
284
|
+
pub fn delete_db(&self, confirm: bool) -> Result<Vec<String>, Error> {
|
|
285
|
+
let deleted = block_on_result(async { self.inner.delete_db(confirm).await })?;
|
|
286
|
+
Ok(deleted)
|
|
287
|
+
}
|
|
268
288
|
}
|
|
269
289
|
|
|
270
290
|
/// Define the Admin class on the SlateDb module.
|
|
@@ -282,6 +302,7 @@ pub fn define_admin_class(ruby: &Ruby, module: &magnus::RModule) -> Result<(), E
|
|
|
282
302
|
class.define_method("_refresh_checkpoint", method!(Admin::refresh_checkpoint, 2))?;
|
|
283
303
|
class.define_method("_delete_checkpoint", method!(Admin::delete_checkpoint, 1))?;
|
|
284
304
|
class.define_method("_run_gc", method!(Admin::run_gc, 1))?;
|
|
305
|
+
class.define_method("_delete_db", method!(Admin::delete_db, 1))?;
|
|
285
306
|
|
|
286
307
|
Ok(())
|
|
287
308
|
}
|
data/ext/slatedb/src/database.rs
CHANGED
|
@@ -4,7 +4,8 @@ use std::sync::{Arc, Mutex};
|
|
|
4
4
|
use magnus::prelude::*;
|
|
5
5
|
use magnus::{function, method, Error, RHash, Ruby};
|
|
6
6
|
use slatedb::config::{
|
|
7
|
-
|
|
7
|
+
CloseOptions, DurabilityLevel, FlushOptions, FlushType, MergeOptions, PutOptions, ReadOptions,
|
|
8
|
+
ScanOptions, Ttl, WriteOptions,
|
|
8
9
|
};
|
|
9
10
|
use slatedb::object_store::memory::InMemory;
|
|
10
11
|
use slatedb::{Db, IsolationLevel, IterationOrder, KeyValue};
|
|
@@ -79,13 +80,32 @@ impl Database {
|
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
fn write_options_from_kwargs(kwargs: &RHash) -> Result<WriteOptions, Error> {
|
|
82
|
-
let await_durable = get_optional::<bool>(kwargs, "await_durable")?.unwrap_or(true);
|
|
83
83
|
let seqnum = get_optional::<u64>(kwargs, "seqnum")?.unwrap_or(0);
|
|
84
84
|
|
|
85
|
-
Ok(WriteOptions {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
Ok(WriteOptions { seqnum })
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/// Parse the `await_durable` keyword argument (defaults to `true`).
|
|
89
|
+
///
|
|
90
|
+
/// As of SlateDB 0.16.0, `await_durable` is no longer a `WriteOptions`
|
|
91
|
+
/// field. Write methods return immediately after updating the in-memory
|
|
92
|
+
/// WAL/MemTable and hand back a `WriteHandle`; blocking until the write is
|
|
93
|
+
/// durable in object storage is done by awaiting that handle. This helper
|
|
94
|
+
/// preserves the previous ergonomic `await_durable:` behavior for callers.
|
|
95
|
+
fn await_durable_from_kwargs(kwargs: &RHash) -> Result<bool, Error> {
|
|
96
|
+
Ok(get_optional::<bool>(kwargs, "await_durable")?.unwrap_or(true))
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/// Parse a `flush_type` name into a SlateDB `FlushType` (SlateDB >= 0.16.0).
|
|
100
|
+
fn parse_flush_type(name: &str) -> Result<FlushType, Error> {
|
|
101
|
+
match name {
|
|
102
|
+
"wal" => Ok(FlushType::Wal),
|
|
103
|
+
"memtable" | "mem_table" => Ok(FlushType::MemTable),
|
|
104
|
+
other => Err(invalid_argument_error(&format!(
|
|
105
|
+
"invalid flush_type: {} (expected 'wal' or 'memtable')",
|
|
106
|
+
other
|
|
107
|
+
))),
|
|
108
|
+
}
|
|
89
109
|
}
|
|
90
110
|
|
|
91
111
|
/// Open a database at the given path.
|
|
@@ -249,16 +269,14 @@ impl Database {
|
|
|
249
269
|
}
|
|
250
270
|
|
|
251
271
|
let put_opts = PutOptions { ttl: Ttl::Default };
|
|
252
|
-
|
|
253
|
-
let write_opts = WriteOptions {
|
|
254
|
-
await_durable: true,
|
|
255
|
-
seqnum: 0,
|
|
256
|
-
};
|
|
272
|
+
let write_opts = WriteOptions::default();
|
|
257
273
|
|
|
258
274
|
block_on_result(async {
|
|
259
|
-
self
|
|
275
|
+
let handle = self
|
|
276
|
+
.inner
|
|
260
277
|
.put_with_options(key.as_bytes(), value.as_bytes(), &put_opts, &write_opts)
|
|
261
|
-
.await
|
|
278
|
+
.await?;
|
|
279
|
+
handle.await_durable().await
|
|
262
280
|
})?;
|
|
263
281
|
self.increment_metric("db.put.count");
|
|
264
282
|
|
|
@@ -280,18 +298,23 @@ impl Database {
|
|
|
280
298
|
let ttl = get_optional::<u64>(&kwargs, "ttl")?;
|
|
281
299
|
let put_opts = PutOptions {
|
|
282
300
|
ttl: match ttl {
|
|
283
|
-
Some(ms) => Ttl::
|
|
301
|
+
Some(ms) => Ttl::ExpireAfterMillis(ms),
|
|
284
302
|
None => Ttl::Default,
|
|
285
303
|
},
|
|
286
304
|
};
|
|
287
305
|
|
|
288
|
-
// Parse await_durable
|
|
289
306
|
let write_opts = Self::write_options_from_kwargs(&kwargs)?;
|
|
307
|
+
let await_durable = Self::await_durable_from_kwargs(&kwargs)?;
|
|
290
308
|
|
|
291
309
|
block_on_result(async {
|
|
292
|
-
self
|
|
310
|
+
let handle = self
|
|
311
|
+
.inner
|
|
293
312
|
.put_with_options(key.as_bytes(), value.as_bytes(), &put_opts, &write_opts)
|
|
294
|
-
.await
|
|
313
|
+
.await?;
|
|
314
|
+
if await_durable {
|
|
315
|
+
handle.await_durable().await?;
|
|
316
|
+
}
|
|
317
|
+
Ok(())
|
|
295
318
|
})?;
|
|
296
319
|
self.increment_metric("db.put_with_options.count");
|
|
297
320
|
|
|
@@ -307,15 +330,14 @@ impl Database {
|
|
|
307
330
|
return Err(invalid_argument_error("key cannot be empty"));
|
|
308
331
|
}
|
|
309
332
|
|
|
310
|
-
let write_opts = WriteOptions
|
|
311
|
-
await_durable: true,
|
|
312
|
-
seqnum: 0,
|
|
313
|
-
};
|
|
333
|
+
let write_opts = WriteOptions::default();
|
|
314
334
|
|
|
315
335
|
block_on_result(async {
|
|
316
|
-
self
|
|
336
|
+
let handle = self
|
|
337
|
+
.inner
|
|
317
338
|
.delete_with_options(key.as_bytes(), &write_opts)
|
|
318
|
-
.await
|
|
339
|
+
.await?;
|
|
340
|
+
handle.await_durable().await
|
|
319
341
|
})?;
|
|
320
342
|
self.increment_metric("db.delete.count");
|
|
321
343
|
|
|
@@ -333,11 +355,17 @@ impl Database {
|
|
|
333
355
|
}
|
|
334
356
|
|
|
335
357
|
let write_opts = Self::write_options_from_kwargs(&kwargs)?;
|
|
358
|
+
let await_durable = Self::await_durable_from_kwargs(&kwargs)?;
|
|
336
359
|
|
|
337
360
|
block_on_result(async {
|
|
338
|
-
self
|
|
361
|
+
let handle = self
|
|
362
|
+
.inner
|
|
339
363
|
.delete_with_options(key.as_bytes(), &write_opts)
|
|
340
|
-
.await
|
|
364
|
+
.await?;
|
|
365
|
+
if await_durable {
|
|
366
|
+
handle.await_durable().await?;
|
|
367
|
+
}
|
|
368
|
+
Ok(())
|
|
341
369
|
})?;
|
|
342
370
|
self.increment_metric("db.delete_with_options.count");
|
|
343
371
|
|
|
@@ -550,7 +578,10 @@ impl Database {
|
|
|
550
578
|
/// * `batch` - The WriteBatch to write
|
|
551
579
|
pub fn write(&self, batch: &WriteBatch) -> Result<(), Error> {
|
|
552
580
|
let batch_inner = batch.take()?;
|
|
553
|
-
block_on_result(async {
|
|
581
|
+
block_on_result(async {
|
|
582
|
+
let handle = self.inner.write(batch_inner).await?;
|
|
583
|
+
handle.await_durable().await
|
|
584
|
+
})?;
|
|
554
585
|
Ok(())
|
|
555
586
|
}
|
|
556
587
|
|
|
@@ -561,13 +592,19 @@ impl Database {
|
|
|
561
592
|
/// * `kwargs` - Keyword arguments (await_durable, seqnum)
|
|
562
593
|
pub fn write_with_options(&self, batch: &WriteBatch, kwargs: RHash) -> Result<(), Error> {
|
|
563
594
|
let write_opts = Self::write_options_from_kwargs(&kwargs)?;
|
|
595
|
+
let await_durable = Self::await_durable_from_kwargs(&kwargs)?;
|
|
564
596
|
|
|
565
597
|
let batch_inner = batch.take()?;
|
|
566
598
|
|
|
567
599
|
block_on_result(async {
|
|
568
|
-
self
|
|
600
|
+
let handle = self
|
|
601
|
+
.inner
|
|
569
602
|
.write_with_options(batch_inner, &write_opts)
|
|
570
|
-
.await
|
|
603
|
+
.await?;
|
|
604
|
+
if await_durable {
|
|
605
|
+
handle.await_durable().await?;
|
|
606
|
+
}
|
|
607
|
+
Ok(())
|
|
571
608
|
})?;
|
|
572
609
|
|
|
573
610
|
Ok(())
|
|
@@ -584,16 +621,14 @@ impl Database {
|
|
|
584
621
|
}
|
|
585
622
|
|
|
586
623
|
let merge_opts = MergeOptions { ttl: Ttl::Default };
|
|
587
|
-
|
|
588
|
-
let write_opts = WriteOptions {
|
|
589
|
-
await_durable: true,
|
|
590
|
-
seqnum: 0,
|
|
591
|
-
};
|
|
624
|
+
let write_opts = WriteOptions::default();
|
|
592
625
|
|
|
593
626
|
block_on_result(async {
|
|
594
|
-
self
|
|
627
|
+
let handle = self
|
|
628
|
+
.inner
|
|
595
629
|
.merge_with_options(key.as_bytes(), value.as_bytes(), &merge_opts, &write_opts)
|
|
596
|
-
.await
|
|
630
|
+
.await?;
|
|
631
|
+
handle.await_durable().await
|
|
597
632
|
})?;
|
|
598
633
|
|
|
599
634
|
Ok(())
|
|
@@ -618,17 +653,23 @@ impl Database {
|
|
|
618
653
|
let ttl = get_optional::<u64>(&kwargs, "ttl")?;
|
|
619
654
|
let merge_opts = MergeOptions {
|
|
620
655
|
ttl: match ttl {
|
|
621
|
-
Some(ms) => Ttl::
|
|
656
|
+
Some(ms) => Ttl::ExpireAfterMillis(ms),
|
|
622
657
|
None => Ttl::Default,
|
|
623
658
|
},
|
|
624
659
|
};
|
|
625
660
|
|
|
626
661
|
let write_opts = Self::write_options_from_kwargs(&kwargs)?;
|
|
662
|
+
let await_durable = Self::await_durable_from_kwargs(&kwargs)?;
|
|
627
663
|
|
|
628
664
|
block_on_result(async {
|
|
629
|
-
self
|
|
665
|
+
let handle = self
|
|
666
|
+
.inner
|
|
630
667
|
.merge_with_options(key.as_bytes(), value.as_bytes(), &merge_opts, &write_opts)
|
|
631
|
-
.await
|
|
668
|
+
.await?;
|
|
669
|
+
if await_durable {
|
|
670
|
+
handle.await_durable().await?;
|
|
671
|
+
}
|
|
672
|
+
Ok(())
|
|
632
673
|
})?;
|
|
633
674
|
|
|
634
675
|
Ok(())
|
|
@@ -708,6 +749,19 @@ impl Database {
|
|
|
708
749
|
Ok(())
|
|
709
750
|
}
|
|
710
751
|
|
|
752
|
+
/// Flush the database, choosing the flush type (SlateDB >= 0.16.0).
|
|
753
|
+
///
|
|
754
|
+
/// # Arguments
|
|
755
|
+
/// * `flush_type` - "wal" to flush the WAL, or "memtable" to freeze and
|
|
756
|
+
/// flush memtable entries to object storage.
|
|
757
|
+
pub fn flush_with_options(&self, flush_type: String) -> Result<(), Error> {
|
|
758
|
+
let options = FlushOptions {
|
|
759
|
+
flush_type: Self::parse_flush_type(&flush_type)?,
|
|
760
|
+
};
|
|
761
|
+
block_on_result(async { self.inner.flush_with_options(options).await })?;
|
|
762
|
+
Ok(())
|
|
763
|
+
}
|
|
764
|
+
|
|
711
765
|
/// Return the database metrics registry.
|
|
712
766
|
pub fn metrics(&self) -> Result<Metrics, Error> {
|
|
713
767
|
Ok(Metrics::new(self.metrics.clone()))
|
|
@@ -718,6 +772,22 @@ impl Database {
|
|
|
718
772
|
block_on_result(async { self.inner.close().await })?;
|
|
719
773
|
Ok(())
|
|
720
774
|
}
|
|
775
|
+
|
|
776
|
+
/// Close the database, controlling the final flush (SlateDB >= 0.16.0).
|
|
777
|
+
///
|
|
778
|
+
/// # Arguments
|
|
779
|
+
/// * `flush_type` - `Some("wal"|"memtable")` to flush before closing, or
|
|
780
|
+
/// `None` to close without a final flush (writes that are not yet durable
|
|
781
|
+
/// may be lost).
|
|
782
|
+
pub fn close_with_options(&self, flush_type: Option<String>) -> Result<(), Error> {
|
|
783
|
+
let flush_type = match flush_type {
|
|
784
|
+
Some(name) => Some(Self::parse_flush_type(&name)?),
|
|
785
|
+
None => None,
|
|
786
|
+
};
|
|
787
|
+
let options = CloseOptions { flush_type };
|
|
788
|
+
block_on_result(async { self.inner.close_with_options(options).await })?;
|
|
789
|
+
Ok(())
|
|
790
|
+
}
|
|
721
791
|
}
|
|
722
792
|
|
|
723
793
|
/// Define the Database class on the SlateDb module.
|
|
@@ -772,9 +842,17 @@ pub fn define_database_class(ruby: &Ruby, module: &magnus::RModule) -> Result<()
|
|
|
772
842
|
"_create_checkpoint",
|
|
773
843
|
method!(Database::create_checkpoint, 1),
|
|
774
844
|
)?;
|
|
775
|
-
class.define_method("
|
|
845
|
+
class.define_method("_flush", method!(Database::flush, 0))?;
|
|
846
|
+
class.define_method(
|
|
847
|
+
"_flush_with_options",
|
|
848
|
+
method!(Database::flush_with_options, 1),
|
|
849
|
+
)?;
|
|
776
850
|
class.define_method("_metrics", method!(Database::metrics, 0))?;
|
|
777
|
-
class.define_method("
|
|
851
|
+
class.define_method("_close", method!(Database::close, 0))?;
|
|
852
|
+
class.define_method(
|
|
853
|
+
"_close_with_options",
|
|
854
|
+
method!(Database::close_with_options, 1),
|
|
855
|
+
)?;
|
|
778
856
|
|
|
779
857
|
Ok(())
|
|
780
858
|
}
|
|
@@ -109,7 +109,7 @@ impl Transaction {
|
|
|
109
109
|
let ttl = get_optional::<u64>(&kwargs, "ttl")?;
|
|
110
110
|
let put_opts = PutOptions {
|
|
111
111
|
ttl: match ttl {
|
|
112
|
-
Some(ms) => Ttl::
|
|
112
|
+
Some(ms) => Ttl::ExpireAfterMillis(ms),
|
|
113
113
|
None => Ttl::Default,
|
|
114
114
|
},
|
|
115
115
|
};
|
|
@@ -172,7 +172,7 @@ impl Transaction {
|
|
|
172
172
|
let ttl = get_optional::<u64>(&kwargs, "ttl")?;
|
|
173
173
|
let merge_opts = MergeOptions {
|
|
174
174
|
ttl: match ttl {
|
|
175
|
-
Some(ms) => Ttl::
|
|
175
|
+
Some(ms) => Ttl::ExpireAfterMillis(ms),
|
|
176
176
|
None => Ttl::Default,
|
|
177
177
|
},
|
|
178
178
|
};
|
|
@@ -395,7 +395,16 @@ impl Transaction {
|
|
|
395
395
|
.take()
|
|
396
396
|
.ok_or_else(|| closed_error("transaction is closed"))?;
|
|
397
397
|
|
|
398
|
-
block_on_result(async {
|
|
398
|
+
block_on_result(async {
|
|
399
|
+
// As of SlateDB 0.16.0, commit returns as soon as the write is in
|
|
400
|
+
// memory and hands back an optional WriteHandle (None for an empty
|
|
401
|
+
// or read-only transaction). Await durability to preserve the
|
|
402
|
+
// previous blocking-commit behavior.
|
|
403
|
+
if let Some(handle) = txn.commit().await? {
|
|
404
|
+
handle.await_durable().await?;
|
|
405
|
+
}
|
|
406
|
+
Ok(())
|
|
407
|
+
})?;
|
|
399
408
|
Ok(())
|
|
400
409
|
}
|
|
401
410
|
|
|
@@ -403,10 +412,7 @@ impl Transaction {
|
|
|
403
412
|
pub fn commit_with_options(&self, kwargs: RHash) -> Result<(), Error> {
|
|
404
413
|
let await_durable = get_optional::<bool>(&kwargs, "await_durable")?.unwrap_or(true);
|
|
405
414
|
let seqnum = get_optional::<u64>(&kwargs, "seqnum")?.unwrap_or(0);
|
|
406
|
-
let write_opts = WriteOptions {
|
|
407
|
-
await_durable,
|
|
408
|
-
seqnum,
|
|
409
|
-
};
|
|
415
|
+
let write_opts = WriteOptions { seqnum };
|
|
410
416
|
|
|
411
417
|
let txn = self
|
|
412
418
|
.inner
|
|
@@ -414,7 +420,14 @@ impl Transaction {
|
|
|
414
420
|
.take()
|
|
415
421
|
.ok_or_else(|| closed_error("transaction is closed"))?;
|
|
416
422
|
|
|
417
|
-
block_on_result(async {
|
|
423
|
+
block_on_result(async {
|
|
424
|
+
if let Some(handle) = txn.commit_with_options(&write_opts).await? {
|
|
425
|
+
if await_durable {
|
|
426
|
+
handle.await_durable().await?;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
Ok(())
|
|
430
|
+
})?;
|
|
418
431
|
Ok(())
|
|
419
432
|
}
|
|
420
433
|
|
|
@@ -49,7 +49,7 @@ impl WriteBatch {
|
|
|
49
49
|
let ttl = get_optional::<u64>(&kwargs, "ttl")?;
|
|
50
50
|
let put_opts = PutOptions {
|
|
51
51
|
ttl: match ttl {
|
|
52
|
-
Some(ms) => Ttl::
|
|
52
|
+
Some(ms) => Ttl::ExpireAfterMillis(ms),
|
|
53
53
|
None => Ttl::Default,
|
|
54
54
|
},
|
|
55
55
|
};
|
|
@@ -102,7 +102,7 @@ impl WriteBatch {
|
|
|
102
102
|
let ttl = get_optional::<u64>(&kwargs, "ttl")?;
|
|
103
103
|
let merge_opts = MergeOptions {
|
|
104
104
|
ttl: match ttl {
|
|
105
|
-
Some(ms) => Ttl::
|
|
105
|
+
Some(ms) => Ttl::ExpireAfterMillis(ms),
|
|
106
106
|
None => Ttl::Default,
|
|
107
107
|
},
|
|
108
108
|
};
|
data/lib/slatedb/admin.rb
CHANGED
|
@@ -118,5 +118,33 @@ module SlateDb
|
|
|
118
118
|
opts[:min_age] = min_age if min_age
|
|
119
119
|
_run_gc(opts)
|
|
120
120
|
end
|
|
121
|
+
|
|
122
|
+
# Delete a database, removing its objects from the object store
|
|
123
|
+
# (SlateDB >= 0.16.0).
|
|
124
|
+
#
|
|
125
|
+
# For a cloned database, any checkpoints it pinned in parent databases are
|
|
126
|
+
# stripped before its own objects are removed.
|
|
127
|
+
#
|
|
128
|
+
# By default this performs a dry run: it returns the object paths that
|
|
129
|
+
# *would* be deleted without removing anything. Pass +confirm: true+ to
|
|
130
|
+
# actually delete. A confirmed delete of a directory that is not a SlateDB
|
|
131
|
+
# database (no manifest and no in-progress deletion marker) is refused, so a
|
|
132
|
+
# mistyped path cannot wipe an unrelated directory. The operation is
|
|
133
|
+
# idempotent.
|
|
134
|
+
#
|
|
135
|
+
# @param confirm [Boolean] When false (the default), performs a dry run and
|
|
136
|
+
# returns the paths that would be deleted. When true, deletes and returns
|
|
137
|
+
# the paths that were removed.
|
|
138
|
+
# @return [Array<String>] Object paths deleted (or that would be deleted)
|
|
139
|
+
#
|
|
140
|
+
# @example Preview what would be deleted
|
|
141
|
+
# admin.delete_db.each { |path| puts path }
|
|
142
|
+
#
|
|
143
|
+
# @example Actually delete the database
|
|
144
|
+
# deleted = admin.delete_db(confirm: true)
|
|
145
|
+
#
|
|
146
|
+
def delete_db(confirm: false)
|
|
147
|
+
_delete_db(confirm)
|
|
148
|
+
end
|
|
121
149
|
end
|
|
122
150
|
end
|
data/lib/slatedb/database.rb
CHANGED
|
@@ -506,5 +506,63 @@ module SlateDb
|
|
|
506
506
|
def metrics
|
|
507
507
|
_metrics
|
|
508
508
|
end
|
|
509
|
+
|
|
510
|
+
# Flush in-memory writes to object storage.
|
|
511
|
+
#
|
|
512
|
+
# With no arguments this flushes pending writes durably, matching the
|
|
513
|
+
# previous behavior. Pass +flush_type+ to control what is flushed
|
|
514
|
+
# (SlateDB >= 0.16.0).
|
|
515
|
+
#
|
|
516
|
+
# @param flush_type [Symbol, String, nil] Which data to flush: :wal to flush
|
|
517
|
+
# the write-ahead log, or :memtable to freeze and flush memtable entries
|
|
518
|
+
# to object storage. When nil (the default), SlateDB flushes the WAL if
|
|
519
|
+
# enabled, otherwise the memtable.
|
|
520
|
+
# @return [void]
|
|
521
|
+
#
|
|
522
|
+
# @example Flush pending writes
|
|
523
|
+
# db.flush
|
|
524
|
+
#
|
|
525
|
+
# @example Explicitly flush the WAL
|
|
526
|
+
# db.flush(flush_type: :wal)
|
|
527
|
+
#
|
|
528
|
+
def flush(flush_type: nil)
|
|
529
|
+
if flush_type.nil?
|
|
530
|
+
_flush
|
|
531
|
+
else
|
|
532
|
+
_flush_with_options(flush_type.to_s)
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
# Close the database.
|
|
537
|
+
#
|
|
538
|
+
# By default the active memtable is flushed before closing (matching the
|
|
539
|
+
# previous behavior). Pass +flush: false+ to close without a final flush,
|
|
540
|
+
# in which case writes that are not yet durable may be lost
|
|
541
|
+
# (SlateDB >= 0.16.0).
|
|
542
|
+
#
|
|
543
|
+
# @param flush [Boolean] Whether to flush before closing (default: true)
|
|
544
|
+
# @param flush_type [Symbol, String, nil] When flushing, which data to
|
|
545
|
+
# flush: :wal or :memtable. Defaults to :memtable. Ignored when
|
|
546
|
+
# +flush: false+.
|
|
547
|
+
# @return [void]
|
|
548
|
+
#
|
|
549
|
+
# @example Close (flushing the memtable first)
|
|
550
|
+
# db.close
|
|
551
|
+
#
|
|
552
|
+
# @example Close without flushing
|
|
553
|
+
# db.close(flush: false)
|
|
554
|
+
#
|
|
555
|
+
# @example Flush the WAL before closing
|
|
556
|
+
# db.close(flush_type: :wal)
|
|
557
|
+
#
|
|
558
|
+
def close(flush: true, flush_type: nil)
|
|
559
|
+
if !flush
|
|
560
|
+
_close_with_options(nil)
|
|
561
|
+
elsif flush_type.nil?
|
|
562
|
+
_close
|
|
563
|
+
else
|
|
564
|
+
_close_with_options(flush_type.to_s)
|
|
565
|
+
end
|
|
566
|
+
end
|
|
509
567
|
end
|
|
510
568
|
end
|
data/lib/slatedb/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: slatedb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- SlateDB Contributors
|
|
@@ -137,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
137
137
|
- !ruby/object:Gem::Version
|
|
138
138
|
version: '0'
|
|
139
139
|
requirements: []
|
|
140
|
-
rubygems_version: 4.0.
|
|
140
|
+
rubygems_version: 4.0.20
|
|
141
141
|
specification_version: 4
|
|
142
142
|
summary: Ruby bindings for SlateDB
|
|
143
143
|
test_files: []
|