nedb-engine 2.0.36__tar.gz → 2.2.0__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 (28) hide show
  1. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/PKG-INFO +14 -12
  2. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/README.md +11 -9
  3. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/pyproject.toml +3 -3
  4. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/__init__.py +1 -1
  5. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/wrap_redis.py +64 -17
  6. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/.gitignore +0 -0
  7. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/LICENSE +0 -0
  8. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/client/node/README.md +0 -0
  9. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/client/python/README.md +0 -0
  10. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/autoindex.py +0 -0
  11. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/backends/__init__.py +0 -0
  12. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/backends/redis_backend.py +0 -0
  13. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/cascade.py +0 -0
  14. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/concurrent.py +0 -0
  15. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/crypto.py +0 -0
  16. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/engine.py +0 -0
  17. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/index.py +0 -0
  18. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/log.py +0 -0
  19. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/merkle.py +0 -0
  20. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/mongo.py +0 -0
  21. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/query.py +0 -0
  22. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/redis_compat.py +0 -0
  23. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/relations.py +0 -0
  24. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/resp2.py +0 -0
  25. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/server.py +0 -0
  26. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/snapshot.py +0 -0
  27. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/sql.py +0 -0
  28. {nedb_engine-2.0.36 → nedb_engine-2.2.0}/python/nedb/store.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nedb-engine
3
- Version: 2.0.36
3
+ Version: 2.2.0
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
- Project-URL: Homepage, https://github.com/Eth-Interchained/nedb
6
- Project-URL: Repository, https://github.com/Eth-Interchained/nedb
5
+ Project-URL: Homepage, https://github.com/aiassistsecure/nedb
6
+ Project-URL: Repository, https://github.com/aiassistsecure/nedb
7
7
  Author: Eth-Interchained
8
8
  License: GPL-3.0-or-later
9
9
  License-File: LICENSE
@@ -38,9 +38,11 @@ One Rust core → ships to **PyPI** and **npm** from a single source.
38
38
 
39
39
  ---
40
40
 
41
- ## v2 — The DAG Engine (current stable: 2.0.27)
41
+ ## NEDB v2.0.36Production Stable
42
42
 
43
- NEDB v2 replaces the append-only log (AOF) with a **content-addressed Merkle DAG**. Every document version is an immutable, BLAKE2b-verified object. Nothing is ever overwritten. As of **v2.0.27**, restarts after the first open are **O(1) warm starts** (driven by a `MANIFEST` of `seq` + Merkle head), the **cold scan is deferred** so the daemon accepts connections immediately, and a new **`GET /events` SSE endpoint** streams scan progress + per-write events live.
43
+ **Current stable: 2.0.36** Cross-platform native wheels shipping `nedbd-v2` binary inside `pip install nedb-engine`. Linux + Windows wheels built on GitHub Actions; macOS arm64 + x86_64 wheels built on Codemagic (M2 Mac Minis). All four platforms publish from one `v*` tag.
44
+
45
+ NEDB v2 replaces the append-only log (AOF) with a **content-addressed Merkle DAG**. Every document version is an immutable, BLAKE2b-verified object. Nothing is ever overwritten. As of **v2.0.36**, restarts after the first open are **O(1) warm starts** (driven by a `MANIFEST` of `seq` + Merkle head), the **cold scan is deferred** so the daemon accepts connections immediately, and a new **`GET /events` SSE endpoint** streams scan progress + per-write events live.
44
46
 
45
47
  ```bash
46
48
  # Run the v2 DAG engine — ships inside pip install nedb-engine
@@ -49,9 +51,9 @@ nedbd --dag --data ./data
49
51
  NEDBD_DAG=1 NEDB_TMK=<32-byte-hex> nedbd --data ./data
50
52
 
51
53
  curl http://127.0.0.1:7070/health
52
- # {"ok":true,"version":"2.0.27","service":"nedbd","engine":"dag","startup_ready":true,"encrypted":true}
54
+ # {"ok":true,"version":"2.0.36","service":"nedbd","engine":"dag","startup_ready":true,"encrypted":true}
53
55
 
54
- # Tail the live event stream (new in v2.0.27)
56
+ # Tail the live event stream (new in v2.0.36)
55
57
  curl http://127.0.0.1:7070/events
56
58
  # event: scan data: {"objects":730000,"of":1310703,"rate":21043,"eta_s":28}
57
59
  # event: ready data: {"seq":1310703,"head":"b2:9c14e07a…"}
@@ -75,7 +77,7 @@ curl http://127.0.0.1:7070/events
75
77
 
76
78
  **v1 AOF engine is still shipped and unchanged** — `nedbd` (no flag) runs v1.
77
79
 
78
- **Production status:** [vision.interchained.org](https://vision.interchained.org) is live on v2.0.27 — **1,310,703 sequences** indexed in the Vision database, AES-256-GCM encrypted at rest, at block height **620,989**.
80
+ **Production status:** [vision.interchained.org](https://vision.interchained.org) is live on v2.0.36 — **1,310,703 sequences** indexed in the Vision database, AES-256-GCM encrypted at rest, at block height **620,989**.
79
81
 
80
82
  ---
81
83
 
@@ -240,11 +242,11 @@ nedbd --dag --data ./data # v2 DAG engine (or NEDBD_DAG=1)
240
242
  NEDBD_RESP2_PORT=6380 nedbd # also speak RESP2 (redis-cli compatible)
241
243
  nedbd --log-level 2 # 0=errors 1=requests 2=deploy 3=verbose
242
244
 
243
- # Live event stream (new in v2.0.27) — SSE: scan progress, ready, per-write head
245
+ # Live event stream (new in v2.0.36) — SSE: scan progress, ready, per-write head
244
246
  curl http://127.0.0.1:7070/events
245
247
  ```
246
248
 
247
- ### Startup modes (v2.0.27)
249
+ ### Startup modes (v2.0.36)
248
250
 
249
251
  - **Warm start** — every restart after the first open reads the `MANIFEST` file and restores `seq` + Merkle `head` in **O(1)**. No scan, no replay, independent of dataset size. Boots in milliseconds.
250
252
  - **Cold start** — first open of an existing dataset spawns the integrity scan in a background thread *and accepts connections immediately*. Reads serve instantly from the content-addressed DAG; writes return `HTTP 503 startup in progress` until the `startup_ready` gate flips. Progress (objects, rate, ETA) streams over `GET /events`.
@@ -254,7 +256,7 @@ curl http://127.0.0.1:7070/events
254
256
  | Variable | Default | Description |
255
257
  |---|---|---|
256
258
  | `NEDBD_DAG` | `0` | Set `1` to launch the v2 DAG engine (`nedbd-v2`). Same as `--dag`. |
257
- | `NEDBD_HOST` | `127.0.0.1` | Bind address. **v2.0.27** defaults to loopback (was `0.0.0.0`) — security hardening fix. Set explicitly to `0.0.0.0` to expose. |
259
+ | `NEDBD_HOST` | `127.0.0.1` | Bind address. **v2.0.36** defaults to loopback (was `0.0.0.0`) — security hardening fix. Set explicitly to `0.0.0.0` to expose. |
258
260
  | `NEDBD_PORT` | `7070` | HTTP bind port. |
259
261
  | `NEDBD_TOKEN` | unset | Optional bearer token; required on every `/v1/*` request when set. |
260
262
  | `NEDB_TMK` | unset | 32-byte hex AES-256-GCM at-rest encryption key. |
@@ -317,7 +319,7 @@ db.query('FROM policy AS OF 200 VALID AS OF "2024-02-15"')
317
319
 
318
320
  ## Performance
319
321
 
320
- **v2 DAG Rust server (v2.0.27, Intel iMac — 10k writes / 100k reads / 30k objects, AES-256-GCM on):**
322
+ **v2 DAG Rust server (v2.0.36, Intel iMac — 10k writes / 100k reads / 30k objects, AES-256-GCM on):**
321
323
 
322
324
  | Operation | Throughput | p50 | p99 |
323
325
  |---|---|---|---|
@@ -19,9 +19,11 @@ One Rust core → ships to **PyPI** and **npm** from a single source.
19
19
 
20
20
  ---
21
21
 
22
- ## v2 — The DAG Engine (current stable: 2.0.27)
22
+ ## NEDB v2.0.36Production Stable
23
23
 
24
- NEDB v2 replaces the append-only log (AOF) with a **content-addressed Merkle DAG**. Every document version is an immutable, BLAKE2b-verified object. Nothing is ever overwritten. As of **v2.0.27**, restarts after the first open are **O(1) warm starts** (driven by a `MANIFEST` of `seq` + Merkle head), the **cold scan is deferred** so the daemon accepts connections immediately, and a new **`GET /events` SSE endpoint** streams scan progress + per-write events live.
24
+ **Current stable: 2.0.36** Cross-platform native wheels shipping `nedbd-v2` binary inside `pip install nedb-engine`. Linux + Windows wheels built on GitHub Actions; macOS arm64 + x86_64 wheels built on Codemagic (M2 Mac Minis). All four platforms publish from one `v*` tag.
25
+
26
+ NEDB v2 replaces the append-only log (AOF) with a **content-addressed Merkle DAG**. Every document version is an immutable, BLAKE2b-verified object. Nothing is ever overwritten. As of **v2.0.36**, restarts after the first open are **O(1) warm starts** (driven by a `MANIFEST` of `seq` + Merkle head), the **cold scan is deferred** so the daemon accepts connections immediately, and a new **`GET /events` SSE endpoint** streams scan progress + per-write events live.
25
27
 
26
28
  ```bash
27
29
  # Run the v2 DAG engine — ships inside pip install nedb-engine
@@ -30,9 +32,9 @@ nedbd --dag --data ./data
30
32
  NEDBD_DAG=1 NEDB_TMK=<32-byte-hex> nedbd --data ./data
31
33
 
32
34
  curl http://127.0.0.1:7070/health
33
- # {"ok":true,"version":"2.0.27","service":"nedbd","engine":"dag","startup_ready":true,"encrypted":true}
35
+ # {"ok":true,"version":"2.0.36","service":"nedbd","engine":"dag","startup_ready":true,"encrypted":true}
34
36
 
35
- # Tail the live event stream (new in v2.0.27)
37
+ # Tail the live event stream (new in v2.0.36)
36
38
  curl http://127.0.0.1:7070/events
37
39
  # event: scan data: {"objects":730000,"of":1310703,"rate":21043,"eta_s":28}
38
40
  # event: ready data: {"seq":1310703,"head":"b2:9c14e07a…"}
@@ -56,7 +58,7 @@ curl http://127.0.0.1:7070/events
56
58
 
57
59
  **v1 AOF engine is still shipped and unchanged** — `nedbd` (no flag) runs v1.
58
60
 
59
- **Production status:** [vision.interchained.org](https://vision.interchained.org) is live on v2.0.27 — **1,310,703 sequences** indexed in the Vision database, AES-256-GCM encrypted at rest, at block height **620,989**.
61
+ **Production status:** [vision.interchained.org](https://vision.interchained.org) is live on v2.0.36 — **1,310,703 sequences** indexed in the Vision database, AES-256-GCM encrypted at rest, at block height **620,989**.
60
62
 
61
63
  ---
62
64
 
@@ -221,11 +223,11 @@ nedbd --dag --data ./data # v2 DAG engine (or NEDBD_DAG=1)
221
223
  NEDBD_RESP2_PORT=6380 nedbd # also speak RESP2 (redis-cli compatible)
222
224
  nedbd --log-level 2 # 0=errors 1=requests 2=deploy 3=verbose
223
225
 
224
- # Live event stream (new in v2.0.27) — SSE: scan progress, ready, per-write head
226
+ # Live event stream (new in v2.0.36) — SSE: scan progress, ready, per-write head
225
227
  curl http://127.0.0.1:7070/events
226
228
  ```
227
229
 
228
- ### Startup modes (v2.0.27)
230
+ ### Startup modes (v2.0.36)
229
231
 
230
232
  - **Warm start** — every restart after the first open reads the `MANIFEST` file and restores `seq` + Merkle `head` in **O(1)**. No scan, no replay, independent of dataset size. Boots in milliseconds.
231
233
  - **Cold start** — first open of an existing dataset spawns the integrity scan in a background thread *and accepts connections immediately*. Reads serve instantly from the content-addressed DAG; writes return `HTTP 503 startup in progress` until the `startup_ready` gate flips. Progress (objects, rate, ETA) streams over `GET /events`.
@@ -235,7 +237,7 @@ curl http://127.0.0.1:7070/events
235
237
  | Variable | Default | Description |
236
238
  |---|---|---|
237
239
  | `NEDBD_DAG` | `0` | Set `1` to launch the v2 DAG engine (`nedbd-v2`). Same as `--dag`. |
238
- | `NEDBD_HOST` | `127.0.0.1` | Bind address. **v2.0.27** defaults to loopback (was `0.0.0.0`) — security hardening fix. Set explicitly to `0.0.0.0` to expose. |
240
+ | `NEDBD_HOST` | `127.0.0.1` | Bind address. **v2.0.36** defaults to loopback (was `0.0.0.0`) — security hardening fix. Set explicitly to `0.0.0.0` to expose. |
239
241
  | `NEDBD_PORT` | `7070` | HTTP bind port. |
240
242
  | `NEDBD_TOKEN` | unset | Optional bearer token; required on every `/v1/*` request when set. |
241
243
  | `NEDB_TMK` | unset | 32-byte hex AES-256-GCM at-rest encryption key. |
@@ -298,7 +300,7 @@ db.query('FROM policy AS OF 200 VALID AS OF "2024-02-15"')
298
300
 
299
301
  ## Performance
300
302
 
301
- **v2 DAG Rust server (v2.0.27, Intel iMac — 10k writes / 100k reads / 30k objects, AES-256-GCM on):**
303
+ **v2 DAG Rust server (v2.0.36, Intel iMac — 10k writes / 100k reads / 30k objects, AES-256-GCM on):**
302
304
 
303
305
  | Operation | Throughput | p50 | p99 |
304
306
  |---|---|---|---|
@@ -10,7 +10,7 @@ build-backend = "hatchling.build"
10
10
 
11
11
  [project]
12
12
  name = "nedb-engine"
13
- version = "2.0.36"
13
+ version = "2.2.0"
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"
@@ -34,8 +34,8 @@ dependencies = [
34
34
  nedbd = "nedb.server:main"
35
35
 
36
36
  [project.urls]
37
- Homepage = "https://github.com/Eth-Interchained/nedb"
38
- Repository = "https://github.com/Eth-Interchained/nedb"
37
+ Homepage = "https://github.com/aiassistsecure/nedb"
38
+ Repository = "https://github.com/aiassistsecure/nedb"
39
39
 
40
40
  [tool.hatch.build.targets.wheel]
41
41
  packages = ["python/nedb"]
@@ -47,4 +47,4 @@ __all__ = [
47
47
  "wrap_redis", "WrappedRedis",
48
48
  "_native", "__has_native__",
49
49
  ]
50
- __version__ = "2.0.36"
50
+ __version__ = "2.2.0"
@@ -151,12 +151,31 @@ class NedBdProxy:
151
151
  self._req("DELETE", f"/v1/databases/{self._name}/rows/{coll}/{id}")
152
152
 
153
153
  def link(self, frm: str, rel: str, to: str, **_kw) -> None:
154
- self._req("POST", self._db("/link"), {"frm": frm, "rel": rel, "to": to})
154
+ # v1 nedbd has POST /link; v2 DAG stores relations as NQL-queryable docs
155
+ # in a __links__ collection — compatible with TRAVERSE queries.
156
+ try:
157
+ self._req("POST", self._db("/link"), {"frm": frm, "rel": rel, "to": to})
158
+ except RuntimeError as e:
159
+ if "404" in str(e) or "not found" in str(e).lower():
160
+ # v2 DAG: store as a document so NQL can traverse it
161
+ self._req("POST", self._db("/put"), {
162
+ "coll": "__links__",
163
+ "id": f"{frm}|{rel}|{to}",
164
+ "doc": {"_from": frm, "_rel": rel, "_to": to},
165
+ })
166
+ else:
167
+ raise
155
168
 
156
169
  def unlink(self, frm: str, rel: str, to: str, **_kw) -> None:
157
- # nedbd doesn't have a dedicated unlink endpoint yet — use NQL delete
158
- # fallback: store as a tombstone via link with _unlinked flag
159
- pass # no-op; future: DELETE /v1/databases/{name}/links/{frm}/{rel}/{to}
170
+ try:
171
+ self._req("DELETE", f"/v1/databases/{self._name}/links/{frm}/{rel}/{to}")
172
+ except RuntimeError:
173
+ # v2 fallback: tombstone the __links__ doc
174
+ try:
175
+ self._req("DELETE",
176
+ f"/v1/databases/{self._name}/rows/__links__/{frm}|{rel}|{to}")
177
+ except RuntimeError:
178
+ pass
160
179
 
161
180
  def neighbors(self, frm: str, rel: str, as_of: Optional[int] = None) -> List[str]:
162
181
  frm_coll, frm_id = (frm.split(":", 1) + [""])[:2]
@@ -423,9 +442,28 @@ class NEDBSurface:
423
442
  return total
424
443
 
425
444
  def _backfill_one(self, mapping: CollectionMapping, batch_size: int) -> int:
426
- """Import all keys matching one mapping from Redis into NEDB."""
427
- count = 0
428
- cursor = 0
445
+ """Import all keys matching one mapping from Redis into NEDB.
446
+
447
+ In nedbd mode uses /batch for high throughput (v2 DAG: ~4000 ops/s).
448
+ In-process mode falls back to individual puts.
449
+ """
450
+ count = 0
451
+ cursor = 0
452
+ pending: List[dict] = []
453
+
454
+ def _flush() -> int:
455
+ if not pending or not self._nedbd_mode:
456
+ return 0
457
+ proxy: NedBdProxy = self._db # type: ignore[assignment]
458
+ try:
459
+ r = proxy._req("POST", proxy._db("/batch"), {"ops": list(pending)})
460
+ n = r.get("count", len(pending))
461
+ pending.clear()
462
+ return n
463
+ except Exception:
464
+ pending.clear()
465
+ return 0
466
+
429
467
  while True:
430
468
  cursor, keys = self._r.scan(cursor, match=mapping.pattern,
431
469
  count=batch_size)
@@ -441,16 +479,24 @@ class NEDBSurface:
441
479
  continue
442
480
  doc = mapping.parse_value(raw_val)
443
481
  doc.setdefault("_source", "backfill")
444
- self._db.put(mapping.collection, doc_id, doc,
445
- client="__backfill__",
446
- evidence="backfill",
447
- confidence=1.0)
448
- self._persist_last_op()
449
- count += 1
482
+ if self._nedbd_mode:
483
+ pending.append({"op": "put", "coll": mapping.collection,
484
+ "id": doc_id, "doc": doc})
485
+ if len(pending) >= 500:
486
+ count += _flush()
487
+ else:
488
+ self._db.put(mapping.collection, doc_id, doc,
489
+ client="__backfill__",
490
+ evidence="backfill",
491
+ confidence=1.0)
492
+ self._persist_last_op()
493
+ count += 1
450
494
  except Exception:
451
495
  pass # skip unreadable keys
452
496
  if cursor == 0:
453
497
  break
498
+
499
+ count += _flush() # flush remainder
454
500
  return count
455
501
 
456
502
  # ── Write shadowing ───────────────────────────────────────────────────────
@@ -641,10 +687,11 @@ def wrap_redis(r: Any, db_name: str = "default",
641
687
  Args:
642
688
  r: An existing ``redis.Redis`` (or compatible) connection.
643
689
  db_name: Logical database name. NEDB uses ``nedb:{db_name}:*``.
644
- nedbd_url: Optional URL of a running nedbd server, e.g.
645
- ``"http://localhost:8421"``. When set, all ``r.nedb.*``
646
- calls are forwarded to nedbd instead of running in-process.
647
- nedbd handles its own durable AOF persistence on disk.
690
+ nedbd_url: Optional URL of a running nedbd server.
691
+ v1 AOF: ``"http://localhost:7070"`` (nedbd, no flag)
692
+ v2 DAG: ``"http://localhost:7070"`` (nedbd --dag)
693
+ When set, all r.nedb.* calls go to nedbd over HTTP.
694
+ v2 DAG backfill uses /batch for ~4000 ops/s throughput.
648
695
  nedbd_token: Optional bearer token for nedbd authentication
649
696
  (set via ``NEDBD_TOKEN`` env on the server).
650
697
 
File without changes
File without changes