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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ea58f5cc108fef4066004dce3db7641d979589c6afa56023845b4e568198630
4
- data.tar.gz: c5e52bded1c840e6d51ba420b673c5f03e3f9450dd78476dc129a45cab02b11b
3
+ metadata.gz: dd1077018f7a8738545fc60b626a0e51d3240ae4141d9616787bf642489a22bc
4
+ data.tar.gz: 7aea1d1d0f9e1e3ee349d742246b7f89353ab8af39a6aca12d3167d7064d9023
5
5
  SHA512:
6
- metadata.gz: 715e35df65d25a1487f648718ec72e593fed5e22289f47c2017aa8eac24ccda5d5df00151ec618b1d732550be2f8b6ac5d8136b9358d18c197ae11b5e437e8a9
7
- data.tar.gz: 92780ae93284906f92a4e4550d885c281af32f7cd1f91642e6ca9ebbe1f114d574d20a17be3f0605b5caaaafe64e27e70f12a96b5fcc6255fd8f0e210f0fa9b1
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.**
@@ -11,7 +11,7 @@ name = "slatedb"
11
11
  crate-type = ["cdylib"]
12
12
 
13
13
  [dependencies]
14
- slatedb = "0.15.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"] }
@@ -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
  }
@@ -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
- DurabilityLevel, MergeOptions, PutOptions, ReadOptions, ScanOptions, Ttl, WriteOptions,
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
- await_durable,
87
- seqnum,
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.inner
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::ExpireAfter(ms),
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.inner
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.inner
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.inner
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 { self.inner.write(batch_inner).await })?;
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.inner
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.inner
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::ExpireAfter(ms),
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.inner
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("flush", method!(Database::flush, 0))?;
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("close", method!(Database::close, 0))?;
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::ExpireAfter(ms),
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::ExpireAfter(ms),
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 { txn.commit().await })?;
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 { txn.commit_with_options(&write_opts).await })?;
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::ExpireAfter(ms),
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::ExpireAfter(ms),
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
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SlateDb
4
- VERSION = "0.4.4"
4
+ VERSION = "0.5.0"
5
5
  end
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.4
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.16
140
+ rubygems_version: 4.0.20
141
141
  specification_version: 4
142
142
  summary: Ruby bindings for SlateDB
143
143
  test_files: []