nedb-engine 2.6.2__tar.gz → 2.6.3__tar.gz

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.
Files changed (37) hide show
  1. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/PKG-INFO +1 -1
  2. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/pyproject.toml +1 -1
  3. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/__init__.py +1 -1
  4. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/_native.abi3.so +0 -0
  5. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/concurrent.py +7 -0
  6. nedb_engine-2.6.3/python/nedb/nedbd-v2 +0 -0
  7. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/nedbd-v2-darwin-arm64 +0 -0
  8. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/nedbd-v2-darwin-x64 +0 -0
  9. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/nedbd-v2.exe +0 -0
  10. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/server.py +29 -2
  11. nedb_engine-2.6.2/python/nedb/nedbd-v2 +0 -0
  12. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/.gitignore +0 -0
  13. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/LICENSE +0 -0
  14. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/README.md +0 -0
  15. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/client/node/README.md +0 -0
  16. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/client/python/README.md +0 -0
  17. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/examples/mini-chain/README.md +0 -0
  18. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/autoindex.py +0 -0
  19. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/backends/__init__.py +0 -0
  20. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/backends/redis_backend.py +0 -0
  21. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/cascade.py +0 -0
  22. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/crypto.py +0 -0
  23. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/engine.py +0 -0
  24. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/index.py +0 -0
  25. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/log.py +0 -0
  26. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/merkle.py +0 -0
  27. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/mongo.py +0 -0
  28. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/proof.py +0 -0
  29. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/query.py +0 -0
  30. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/redis_compat.py +0 -0
  31. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/relations.py +0 -0
  32. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/resp2.py +0 -0
  33. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/snapshot.py +0 -0
  34. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/sql.py +0 -0
  35. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/store.py +0 -0
  36. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/python/nedb/wrap_redis.py +0 -0
  37. {nedb_engine-2.6.2 → nedb_engine-2.6.3}/rust/nedb-v2/README.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nedb-engine
3
- Version: 2.6.2
3
+ Version: 2.6.3
4
4
  Summary: NEDB — a versioned, self-compressing, time-traveling embedded database (replay-protected, idempotent, relational, searchable) with durable AOF persistence and a server daemon (nedbd).
5
5
  Project-URL: Homepage, https://github.com/aiassistsecure/nedb
6
6
  Project-URL: Repository, https://github.com/aiassistsecure/nedb
@@ -10,7 +10,7 @@ build-backend = "hatchling.build"
10
10
 
11
11
  [project]
12
12
  name = "nedb-engine"
13
- version = "2.6.2"
13
+ version = "2.6.3"
14
14
  description = "NEDB — a versioned, self-compressing, time-traveling embedded database (replay-protected, idempotent, relational, searchable) with durable AOF persistence and a server daemon (nedbd)."
15
15
  readme = "README.md"
16
16
  requires-python = ">=3.8"
@@ -89,4 +89,4 @@ __all__ = [
89
89
  "verify_proof", "fold_head",
90
90
  "_native", "__has_native__",
91
91
  ]
92
- __version__ = "2.6.2"
92
+ __version__ = "2.6.3"
@@ -115,6 +115,11 @@ class Sequencer:
115
115
  def checkpoint(self) -> Any:
116
116
  return self._submit("checkpoint")
117
117
 
118
+ def sweep(self) -> Any:
119
+ """TTL sweep as ONE committer intent — sweep appends delete ops, so it
120
+ must ride the single writer, never race it from another thread."""
121
+ return self._submit("sweep")
122
+
118
123
  # ── read API: concurrent, snapshot-isolated at committed_seq ───────────────
119
124
  def query(self, nql: str) -> List[dict]:
120
125
  plan = parse_nql(nql)
@@ -216,6 +221,8 @@ class Sequencer:
216
221
  return db.checkpoint()
217
222
  if k == "tx":
218
223
  return db.tx(*intent.args, **intent.kwargs)
224
+ if k == "sweep":
225
+ return db.sweep()
219
226
  raise ValueError(f"unknown write kind: {k}")
220
227
 
221
228
  def close(self) -> None:
Binary file
@@ -12,6 +12,7 @@ Config (env):
12
12
  NEDBD_PORT bind port (default 7070)
13
13
  NEDBD_DATA data root directory (default ./nedb-data)
14
14
  NEDBD_TOKEN bearer token (optional; if set, every /v1 route requires it)
15
+ NEDBD_SWEEP_S TTL sweep interval s (default 30; 0 disables the sweeper)
15
16
 
16
17
  Run:
17
18
  nedbd # console script (pip install nedb-engine)
@@ -24,7 +25,7 @@ HTTP API (all JSON):
24
25
  GET /v1/databases/<name>
25
26
  DELETE /v1/databases/<name>
26
27
  POST /v1/databases/<name>/query {nql}
27
- POST /v1/databases/<name>/put {coll, id, doc, client?, nonce?, idem?}
28
+ POST /v1/databases/<name>/put {coll, id, doc, client?, nonce?, idem?, ttl_s?}
28
29
  POST /v1/databases/<name>/index {coll, field, kind}
29
30
  POST /v1/databases/<name>/link {frm, rel, to}
30
31
  DELETE /v1/databases/<name>/rows/<coll>/<id>
@@ -35,6 +36,8 @@ HTTP API (all JSON):
35
36
  GET /v1/databases/<name>/files/<filename>/root?version=N&tier=warm — Merkle root (anchorable)
36
37
  POST /v1/databases/<name>/proof {hash} — Merkle inclusion proof (verifiable offline)
37
38
  POST /v1/databases/<name>/checkpoint — on-demand checkpoint
39
+ POST /v1/databases/<name>/sweep — delete TTL-expired docs now (also runs
40
+ automatically every NEDBD_SWEEP_S, default 30)
38
41
  POST /v1/databases/<name>/batch — ATOMIC multi-op tx: {ops: [{op, coll, id,
39
42
  doc?, if_seq?, idem?, client?}], client?}
40
43
  all-or-nothing; if_seq CAS preconditions
@@ -327,7 +330,7 @@ def make_handler(manager: Manager, token: Optional[str]):
327
330
  if not coll or rid is None or not isinstance(doc, dict):
328
331
  raise HttpError(400, "coll, id, and doc are required")
329
332
  _scalar = ("client", "nonce", "idem", "evidence", "confidence",
330
- "valid_from", "valid_to")
333
+ "valid_from", "valid_to", "ttl_s")
331
334
  kw = {k: b[k] for k in _scalar if b.get(k) is not None}
332
335
  # caused_by may live at the top level of the request body
333
336
  # OR inside doc (natural for clients embedding it in the document).
@@ -369,6 +372,10 @@ def make_handler(manager: Manager, token: Optional[str]):
369
372
  head = db.checkpoint()
370
373
  self._send(200, {"ok": True, "head": head, "seq": db.seq})
371
374
  return
375
+ if method == "POST" and action == "sweep":
376
+ swept = db.sweep()
377
+ self._send(200, {"ok": True, "swept": swept, "seq": db.seq})
378
+ return
372
379
  if method == "GET" and action == "log":
373
380
  limit = int(query.get("limit", ["50"])[0])
374
381
  ops = [o.to_dict() for o in db.log.ops[-limit:]][::-1]
@@ -913,6 +920,26 @@ def main() -> None:
913
920
  token = args.token
914
921
  resp2_port = args.resp2_port
915
922
  manager = Manager(data)
923
+
924
+ # TTL sweeper: engine expiry is lazy (as_of=None gets) but daemon reads are
925
+ # snapshot-pinned, so expired docs would linger forever without an active
926
+ # sweep. Runs every NEDBD_SWEEP_S seconds (default 30; 0 disables) through
927
+ # each Sequencer's committer intent — single-writer discipline preserved.
928
+ sweep_s = float(os.environ.get("NEDBD_SWEEP_S", "30"))
929
+ if sweep_s > 0:
930
+ def _sweeper():
931
+ import time as _t
932
+ while True:
933
+ _t.sleep(sweep_s)
934
+ for _name in list(manager._open.keys()):
935
+ try:
936
+ n = manager._open[_name].sweep()
937
+ if n:
938
+ _log(f" [nedbd] ttl sweep [{_name}]: {n} expired", level=1)
939
+ except Exception as _e: # noqa: BLE001
940
+ _log(f" [nedbd] ttl sweep [{_name}] error: {_e}", level=1)
941
+ threading.Thread(target=_sweeper, name="nedbd-ttl-sweeper", daemon=True).start()
942
+
916
943
  httpd = ThreadingHTTPServer((host, port), make_handler(manager, token))
917
944
  auth = "on" if token else "off"
918
945
  BANNER = f"""\
Binary file
File without changes
File without changes
File without changes