Skip to content

Commit 6e8e12b

Browse files
authored
Merge pull request #55 from tidesdb/0.10.0
iss #53 #54 retire unused objecttargetfilesize cf config field and ad…
2 parents 1ce235c + a2488bd commit 6e8e12b

5 files changed

Lines changed: 77 additions & 15 deletions

File tree

README.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,3 @@ Multiple licenses apply:
3131
## Contributing
3232

3333
Contributions are welcome! Please feel free to submit a Pull Request.
34-
35-
## Support
36-
37-
- [Discord](https://discord.gg/tWEmjR66cy)
38-
- [GitHub Issues](https://github.com/tidesdb/tidesdb-python/issues)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "tidesdb"
7-
version = "0.9.8"
7+
version = "0.10.0"
88
description = "Official Python bindings for TidesDB - A high-performance embedded key-value storage engine"
99
readme = "README.md"
1010
requires-python = ">=3.10"

src/tidesdb/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
TDB_ERR_READONLY,
5050
)
5151

52-
__version__ = "0.9.8"
52+
__version__ = "0.10.0"
5353
__all__ = [
5454
"TidesDB",
5555
"Transaction",

src/tidesdb/tidesdb.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ class _CColumnFamilyConfig(Structure):
212212
("use_btree", c_int),
213213
("commit_hook_fn", c_void_p),
214214
("commit_hook_ctx", c_void_p),
215-
("object_target_file_size", c_size_t),
215+
("_object_target_file_size_reserved", c_size_t),
216216
("object_lazy_compaction", c_int),
217217
("object_prefetch_compaction", c_int),
218218
]
@@ -411,6 +411,9 @@ class _CDbStats(Structure):
411411
_lib.tidesdb_txn_delete.argtypes = [c_void_p, c_void_p, POINTER(c_uint8), c_size_t]
412412
_lib.tidesdb_txn_delete.restype = c_int
413413

414+
_lib.tidesdb_txn_single_delete.argtypes = [c_void_p, c_void_p, POINTER(c_uint8), c_size_t]
415+
_lib.tidesdb_txn_single_delete.restype = c_int
416+
414417
_lib.tidesdb_txn_commit.argtypes = [c_void_p]
415418
_lib.tidesdb_txn_commit.restype = c_int
416419

@@ -657,7 +660,6 @@ class ColumnFamilyConfig:
657660
l1_file_count_trigger: int = 4
658661
l0_queue_stall_threshold: int = 20
659662
use_btree: bool = False
660-
object_target_file_size: int = 0
661663
object_lazy_compaction: bool = False
662664
object_prefetch_compaction: bool = True
663665

@@ -690,7 +692,6 @@ def _to_c_struct(self, name: str = "") -> _CColumnFamilyConfig:
690692
c_config.l1_file_count_trigger = self.l1_file_count_trigger
691693
c_config.l0_queue_stall_threshold = self.l0_queue_stall_threshold
692694
c_config.use_btree = 1 if self.use_btree else 0
693-
c_config.object_target_file_size = self.object_target_file_size
694695
c_config.object_lazy_compaction = 1 if self.object_lazy_compaction else 0
695696
c_config.object_prefetch_compaction = 1 if self.object_prefetch_compaction else 0
696697

@@ -864,7 +865,6 @@ def default_column_family_config() -> ColumnFamilyConfig:
864865
l1_file_count_trigger=c_config.l1_file_count_trigger,
865866
l0_queue_stall_threshold=c_config.l0_queue_stall_threshold,
866867
use_btree=bool(c_config.use_btree),
867-
object_target_file_size=c_config.object_target_file_size,
868868
object_lazy_compaction=bool(c_config.object_lazy_compaction),
869869
object_prefetch_compaction=bool(c_config.object_prefetch_compaction),
870870
)
@@ -927,7 +927,6 @@ def load_config_from_ini(file_path: str, cf_name: str) -> ColumnFamilyConfig:
927927
l1_file_count_trigger=c_config.l1_file_count_trigger,
928928
l0_queue_stall_threshold=c_config.l0_queue_stall_threshold,
929929
use_btree=bool(c_config.use_btree),
930-
object_target_file_size=c_config.object_target_file_size,
931930
object_lazy_compaction=bool(c_config.object_lazy_compaction),
932931
object_prefetch_compaction=bool(c_config.object_prefetch_compaction),
933932
)
@@ -1304,7 +1303,6 @@ def get_stats(self) -> Stats:
13041303
l1_file_count_trigger=c_cfg.l1_file_count_trigger,
13051304
l0_queue_stall_threshold=c_cfg.l0_queue_stall_threshold,
13061305
use_btree=bool(c_cfg.use_btree),
1307-
object_target_file_size=c_cfg.object_target_file_size,
13081306
object_lazy_compaction=bool(c_cfg.object_lazy_compaction),
13091307
object_prefetch_compaction=bool(c_cfg.object_prefetch_compaction),
13101308
)
@@ -1424,6 +1422,36 @@ def delete(self, cf: ColumnFamily, key: bytes) -> None:
14241422
if result != TDB_SUCCESS:
14251423
raise TidesDBError.from_code(result, "failed to delete key")
14261424

1425+
def single_delete(self, cf: ColumnFamily, key: bytes) -> None:
1426+
"""
1427+
Write a tombstone carrying a caller-provided promise that the key has been
1428+
put at most once since its previous single-delete (or since the start of
1429+
history). This lets compaction drop the put and the tombstone together as
1430+
soon as both appear in the same merge input, rather than carrying the
1431+
tombstone forward to the largest active level. Read semantics match delete().
1432+
1433+
The engine does not verify the promise at runtime; violating it can leave
1434+
older puts visible and is a bug in the caller. Use only for insert-once-
1435+
then-delete patterns (classic insert benchmarks, secondary indexes on
1436+
never-updated columns, log tables with scheduled purges). Not safe for
1437+
repeated updates to the same key. When in doubt, prefer delete().
1438+
1439+
Args:
1440+
cf: Column family handle
1441+
key: Key as bytes
1442+
"""
1443+
if self._closed:
1444+
raise TidesDBError("Transaction is closed")
1445+
if self._committed:
1446+
raise TidesDBError("Transaction already committed")
1447+
1448+
key_buf = (c_uint8 * len(key)).from_buffer_copy(key) if key else None
1449+
1450+
result = _lib.tidesdb_txn_single_delete(self._txn, cf._cf, key_buf, len(key))
1451+
1452+
if result != TDB_SUCCESS:
1453+
raise TidesDBError.from_code(result, "failed to single-delete key")
1454+
14271455
def commit(self) -> None:
14281456
"""Commit the transaction."""
14291457
if self._closed:

tests/test_tidesdb.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,47 @@ def test_isolation_level(self, db, cf):
198198
txn.commit()
199199
txn.close()
200200

201+
def test_single_delete(self, db, cf):
202+
"""Test single_delete behaves like delete for read semantics."""
203+
with db.begin_txn() as txn:
204+
txn.put(cf, b"sd_key", b"sd_value")
205+
txn.commit()
206+
207+
with db.begin_txn() as txn:
208+
txn.single_delete(cf, b"sd_key")
209+
txn.commit()
210+
211+
with db.begin_txn() as txn:
212+
with pytest.raises(tidesdb.TidesDBError):
213+
txn.get(cf, b"sd_key")
214+
215+
def test_single_delete_combined_with_put(self, db, cf):
216+
"""Test single_delete combined with other ops in the same transaction."""
217+
with db.begin_txn() as txn:
218+
txn.put(cf, b"sd_a", b"value_a")
219+
txn.put(cf, b"sd_b", b"value_b")
220+
txn.commit()
221+
222+
with db.begin_txn() as txn:
223+
txn.put(cf, b"sd_c", b"value_c")
224+
txn.single_delete(cf, b"sd_a")
225+
txn.commit()
226+
227+
with db.begin_txn() as txn:
228+
assert txn.get(cf, b"sd_b") == b"value_b"
229+
assert txn.get(cf, b"sd_c") == b"value_c"
230+
with pytest.raises(tidesdb.TidesDBError):
231+
txn.get(cf, b"sd_a")
232+
233+
def test_single_delete_after_commit_raises(self, db, cf):
234+
"""Test that single_delete on a committed transaction raises."""
235+
txn = db.begin_txn()
236+
txn.put(cf, b"sd_x", b"value_x")
237+
txn.commit()
238+
with pytest.raises(tidesdb.TidesDBError):
239+
txn.single_delete(cf, b"sd_x")
240+
txn.close()
241+
201242

202243
class TestSavepoints:
203244
"""Tests for savepoint operations."""
@@ -1201,14 +1242,12 @@ class TestObjectStoreConfigFields:
12011242
def test_cf_config_defaults(self):
12021243
"""Test object store config defaults in ColumnFamilyConfig."""
12031244
config = tidesdb.ColumnFamilyConfig()
1204-
assert config.object_target_file_size == 0
12051245
assert config.object_lazy_compaction is False
12061246
assert config.object_prefetch_compaction is True
12071247

12081248
def test_cf_config_custom_values(self, db):
12091249
"""Test creating column family with object store config fields set."""
12101250
config = tidesdb.ColumnFamilyConfig(
1211-
object_target_file_size=128 * 1024 * 1024,
12121251
object_lazy_compaction=True,
12131252
object_prefetch_compaction=False,
12141253
)

0 commit comments

Comments
 (0)