diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-12-03 08:54:00 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-12-03 08:54:00 +0000 |
| commit | 2f8ecd482077d82f2d1a937c7f979eaaa87a27b2 (patch) | |
| tree | cd892cde6ef6fd7ff654377946cab5b95339276f | |
| parent | 62a3855cb96616caf704a0f112fb2ade99fb8b45 (diff) | |
feat: implement LMDB database backend
- Add nostr-lmdb dependency (v0.44) for persistent storage
- Create SharedDatabase type alias for database abstraction
- Update all database-related functions to use trait object
- Support runtime selection via NGIT_DATABASE_BACKEND env var
Database backends:
- memory: In-memory (default, fastest, no persistence)
- lmdb: LMDB backend (persistent, general purpose)
All 34 tests pass with the new implementation.
| -rw-r--r-- | .env.example | 2 | ||||
| -rw-r--r-- | Cargo.lock | 239 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/git/authorization.rs | 12 | ||||
| -rw-r--r-- | src/git/handlers.rs | 7 | ||||
| -rw-r--r-- | src/http/mod.rs | 9 | ||||
| -rw-r--r-- | src/nostr/builder.rs | 56 |
7 files changed, 289 insertions, 37 deletions
diff --git a/.env.example b/.env.example index 0a27bbb..796415e 100644 --- a/.env.example +++ b/.env.example | |||
| @@ -17,7 +17,7 @@ NGIT_RELAY_DATA_PATH=./data/relay | |||
| 17 | # Database backend (memory, nostrdb, lmdb) | 17 | # Database backend (memory, nostrdb, lmdb) |
| 18 | # - memory: In-memory database (default, fastest, no persistence) | 18 | # - memory: In-memory database (default, fastest, no persistence) |
| 19 | # - nostrdb: NostrDB backend (persistent, optimized for Nostr) [Not yet implemented] | 19 | # - nostrdb: NostrDB backend (persistent, optimized for Nostr) [Not yet implemented] |
| 20 | # - lmdb: LMDB backend (persistent, general purpose) [Not yet implemented] | 20 | # - lmdb: LMDB backend (persistent, general purpose) |
| 21 | NGIT_DATABASE_BACKEND=memory | 21 | NGIT_DATABASE_BACKEND=memory |
| 22 | 22 | ||
| 23 | # Server configuration | 23 | # Server configuration |
| @@ -248,6 +248,9 @@ name = "bitflags" | |||
| 248 | version = "2.10.0" | 248 | version = "2.10.0" |
| 249 | source = "registry+https://github.com/rust-lang/crates.io-index" | 249 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 250 | checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" | 250 | checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" |
| 251 | dependencies = [ | ||
| 252 | "serde_core", | ||
| 253 | ] | ||
| 251 | 254 | ||
| 252 | [[package]] | 255 | [[package]] |
| 253 | name = "block-buffer" | 256 | name = "block-buffer" |
| @@ -274,6 +277,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 274 | checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" | 277 | checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" |
| 275 | 278 | ||
| 276 | [[package]] | 279 | [[package]] |
| 280 | name = "byteorder" | ||
| 281 | version = "1.5.0" | ||
| 282 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 283 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" | ||
| 284 | |||
| 285 | [[package]] | ||
| 277 | name = "bytes" | 286 | name = "bytes" |
| 278 | version = "1.10.1" | 287 | version = "1.10.1" |
| 279 | source = "registry+https://github.com/rust-lang/crates.io-index" | 288 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -433,6 +442,21 @@ dependencies = [ | |||
| 433 | ] | 442 | ] |
| 434 | 443 | ||
| 435 | [[package]] | 444 | [[package]] |
| 445 | name = "crossbeam-queue" | ||
| 446 | version = "0.3.12" | ||
| 447 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 448 | checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" | ||
| 449 | dependencies = [ | ||
| 450 | "crossbeam-utils", | ||
| 451 | ] | ||
| 452 | |||
| 453 | [[package]] | ||
| 454 | name = "crossbeam-utils" | ||
| 455 | version = "0.8.21" | ||
| 456 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 457 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" | ||
| 458 | |||
| 459 | [[package]] | ||
| 436 | name = "crypto-common" | 460 | name = "crypto-common" |
| 437 | version = "0.1.6" | 461 | version = "0.1.6" |
| 438 | source = "registry+https://github.com/rust-lang/crates.io-index" | 462 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -478,6 +502,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 478 | checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" | 502 | checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" |
| 479 | 503 | ||
| 480 | [[package]] | 504 | [[package]] |
| 505 | name = "doxygen-rs" | ||
| 506 | version = "0.4.2" | ||
| 507 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 508 | checksum = "415b6ec780d34dcf624666747194393603d0373b7141eef01d12ee58881507d9" | ||
| 509 | dependencies = [ | ||
| 510 | "phf", | ||
| 511 | ] | ||
| 512 | |||
| 513 | [[package]] | ||
| 481 | name = "either" | 514 | name = "either" |
| 482 | version = "1.15.0" | 515 | version = "1.15.0" |
| 483 | source = "registry+https://github.com/rust-lang/crates.io-index" | 516 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -521,6 +554,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 521 | checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" | 554 | checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" |
| 522 | 555 | ||
| 523 | [[package]] | 556 | [[package]] |
| 557 | name = "flatbuffers" | ||
| 558 | version = "25.9.23" | ||
| 559 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 560 | checksum = "09b6620799e7340ebd9968d2e0708eb82cf1971e9a16821e2091b6d6e475eed5" | ||
| 561 | dependencies = [ | ||
| 562 | "bitflags 2.10.0", | ||
| 563 | "rustc_version", | ||
| 564 | ] | ||
| 565 | |||
| 566 | [[package]] | ||
| 524 | name = "flate2" | 567 | name = "flate2" |
| 525 | version = "1.1.5" | 568 | version = "1.1.5" |
| 526 | source = "registry+https://github.com/rust-lang/crates.io-index" | 569 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -531,6 +574,18 @@ dependencies = [ | |||
| 531 | ] | 574 | ] |
| 532 | 575 | ||
| 533 | [[package]] | 576 | [[package]] |
| 577 | name = "flume" | ||
| 578 | version = "0.11.1" | ||
| 579 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 580 | checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" | ||
| 581 | dependencies = [ | ||
| 582 | "futures-core", | ||
| 583 | "futures-sink", | ||
| 584 | "nanorand", | ||
| 585 | "spin", | ||
| 586 | ] | ||
| 587 | |||
| 588 | [[package]] | ||
| 534 | name = "fnv" | 589 | name = "fnv" |
| 535 | version = "1.0.7" | 590 | version = "1.0.7" |
| 536 | source = "registry+https://github.com/rust-lang/crates.io-index" | 591 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -769,6 +824,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 769 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" | 824 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" |
| 770 | 825 | ||
| 771 | [[package]] | 826 | [[package]] |
| 827 | name = "heed" | ||
| 828 | version = "0.20.5" | ||
| 829 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 830 | checksum = "7d4f449bab7320c56003d37732a917e18798e2f1709d80263face2b4f9436ddb" | ||
| 831 | dependencies = [ | ||
| 832 | "bitflags 2.10.0", | ||
| 833 | "byteorder", | ||
| 834 | "heed-traits", | ||
| 835 | "heed-types", | ||
| 836 | "libc", | ||
| 837 | "lmdb-master-sys", | ||
| 838 | "once_cell", | ||
| 839 | "page_size", | ||
| 840 | "synchronoise", | ||
| 841 | "url", | ||
| 842 | ] | ||
| 843 | |||
| 844 | [[package]] | ||
| 845 | name = "heed-traits" | ||
| 846 | version = "0.20.0" | ||
| 847 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 848 | checksum = "eb3130048d404c57ce5a1ac61a903696e8fcde7e8c2991e9fcfc1f27c3ef74ff" | ||
| 849 | |||
| 850 | [[package]] | ||
| 851 | name = "heed-types" | ||
| 852 | version = "0.20.1" | ||
| 853 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 854 | checksum = "9d3f528b053a6d700b2734eabcd0fd49cb8230647aa72958467527b0b7917114" | ||
| 855 | dependencies = [ | ||
| 856 | "byteorder", | ||
| 857 | "heed-traits", | ||
| 858 | ] | ||
| 859 | |||
| 860 | [[package]] | ||
| 772 | name = "hex" | 861 | name = "hex" |
| 773 | version = "0.4.3" | 862 | version = "0.4.3" |
| 774 | source = "registry+https://github.com/rust-lang/crates.io-index" | 863 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1152,6 +1241,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 1152 | checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" | 1241 | checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" |
| 1153 | 1242 | ||
| 1154 | [[package]] | 1243 | [[package]] |
| 1244 | name = "lmdb-master-sys" | ||
| 1245 | version = "0.2.5" | ||
| 1246 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1247 | checksum = "864808e0b19fb6dd3b70ba94ee671b82fce17554cf80aeb0a155c65bb08027df" | ||
| 1248 | dependencies = [ | ||
| 1249 | "cc", | ||
| 1250 | "doxygen-rs", | ||
| 1251 | "libc", | ||
| 1252 | ] | ||
| 1253 | |||
| 1254 | [[package]] | ||
| 1155 | name = "lock_api" | 1255 | name = "lock_api" |
| 1156 | version = "0.4.14" | 1256 | version = "0.4.14" |
| 1157 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1257 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1215,6 +1315,15 @@ dependencies = [ | |||
| 1215 | ] | 1315 | ] |
| 1216 | 1316 | ||
| 1217 | [[package]] | 1317 | [[package]] |
| 1318 | name = "nanorand" | ||
| 1319 | version = "0.7.0" | ||
| 1320 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1321 | checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" | ||
| 1322 | dependencies = [ | ||
| 1323 | "getrandom 0.2.16", | ||
| 1324 | ] | ||
| 1325 | |||
| 1326 | [[package]] | ||
| 1218 | name = "native-tls" | 1327 | name = "native-tls" |
| 1219 | version = "0.2.14" | 1328 | version = "0.2.14" |
| 1220 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1329 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1250,6 +1359,7 @@ dependencies = [ | |||
| 1250 | "http-body-util", | 1359 | "http-body-util", |
| 1251 | "hyper 1.8.1", | 1360 | "hyper 1.8.1", |
| 1252 | "hyper-util", | 1361 | "hyper-util", |
| 1362 | "nostr-lmdb", | ||
| 1253 | "nostr-relay-builder", | 1363 | "nostr-relay-builder", |
| 1254 | "nostr-sdk 0.44.1", | 1364 | "nostr-sdk 0.44.1", |
| 1255 | "serde", | 1365 | "serde", |
| @@ -1327,6 +1437,7 @@ version = "0.44.0" | |||
| 1327 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1437 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1328 | checksum = "7462c9d8ae5ef6a28d66a192d399ad2530f1f2130b13186296dbb11bdef5b3d1" | 1438 | checksum = "7462c9d8ae5ef6a28d66a192d399ad2530f1f2130b13186296dbb11bdef5b3d1" |
| 1329 | dependencies = [ | 1439 | dependencies = [ |
| 1440 | "flatbuffers", | ||
| 1330 | "lru", | 1441 | "lru", |
| 1331 | "nostr 0.44.1", | 1442 | "nostr 0.44.1", |
| 1332 | "tokio", | 1443 | "tokio", |
| @@ -1342,6 +1453,21 @@ dependencies = [ | |||
| 1342 | ] | 1453 | ] |
| 1343 | 1454 | ||
| 1344 | [[package]] | 1455 | [[package]] |
| 1456 | name = "nostr-lmdb" | ||
| 1457 | version = "0.44.0" | ||
| 1458 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1459 | checksum = "1201bcf1f900c352f9f2cea5249960dc6b23049b65699a516e1327243becf6a2" | ||
| 1460 | dependencies = [ | ||
| 1461 | "async-utility", | ||
| 1462 | "flume", | ||
| 1463 | "heed", | ||
| 1464 | "nostr 0.44.1", | ||
| 1465 | "nostr-database 0.44.0", | ||
| 1466 | "tokio", | ||
| 1467 | "tracing", | ||
| 1468 | ] | ||
| 1469 | |||
| 1470 | [[package]] | ||
| 1345 | name = "nostr-relay-builder" | 1471 | name = "nostr-relay-builder" |
| 1346 | version = "0.44.0" | 1472 | version = "0.44.0" |
| 1347 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1473 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1502,6 +1628,16 @@ dependencies = [ | |||
| 1502 | ] | 1628 | ] |
| 1503 | 1629 | ||
| 1504 | [[package]] | 1630 | [[package]] |
| 1631 | name = "page_size" | ||
| 1632 | version = "0.6.0" | ||
| 1633 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1634 | checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" | ||
| 1635 | dependencies = [ | ||
| 1636 | "libc", | ||
| 1637 | "winapi", | ||
| 1638 | ] | ||
| 1639 | |||
| 1640 | [[package]] | ||
| 1505 | name = "parking_lot" | 1641 | name = "parking_lot" |
| 1506 | version = "0.12.5" | 1642 | version = "0.12.5" |
| 1507 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1643 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1552,6 +1688,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 1552 | checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" | 1688 | checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" |
| 1553 | 1689 | ||
| 1554 | [[package]] | 1690 | [[package]] |
| 1691 | name = "phf" | ||
| 1692 | version = "0.11.3" | ||
| 1693 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1694 | checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" | ||
| 1695 | dependencies = [ | ||
| 1696 | "phf_macros", | ||
| 1697 | "phf_shared", | ||
| 1698 | ] | ||
| 1699 | |||
| 1700 | [[package]] | ||
| 1701 | name = "phf_generator" | ||
| 1702 | version = "0.11.3" | ||
| 1703 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1704 | checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" | ||
| 1705 | dependencies = [ | ||
| 1706 | "phf_shared", | ||
| 1707 | "rand 0.8.5", | ||
| 1708 | ] | ||
| 1709 | |||
| 1710 | [[package]] | ||
| 1711 | name = "phf_macros" | ||
| 1712 | version = "0.11.3" | ||
| 1713 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1714 | checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" | ||
| 1715 | dependencies = [ | ||
| 1716 | "phf_generator", | ||
| 1717 | "phf_shared", | ||
| 1718 | "proc-macro2", | ||
| 1719 | "quote", | ||
| 1720 | "syn", | ||
| 1721 | ] | ||
| 1722 | |||
| 1723 | [[package]] | ||
| 1724 | name = "phf_shared" | ||
| 1725 | version = "0.11.3" | ||
| 1726 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1727 | checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" | ||
| 1728 | dependencies = [ | ||
| 1729 | "siphasher", | ||
| 1730 | ] | ||
| 1731 | |||
| 1732 | [[package]] | ||
| 1555 | name = "pin-project-lite" | 1733 | name = "pin-project-lite" |
| 1556 | version = "0.2.16" | 1734 | version = "0.2.16" |
| 1557 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1735 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1774,6 +1952,15 @@ dependencies = [ | |||
| 1774 | ] | 1952 | ] |
| 1775 | 1953 | ||
| 1776 | [[package]] | 1954 | [[package]] |
| 1955 | name = "rustc_version" | ||
| 1956 | version = "0.4.1" | ||
| 1957 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1958 | checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" | ||
| 1959 | dependencies = [ | ||
| 1960 | "semver", | ||
| 1961 | ] | ||
| 1962 | |||
| 1963 | [[package]] | ||
| 1777 | name = "rustix" | 1964 | name = "rustix" |
| 1778 | version = "1.1.2" | 1965 | version = "1.1.2" |
| 1779 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1966 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1921,6 +2108,12 @@ dependencies = [ | |||
| 1921 | ] | 2108 | ] |
| 1922 | 2109 | ||
| 1923 | [[package]] | 2110 | [[package]] |
| 2111 | name = "semver" | ||
| 2112 | version = "1.0.27" | ||
| 2113 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2114 | checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" | ||
| 2115 | |||
| 2116 | [[package]] | ||
| 1924 | name = "serde" | 2117 | name = "serde" |
| 1925 | version = "1.0.228" | 2118 | version = "1.0.228" |
| 1926 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2119 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -2028,6 +2221,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 2028 | checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" | 2221 | checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" |
| 2029 | 2222 | ||
| 2030 | [[package]] | 2223 | [[package]] |
| 2224 | name = "siphasher" | ||
| 2225 | version = "1.0.1" | ||
| 2226 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2227 | checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" | ||
| 2228 | |||
| 2229 | [[package]] | ||
| 2031 | name = "slab" | 2230 | name = "slab" |
| 2032 | version = "0.4.11" | 2231 | version = "0.4.11" |
| 2033 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2232 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -2060,6 +2259,15 @@ dependencies = [ | |||
| 2060 | ] | 2259 | ] |
| 2061 | 2260 | ||
| 2062 | [[package]] | 2261 | [[package]] |
| 2262 | name = "spin" | ||
| 2263 | version = "0.9.8" | ||
| 2264 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2265 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" | ||
| 2266 | dependencies = [ | ||
| 2267 | "lock_api", | ||
| 2268 | ] | ||
| 2269 | |||
| 2270 | [[package]] | ||
| 2063 | name = "stable_deref_trait" | 2271 | name = "stable_deref_trait" |
| 2064 | version = "1.2.1" | 2272 | version = "1.2.1" |
| 2065 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2273 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -2095,6 +2303,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 2095 | checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" | 2303 | checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" |
| 2096 | 2304 | ||
| 2097 | [[package]] | 2305 | [[package]] |
| 2306 | name = "synchronoise" | ||
| 2307 | version = "1.0.1" | ||
| 2308 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2309 | checksum = "3dbc01390fc626ce8d1cffe3376ded2b72a11bb70e1c75f404a210e4daa4def2" | ||
| 2310 | dependencies = [ | ||
| 2311 | "crossbeam-queue", | ||
| 2312 | ] | ||
| 2313 | |||
| 2314 | [[package]] | ||
| 2098 | name = "synstructure" | 2315 | name = "synstructure" |
| 2099 | version = "0.13.2" | 2316 | version = "0.13.2" |
| 2100 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2317 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -2625,6 +2842,28 @@ dependencies = [ | |||
| 2625 | ] | 2842 | ] |
| 2626 | 2843 | ||
| 2627 | [[package]] | 2844 | [[package]] |
| 2845 | name = "winapi" | ||
| 2846 | version = "0.3.9" | ||
| 2847 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2848 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" | ||
| 2849 | dependencies = [ | ||
| 2850 | "winapi-i686-pc-windows-gnu", | ||
| 2851 | "winapi-x86_64-pc-windows-gnu", | ||
| 2852 | ] | ||
| 2853 | |||
| 2854 | [[package]] | ||
| 2855 | name = "winapi-i686-pc-windows-gnu" | ||
| 2856 | version = "0.4.0" | ||
| 2857 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2858 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | ||
| 2859 | |||
| 2860 | [[package]] | ||
| 2861 | name = "winapi-x86_64-pc-windows-gnu" | ||
| 2862 | version = "0.4.0" | ||
| 2863 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2864 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | ||
| 2865 | |||
| 2866 | [[package]] | ||
| 2628 | name = "windows-core" | 2867 | name = "windows-core" |
| 2629 | version = "0.62.2" | 2868 | version = "0.62.2" |
| 2630 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2869 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -21,6 +21,7 @@ nostr-relay-builder = "0.44" | |||
| 21 | 21 | ||
| 22 | # Nostr | 22 | # Nostr |
| 23 | nostr-sdk = "0.44" | 23 | nostr-sdk = "0.44" |
| 24 | nostr-lmdb = "0.44" | ||
| 24 | 25 | ||
| 25 | # Utilities | 26 | # Utilities |
| 26 | futures-util = "0.3" | 27 | futures-util = "0.3" |
diff --git a/src/git/authorization.rs b/src/git/authorization.rs index 3b0e759..4896fc0 100644 --- a/src/git/authorization.rs +++ b/src/git/authorization.rs | |||
| @@ -31,9 +31,9 @@ use anyhow::{anyhow, Result}; | |||
| 31 | use nostr_relay_builder::prelude::*; | 31 | use nostr_relay_builder::prelude::*; |
| 32 | use nostr_sdk::{EventId, ToBech32}; | 32 | use nostr_sdk::{EventId, ToBech32}; |
| 33 | use std::collections::{HashMap, HashSet}; | 33 | use std::collections::{HashMap, HashSet}; |
| 34 | use std::sync::Arc; | ||
| 35 | use tracing::debug; | 34 | use tracing::debug; |
| 36 | 35 | ||
| 36 | use crate::nostr::builder::SharedDatabase; | ||
| 37 | use crate::nostr::events::{ | 37 | use crate::nostr::events::{ |
| 38 | RepositoryAnnouncement, RepositoryState, KIND_PR, KIND_PR_UPDATE, KIND_REPOSITORY_ANNOUNCEMENT, | 38 | RepositoryAnnouncement, RepositoryState, KIND_PR, KIND_PR_UPDATE, KIND_REPOSITORY_ANNOUNCEMENT, |
| 39 | KIND_REPOSITORY_STATE, | 39 | KIND_REPOSITORY_STATE, |
| @@ -56,7 +56,7 @@ pub struct RepositoryData { | |||
| 56 | /// This performs a single database query to fetch both announcement and state events, | 56 | /// This performs a single database query to fetch both announcement and state events, |
| 57 | /// which is more efficient than separate queries. | 57 | /// which is more efficient than separate queries. |
| 58 | pub async fn fetch_repository_data( | 58 | pub async fn fetch_repository_data( |
| 59 | database: &Arc<MemoryDatabase>, | 59 | database: &SharedDatabase, |
| 60 | identifier: &str, | 60 | identifier: &str, |
| 61 | ) -> Result<RepositoryData> { | 61 | ) -> Result<RepositoryData> { |
| 62 | let filter = Filter::new() | 62 | let filter = Filter::new() |
| @@ -284,7 +284,7 @@ pub fn is_latest_state( | |||
| 284 | /// | 284 | /// |
| 285 | /// Returns an `AuthorizationResult` that indicates whether a push is authorized. | 285 | /// Returns an `AuthorizationResult` that indicates whether a push is authorized. |
| 286 | pub async fn get_authorization_from_db( | 286 | pub async fn get_authorization_from_db( |
| 287 | database: &Arc<MemoryDatabase>, | 287 | database: &SharedDatabase, |
| 288 | identifier: &str, | 288 | identifier: &str, |
| 289 | ) -> Result<AuthorizationResult> { | 289 | ) -> Result<AuthorizationResult> { |
| 290 | // Fetch all repository data with a single query | 290 | // Fetch all repository data with a single query |
| @@ -340,7 +340,7 @@ pub async fn get_authorization_from_db( | |||
| 340 | /// | 340 | /// |
| 341 | /// Returns an `AuthorizationResult` that indicates whether a push is authorized. | 341 | /// Returns an `AuthorizationResult` that indicates whether a push is authorized. |
| 342 | pub async fn get_authorization_for_owner( | 342 | pub async fn get_authorization_for_owner( |
| 343 | database: &Arc<MemoryDatabase>, | 343 | database: &SharedDatabase, |
| 344 | identifier: &str, | 344 | identifier: &str, |
| 345 | owner_pubkey: &str, | 345 | owner_pubkey: &str, |
| 346 | ) -> Result<AuthorizationResult> { | 346 | ) -> Result<AuthorizationResult> { |
| @@ -817,7 +817,7 @@ pub fn npub_to_pubkey(npub: &str) -> Result<String> { | |||
| 817 | /// - `Ok(None)` if the event doesn't exist (push should be allowed) | 817 | /// - `Ok(None)` if the event doesn't exist (push should be allowed) |
| 818 | /// - `Err(_)` on database errors | 818 | /// - `Err(_)` on database errors |
| 819 | pub async fn get_event_commit_tag( | 819 | pub async fn get_event_commit_tag( |
| 820 | database: &Arc<MemoryDatabase>, | 820 | database: &SharedDatabase, |
| 821 | event_id: &EventId, | 821 | event_id: &EventId, |
| 822 | ) -> Result<Option<String>> { | 822 | ) -> Result<Option<String>> { |
| 823 | // Query for PR (1618) and PR Update (1619) events with this ID | 823 | // Query for PR (1618) and PR Update (1619) events with this ID |
| @@ -872,7 +872,7 @@ pub async fn get_event_commit_tag( | |||
| 872 | /// * `Ok(())` if all refs/nostr/ pushes are valid | 872 | /// * `Ok(())` if all refs/nostr/ pushes are valid |
| 873 | /// * `Err(_)` if any ref has invalid event ID format or fails commit validation | 873 | /// * `Err(_)` if any ref has invalid event ID format or fails commit validation |
| 874 | pub async fn validate_nostr_ref_pushes( | 874 | pub async fn validate_nostr_ref_pushes( |
| 875 | database: &Arc<MemoryDatabase>, | 875 | database: &SharedDatabase, |
| 876 | pushed_refs: &[(String, String, String)], | 876 | pushed_refs: &[(String, String, String)], |
| 877 | ) -> Result<()> { | 877 | ) -> Result<()> { |
| 878 | for (_, new_oid, ref_name) in pushed_refs { | 878 | for (_, new_oid, ref_name) in pushed_refs { |
diff --git a/src/git/handlers.rs b/src/git/handlers.rs index e84cabb..8e5f5e1 100644 --- a/src/git/handlers.rs +++ b/src/git/handlers.rs | |||
| @@ -4,9 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | use http_body_util::Full; | 5 | use http_body_util::Full; |
| 6 | use hyper::{body::Bytes, Response, StatusCode}; | 6 | use hyper::{body::Bytes, Response, StatusCode}; |
| 7 | use nostr_relay_builder::prelude::MemoryDatabase; | ||
| 8 | use std::path::PathBuf; | 7 | use std::path::PathBuf; |
| 9 | use std::sync::Arc; | ||
| 10 | use tokio::io::{AsyncReadExt, AsyncWriteExt}; | 8 | use tokio::io::{AsyncReadExt, AsyncWriteExt}; |
| 11 | use tracing::{debug, error, info, warn}; | 9 | use tracing::{debug, error, info, warn}; |
| 12 | 10 | ||
| @@ -18,6 +16,7 @@ use super::protocol::{GitService, PktLine}; | |||
| 18 | use super::subprocess::GitSubprocess; | 16 | use super::subprocess::GitSubprocess; |
| 19 | use super::try_set_head_if_available; | 17 | use super::try_set_head_if_available; |
| 20 | 18 | ||
| 19 | use crate::nostr::builder::SharedDatabase; | ||
| 21 | use crate::nostr::events::RepositoryState; | 20 | use crate::nostr::events::RepositoryState; |
| 22 | 21 | ||
| 23 | /// Handle GET /info/refs?service=git-{upload,receive}-pack | 22 | /// Handle GET /info/refs?service=git-{upload,receive}-pack |
| @@ -178,7 +177,7 @@ pub async fn handle_upload_pack( | |||
| 178 | pub async fn handle_receive_pack( | 177 | pub async fn handle_receive_pack( |
| 179 | repo_path: PathBuf, | 178 | repo_path: PathBuf, |
| 180 | request_body: Bytes, | 179 | request_body: Bytes, |
| 181 | database: Option<Arc<MemoryDatabase>>, | 180 | database: Option<SharedDatabase>, |
| 182 | identifier: &str, | 181 | identifier: &str, |
| 183 | owner_pubkey: &str, | 182 | owner_pubkey: &str, |
| 184 | ) -> Result<Response<Full<Bytes>>, GitError> { | 183 | ) -> Result<Response<Full<Bytes>>, GitError> { |
| @@ -310,7 +309,7 @@ pub async fn handle_receive_pack( | |||
| 310 | /// 5. Validates that pushed refs match the state | 309 | /// 5. Validates that pushed refs match the state |
| 311 | /// 6. Validates refs/nostr/<event-id> has valid event id and if event exists, `c` tag matches ref | 310 | /// 6. Validates refs/nostr/<event-id> has valid event id and if event exists, `c` tag matches ref |
| 312 | async fn authorize_push( | 311 | async fn authorize_push( |
| 313 | database: &Arc<MemoryDatabase>, | 312 | database: &SharedDatabase, |
| 314 | identifier: &str, | 313 | identifier: &str, |
| 315 | owner_pubkey: &str, | 314 | owner_pubkey: &str, |
| 316 | request_body: &Bytes, | 315 | request_body: &Bytes, |
diff --git a/src/http/mod.rs b/src/http/mod.rs index 5cf8dbe..4665281 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs | |||
| @@ -7,7 +7,6 @@ pub mod nip11; | |||
| 7 | use std::future::Future; | 7 | use std::future::Future; |
| 8 | use std::net::SocketAddr; | 8 | use std::net::SocketAddr; |
| 9 | use std::pin::Pin; | 9 | use std::pin::Pin; |
| 10 | use std::sync::Arc; | ||
| 11 | 10 | ||
| 12 | use base64::Engine; | 11 | use base64::Engine; |
| 13 | use http_body_util::{BodyExt, Full}; | 12 | use http_body_util::{BodyExt, Full}; |
| @@ -17,7 +16,6 @@ use hyper::server::conn::http1; | |||
| 17 | use hyper::service::Service; | 16 | use hyper::service::Service; |
| 18 | use hyper::{Method, Request, Response}; | 17 | use hyper::{Method, Request, Response}; |
| 19 | use hyper_util::rt::TokioIo; | 18 | use hyper_util::rt::TokioIo; |
| 20 | use nostr_relay_builder::prelude::MemoryDatabase; | ||
| 21 | use nostr_relay_builder::LocalRelay; | 19 | use nostr_relay_builder::LocalRelay; |
| 22 | use nostr_sdk::hashes::sha1::Hash as Sha1Hash; | 20 | use nostr_sdk::hashes::sha1::Hash as Sha1Hash; |
| 23 | use nostr_sdk::hashes::{Hash, HashEngine}; | 21 | use nostr_sdk::hashes::{Hash, HashEngine}; |
| @@ -26,6 +24,7 @@ use tokio::net::TcpListener; | |||
| 26 | 24 | ||
| 27 | use crate::config::Config; | 25 | use crate::config::Config; |
| 28 | use crate::git; | 26 | use crate::git; |
| 27 | use crate::nostr::builder::SharedDatabase; | ||
| 29 | 28 | ||
| 30 | /// CORS headers required by GRASP-01 specification (lines 40-47) | 29 | /// CORS headers required by GRASP-01 specification (lines 40-47) |
| 31 | const CORS_ALLOW_ORIGIN: &str = "*"; | 30 | const CORS_ALLOW_ORIGIN: &str = "*"; |
| @@ -90,7 +89,7 @@ struct HttpService { | |||
| 90 | config: Config, | 89 | config: Config, |
| 91 | remote: SocketAddr, | 90 | remote: SocketAddr, |
| 92 | /// Database reference for direct queries (e.g., push authorization) | 91 | /// Database reference for direct queries (e.g., push authorization) |
| 93 | database: Arc<MemoryDatabase>, | 92 | database: SharedDatabase, |
| 94 | } | 93 | } |
| 95 | 94 | ||
| 96 | impl HttpService { | 95 | impl HttpService { |
| @@ -98,7 +97,7 @@ impl HttpService { | |||
| 98 | relay: LocalRelay, | 97 | relay: LocalRelay, |
| 99 | config: Config, | 98 | config: Config, |
| 100 | remote: SocketAddr, | 99 | remote: SocketAddr, |
| 101 | database: Arc<MemoryDatabase>, | 100 | database: SharedDatabase, |
| 102 | ) -> Self { | 101 | ) -> Self { |
| 103 | Self { | 102 | Self { |
| 104 | relay, | 103 | relay, |
| @@ -423,7 +422,7 @@ fn derive_accept_key(request_key: &[u8]) -> String { | |||
| 423 | pub async fn run_server( | 422 | pub async fn run_server( |
| 424 | config: Config, | 423 | config: Config, |
| 425 | relay: LocalRelay, | 424 | relay: LocalRelay, |
| 426 | database: Arc<MemoryDatabase>, | 425 | database: SharedDatabase, |
| 427 | ) -> anyhow::Result<()> { | 426 | ) -> anyhow::Result<()> { |
| 428 | let bind_addr: SocketAddr = config.bind_address.parse()?; | 427 | let bind_addr: SocketAddr = config.bind_address.parse()?; |
| 429 | 428 | ||
diff --git a/src/nostr/builder.rs b/src/nostr/builder.rs index 2f182ea..eabb38f 100644 --- a/src/nostr/builder.rs +++ b/src/nostr/builder.rs | |||
| @@ -9,6 +9,7 @@ use std::sync::Arc; | |||
| 9 | use nostr::nips::nip19::ToBech32; | 9 | use nostr::nips::nip19::ToBech32; |
| 10 | use nostr::prelude::{Alphabet, SingleLetterTag}; | 10 | use nostr::prelude::{Alphabet, SingleLetterTag}; |
| 11 | use nostr::{EventId, Filter, Kind, PublicKey}; | 11 | use nostr::{EventId, Filter, Kind, PublicKey}; |
| 12 | use nostr_lmdb::NostrLMDB; | ||
| 12 | use nostr_relay_builder::prelude::*; | 13 | use nostr_relay_builder::prelude::*; |
| 13 | 14 | ||
| 14 | use crate::config::{Config, DatabaseBackend}; | 15 | use crate::config::{Config, DatabaseBackend}; |
| @@ -18,6 +19,9 @@ use crate::nostr::events::{ | |||
| 18 | KIND_PR_UPDATE, KIND_REPOSITORY_ANNOUNCEMENT, KIND_REPOSITORY_STATE, | 19 | KIND_PR_UPDATE, KIND_REPOSITORY_ANNOUNCEMENT, KIND_REPOSITORY_STATE, |
| 19 | }; | 20 | }; |
| 20 | 21 | ||
| 22 | /// Type alias for the shared database used by the relay | ||
| 23 | pub type SharedDatabase = Arc<dyn NostrDatabase>; | ||
| 24 | |||
| 21 | /// Result of aligning a repository with authorized state | 25 | /// Result of aligning a repository with authorized state |
| 22 | #[derive(Debug, Default)] | 26 | #[derive(Debug, Default)] |
| 23 | struct AlignmentResult { | 27 | struct AlignmentResult { |
| @@ -35,23 +39,33 @@ struct AlignmentResult { | |||
| 35 | /// | 39 | /// |
| 36 | /// Validates all events according to GRASP-01 specification: | 40 | /// Validates all events according to GRASP-01 specification: |
| 37 | /// - Repository announcements must list service in clone and relays tags | 41 | /// - Repository announcements must list service in clone and relays tags |
| 38 | /// - Repository state announcements must have valid structure | 42 | /// - Repository state announcements must have valid structure |
| 39 | /// - Other events must reference accepted repositories or events | 43 | /// - Other events must reference accepted repositories or events |
| 40 | /// - Forward references are supported (events referenced by accepted events) | 44 | /// - Forward references are supported (events referenced by accepted events) |
| 41 | /// - Orphan events with no valid references are rejected | 45 | /// - Orphan events with no valid references are rejected |
| 42 | /// | 46 | /// |
| 43 | /// Uses stateful database queries to check event relationships. | 47 | /// Uses stateful database queries to check event relationships. |
| 44 | #[derive(Debug, Clone)] | 48 | #[derive(Clone)] |
| 45 | pub struct Nip34WritePolicy { | 49 | pub struct Nip34WritePolicy { |
| 46 | domain: String, | 50 | domain: String, |
| 47 | database: Arc<MemoryDatabase>, | 51 | database: SharedDatabase, |
| 48 | git_data_path: PathBuf, | 52 | git_data_path: PathBuf, |
| 49 | } | 53 | } |
| 50 | 54 | ||
| 55 | impl std::fmt::Debug for Nip34WritePolicy { | ||
| 56 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
| 57 | f.debug_struct("Nip34WritePolicy") | ||
| 58 | .field("domain", &self.domain) | ||
| 59 | .field("git_data_path", &self.git_data_path) | ||
| 60 | .field("database", &"<database>") | ||
| 61 | .finish() | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 51 | impl Nip34WritePolicy { | 65 | impl Nip34WritePolicy { |
| 52 | pub fn new( | 66 | pub fn new( |
| 53 | domain: impl Into<String>, | 67 | domain: impl Into<String>, |
| 54 | database: Arc<MemoryDatabase>, | 68 | database: SharedDatabase, |
| 55 | git_data_path: impl Into<PathBuf>, | 69 | git_data_path: impl Into<PathBuf>, |
| 56 | ) -> Self { | 70 | ) -> Self { |
| 57 | Self { | 71 | Self { |
| @@ -104,7 +118,7 @@ impl Nip34WritePolicy { | |||
| 104 | /// The authorized_pubkeys should be the owner and maintainers of a specific | 118 | /// The authorized_pubkeys should be the owner and maintainers of a specific |
| 105 | /// announcement, so different owners with the same identifier don't interfere. | 119 | /// announcement, so different owners with the same identifier don't interfere. |
| 106 | async fn is_latest_state_for_identifier( | 120 | async fn is_latest_state_for_identifier( |
| 107 | database: &Arc<MemoryDatabase>, | 121 | database: &SharedDatabase, |
| 108 | state: &RepositoryState, | 122 | state: &RepositoryState, |
| 109 | authorized_pubkeys: &[PublicKey], | 123 | authorized_pubkeys: &[PublicKey], |
| 110 | ) -> Result<bool, String> { | 124 | ) -> Result<bool, String> { |
| @@ -155,7 +169,7 @@ impl Nip34WritePolicy { | |||
| 155 | /// should update HEAD in the repository of the announcement owner, | 169 | /// should update HEAD in the repository of the announcement owner, |
| 156 | /// not in the maintainer's own (possibly non-existent) repository. | 170 | /// not in the maintainer's own (possibly non-existent) repository. |
| 157 | async fn find_authorized_announcements( | 171 | async fn find_authorized_announcements( |
| 158 | database: &Arc<MemoryDatabase>, | 172 | database: &SharedDatabase, |
| 159 | identifier: &str, | 173 | identifier: &str, |
| 160 | state_author: &PublicKey, | 174 | state_author: &PublicKey, |
| 161 | ) -> Result<Vec<RepositoryAnnouncement>, String> { | 175 | ) -> Result<Vec<RepositoryAnnouncement>, String> { |
| @@ -205,7 +219,7 @@ impl Nip34WritePolicy { | |||
| 205 | /// - This state event is the latest for the identifier in that context | 219 | /// - This state event is the latest for the identifier in that context |
| 206 | async fn identify_owner_repositories( | 220 | async fn identify_owner_repositories( |
| 207 | &self, | 221 | &self, |
| 208 | database: &Arc<MemoryDatabase>, | 222 | database: &SharedDatabase, |
| 209 | state: &RepositoryState, | 223 | state: &RepositoryState, |
| 210 | ) -> Result<Vec<(RepositoryAnnouncement, std::path::PathBuf)>, String> { | 224 | ) -> Result<Vec<(RepositoryAnnouncement, std::path::PathBuf)>, String> { |
| 211 | // Find all announcements where state author is authorized | 225 | // Find all announcements where state author is authorized |
| @@ -485,7 +499,7 @@ impl Nip34WritePolicy { | |||
| 485 | /// Ok(Some(n)) if n refs were deleted, Ok(None) if no action taken, Err on failure | 499 | /// Ok(Some(n)) if n refs were deleted, Ok(None) if no action taken, Err on failure |
| 486 | async fn validate_pr_nostr_ref( | 500 | async fn validate_pr_nostr_ref( |
| 487 | &self, | 501 | &self, |
| 488 | database: &Arc<MemoryDatabase>, | 502 | database: &SharedDatabase, |
| 489 | event: &Event, | 503 | event: &Event, |
| 490 | ) -> Result<Option<usize>, String> { | 504 | ) -> Result<Option<usize>, String> { |
| 491 | let event_id = event.id.to_hex(); | 505 | let event_id = event.id.to_hex(); |
| @@ -651,7 +665,7 @@ impl Nip34WritePolicy { | |||
| 651 | /// Check if any addressable events (repositories) exist in database | 665 | /// Check if any addressable events (repositories) exist in database |
| 652 | /// Returns the first matching addressable reference found, or None if none match | 666 | /// Returns the first matching addressable reference found, or None if none match |
| 653 | async fn find_accepted_repository( | 667 | async fn find_accepted_repository( |
| 654 | database: &Arc<MemoryDatabase>, | 668 | database: &SharedDatabase, |
| 655 | addressables: &[String], | 669 | addressables: &[String], |
| 656 | ) -> Result<Option<String>, String> { | 670 | ) -> Result<Option<String>, String> { |
| 657 | if addressables.is_empty() { | 671 | if addressables.is_empty() { |
| @@ -724,7 +738,7 @@ impl Nip34WritePolicy { | |||
| 724 | /// Check if any events exist in database | 738 | /// Check if any events exist in database |
| 725 | /// Returns the first matching event ID found, or None if none match | 739 | /// Returns the first matching event ID found, or None if none match |
| 726 | async fn find_accepted_event( | 740 | async fn find_accepted_event( |
| 727 | database: &Arc<MemoryDatabase>, | 741 | database: &SharedDatabase, |
| 728 | event_ids: &[EventId], | 742 | event_ids: &[EventId], |
| 729 | ) -> Result<Option<EventId>, String> { | 743 | ) -> Result<Option<EventId>, String> { |
| 730 | if event_ids.is_empty() { | 744 | if event_ids.is_empty() { |
| @@ -752,7 +766,7 @@ impl Nip34WritePolicy { | |||
| 752 | /// This optimization recognizes that replaceable events are referenced by coordinate address, | 766 | /// This optimization recognizes that replaceable events are referenced by coordinate address, |
| 753 | /// while regular events are referenced by event ID. | 767 | /// while regular events are referenced by event ID. |
| 754 | async fn is_referenced_by_accepted( | 768 | async fn is_referenced_by_accepted( |
| 755 | database: &Arc<MemoryDatabase>, | 769 | database: &SharedDatabase, |
| 756 | event: &Event, | 770 | event: &Event, |
| 757 | ) -> Result<bool, String> { | 771 | ) -> Result<bool, String> { |
| 758 | let kind_u16 = event.kind.as_u16(); | 772 | let kind_u16 = event.kind.as_u16(); |
| @@ -1152,14 +1166,14 @@ pub struct RelayWithDatabase { | |||
| 1152 | /// The local relay instance | 1166 | /// The local relay instance |
| 1153 | pub relay: LocalRelay, | 1167 | pub relay: LocalRelay, |
| 1154 | /// The database Arc that can be used for direct queries | 1168 | /// The database Arc that can be used for direct queries |
| 1155 | pub database: Arc<MemoryDatabase>, | 1169 | pub database: SharedDatabase, |
| 1156 | } | 1170 | } |
| 1157 | 1171 | ||
| 1158 | /// Create a configured LocalRelay with full GRASP-01 validation | 1172 | /// Create a configured LocalRelay with full GRASP-01 validation |
| 1159 | /// | 1173 | /// |
| 1160 | /// Returns a `RelayWithDatabase` struct containing: | 1174 | /// Returns a `RelayWithDatabase` struct containing: |
| 1161 | /// - The `LocalRelay` for handling WebSocket connections | 1175 | /// - The `LocalRelay` for handling WebSocket connections |
| 1162 | /// - The `Arc<MemoryDatabase>` for direct database queries (e.g., push authorization) | 1176 | /// - The `SharedDatabase` for direct database queries (e.g., push authorization) |
| 1163 | pub fn create_relay(config: &Config) -> Result<RelayWithDatabase> { | 1177 | pub fn create_relay(config: &Config) -> Result<RelayWithDatabase> { |
| 1164 | tracing::info!("Configuring nostr relay with GRASP-01 validation..."); | 1178 | tracing::info!("Configuring nostr relay with GRASP-01 validation..."); |
| 1165 | 1179 | ||
| @@ -1167,7 +1181,7 @@ pub fn create_relay(config: &Config) -> Result<RelayWithDatabase> { | |||
| 1167 | let db_path = Path::new(&config.relay_data_path); | 1181 | let db_path = Path::new(&config.relay_data_path); |
| 1168 | 1182 | ||
| 1169 | // Create database based on configuration | 1183 | // Create database based on configuration |
| 1170 | let database = match config.database_backend { | 1184 | let database: SharedDatabase = match config.database_backend { |
| 1171 | DatabaseBackend::Memory => { | 1185 | DatabaseBackend::Memory => { |
| 1172 | tracing::info!("Using in-memory database (no persistence)"); | 1186 | tracing::info!("Using in-memory database (no persistence)"); |
| 1173 | Arc::new(MemoryDatabase::with_opts(MemoryDatabaseOptions { | 1187 | Arc::new(MemoryDatabase::with_opts(MemoryDatabaseOptions { |
| @@ -1187,13 +1201,13 @@ pub fn create_relay(config: &Config) -> Result<RelayWithDatabase> { | |||
| 1187 | } | 1201 | } |
| 1188 | DatabaseBackend::Lmdb => { | 1202 | DatabaseBackend::Lmdb => { |
| 1189 | tracing::info!("Using LMDB backend at: {}", db_path.display()); | 1203 | tracing::info!("Using LMDB backend at: {}", db_path.display()); |
| 1190 | // TODO: Implement LMDB backend once nostr-relay-builder supports it | 1204 | // Ensure the database directory exists |
| 1191 | // For now, fall back to memory database | 1205 | std::fs::create_dir_all(db_path).map_err(|e| { |
| 1192 | tracing::warn!("LMDB backend not yet implemented, using in-memory database"); | 1206 | anyhow::anyhow!("Failed to create LMDB directory {}: {}", db_path.display(), e) |
| 1193 | Arc::new(MemoryDatabase::with_opts(MemoryDatabaseOptions { | 1207 | })?; |
| 1194 | events: true, | 1208 | Arc::new(NostrLMDB::open(db_path).map_err(|e| { |
| 1195 | max_events: Some(100_000), | 1209 | anyhow::anyhow!("Failed to open LMDB database at {}: {}", db_path.display(), e) |
| 1196 | })) | 1210 | })?) |
| 1197 | } | 1211 | } |
| 1198 | }; | 1212 | }; |
| 1199 | 1213 | ||