Constellation, Spacedust, Slingshot, UFOs: atproto crates and services for microcosm
75
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #8 from at-microcosm/ufos-deadlock-debug

Ufos deadlock debug

authored by

phil and committed by
GitHub
89f8041d 962fe4f1

+705 -359
+221 -174
Cargo.lock
··· 202 202 203 203 [[package]] 204 204 name = "async-trait" 205 - version = "0.1.87" 205 + version = "0.1.88" 206 206 source = "registry+https://github.com/rust-lang/crates.io-index" 207 - checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" 207 + checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" 208 208 dependencies = [ 209 209 "proc-macro2", 210 210 "quote", ··· 398 398 399 399 [[package]] 400 400 name = "basic-toml" 401 - version = "0.1.9" 401 + version = "0.1.10" 402 402 source = "registry+https://github.com/rust-lang/crates.io-index" 403 - checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" 403 + checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" 404 404 dependencies = [ 405 405 "serde", 406 406 ] ··· 473 473 ] 474 474 475 475 [[package]] 476 + name = "bindgen" 477 + version = "0.71.1" 478 + source = "registry+https://github.com/rust-lang/crates.io-index" 479 + checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" 480 + dependencies = [ 481 + "bitflags", 482 + "cexpr", 483 + "clang-sys", 484 + "itertools 0.13.0", 485 + "proc-macro2", 486 + "quote", 487 + "regex", 488 + "rustc-hash 2.1.1", 489 + "shlex", 490 + "syn", 491 + ] 492 + 493 + [[package]] 476 494 name = "bitflags" 477 - version = "2.8.0" 495 + version = "2.9.0" 478 496 source = "registry+https://github.com/rust-lang/crates.io-index" 479 - checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" 497 + checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 480 498 481 499 [[package]] 482 500 name = "block-buffer" ··· 507 525 508 526 [[package]] 509 527 name = "bytes" 510 - version = "1.10.0" 528 + version = "1.10.1" 511 529 source = "registry+https://github.com/rust-lang/crates.io-index" 512 - checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" 530 + checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 513 531 514 532 [[package]] 515 533 name = "byteview" ··· 519 537 520 538 [[package]] 521 539 name = "bzip2-sys" 522 - version = "0.1.11+1.0.8" 540 + version = "0.1.13+1.0.8" 523 541 source = "registry+https://github.com/rust-lang/crates.io-index" 524 - checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" 542 + checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" 525 543 dependencies = [ 526 544 "cc", 527 - "libc", 528 545 "pkg-config", 529 546 ] 530 547 ··· 539 556 540 557 [[package]] 541 558 name = "cc" 542 - version = "1.2.12" 559 + version = "1.2.17" 543 560 source = "registry+https://github.com/rust-lang/crates.io-index" 544 - checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2" 561 + checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" 545 562 dependencies = [ 546 563 "jobserver", 547 564 "libc", ··· 571 588 572 589 [[package]] 573 590 name = "chrono" 574 - version = "0.4.39" 591 + version = "0.4.40" 575 592 source = "registry+https://github.com/rust-lang/crates.io-index" 576 - checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" 593 + checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" 577 594 dependencies = [ 578 595 "android-tzdata", 579 596 "iana-time-zone", ··· 581 598 "num-traits", 582 599 "serde", 583 600 "wasm-bindgen", 584 - "windows-targets", 601 + "windows-link", 585 602 ] 586 603 587 604 [[package]] ··· 611 628 612 629 [[package]] 613 630 name = "clap" 614 - version = "4.5.31" 631 + version = "4.5.33" 615 632 source = "registry+https://github.com/rust-lang/crates.io-index" 616 - checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" 633 + checksum = "e2c80cae4c3350dd8f1272c73e83baff9a6ba550b8bfbe651b3c45b78cd1751e" 617 634 dependencies = [ 618 635 "clap_builder", 619 636 "clap_derive", ··· 621 638 622 639 [[package]] 623 640 name = "clap_builder" 624 - version = "4.5.31" 641 + version = "4.5.33" 625 642 source = "registry+https://github.com/rust-lang/crates.io-index" 626 - checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" 643 + checksum = "0123e386f691c90aa228219b5b1ee72d465e8e231c79e9c82324f016a62a741c" 627 644 dependencies = [ 628 645 "anstream", 629 646 "anstyle", ··· 633 650 634 651 [[package]] 635 652 name = "clap_derive" 636 - version = "4.5.28" 653 + version = "4.5.32" 637 654 source = "registry+https://github.com/rust-lang/crates.io-index" 638 - checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" 655 + checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" 639 656 dependencies = [ 640 657 "heck", 641 658 "proc-macro2", ··· 855 872 856 873 [[package]] 857 874 name = "data-encoding" 858 - version = "2.7.0" 875 + version = "2.8.0" 859 876 source = "registry+https://github.com/rust-lang/crates.io-index" 860 - checksum = "0e60eed09d8c01d3cee5b7d30acb059b76614c918fa0f992e0dd6eeb10daad6f" 877 + checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" 861 878 862 879 [[package]] 863 880 name = "data-encoding-macro" 864 - version = "0.1.16" 881 + version = "0.1.17" 865 882 source = "registry+https://github.com/rust-lang/crates.io-index" 866 - checksum = "5b16d9d0d88a5273d830dac8b78ceb217ffc9b1d5404e5597a3542515329405b" 883 + checksum = "9f9724adfcf41f45bf652b3995837669d73c4d49a1b5ac1ff82905ac7d9b5558" 867 884 dependencies = [ 868 885 "data-encoding", 869 886 "data-encoding-macro-internal", ··· 871 888 872 889 [[package]] 873 890 name = "data-encoding-macro-internal" 874 - version = "0.1.14" 891 + version = "0.1.15" 875 892 source = "registry+https://github.com/rust-lang/crates.io-index" 876 - checksum = "1145d32e826a7748b69ee8fc62d3e6355ff7f1051df53141e7048162fc90481b" 893 + checksum = "18e4fdb82bd54a12e42fb58a800dcae6b9e13982238ce2296dc3570b92148e1f" 877 894 dependencies = [ 878 895 "data-encoding", 879 896 "syn", ··· 887 904 888 905 [[package]] 889 906 name = "deranged" 890 - version = "0.3.11" 907 + version = "0.4.1" 891 908 source = "registry+https://github.com/rust-lang/crates.io-index" 892 - checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" 909 + checksum = "28cfac68e08048ae1883171632c2aef3ebc555621ae56fbccce1cbf22dd7f058" 893 910 dependencies = [ 894 911 "powerfmt", 895 912 "serde", ··· 964 981 "http-body-util", 965 982 "hyper", 966 983 "hyper-util", 967 - "indexmap 2.7.1", 984 + "indexmap 2.8.0", 968 985 "multer", 969 986 "openapiv3", 970 987 "paste", ··· 1016 1033 1017 1034 [[package]] 1018 1035 name = "either" 1019 - version = "1.13.0" 1036 + version = "1.15.0" 1020 1037 source = "registry+https://github.com/rust-lang/crates.io-index" 1021 - checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 1038 + checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 1022 1039 1023 1040 [[package]] 1024 1041 name = "encoding_rs" ··· 1066 1083 1067 1084 [[package]] 1068 1085 name = "equivalent" 1069 - version = "1.0.1" 1086 + version = "1.0.2" 1070 1087 source = "registry+https://github.com/rust-lang/crates.io-index" 1071 - checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 1088 + checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 1072 1089 1073 1090 [[package]] 1074 1091 name = "errno" ··· 1109 1126 1110 1127 [[package]] 1111 1128 name = "fjall" 1112 - version = "2.6.7" 1113 - source = "registry+https://github.com/rust-lang/crates.io-index" 1114 - checksum = "0ad81b05d96e456433c704ae51210be48241c43214f97820c9254b80f9428cae" 1129 + version = "2.7.0" 1130 + source = "git+https://github.com/fjall-rs/fjall.git?branch=fix%2Flockless-ranges#d2102006958b0b30bdde0f7315b9b22539bb5f89" 1115 1131 dependencies = [ 1116 1132 "byteorder", 1117 1133 "byteview", ··· 1151 1167 1152 1168 [[package]] 1153 1169 name = "foldhash" 1154 - version = "0.1.4" 1170 + version = "0.1.5" 1155 1171 source = "registry+https://github.com/rust-lang/crates.io-index" 1156 - checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" 1172 + checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" 1157 1173 1158 1174 [[package]] 1159 1175 name = "foreign-types" ··· 1185 1201 source = "registry+https://github.com/rust-lang/crates.io-index" 1186 1202 checksum = "c29c30684418547d476f0b48e84f4821639119c483b1eccd566c8cd0cd05f521" 1187 1203 dependencies = [ 1188 - "rustix", 1204 + "rustix 0.38.44", 1189 1205 "windows-sys 0.52.0", 1190 1206 ] 1191 1207 ··· 1314 1330 1315 1331 [[package]] 1316 1332 name = "getrandom" 1317 - version = "0.3.1" 1333 + version = "0.3.2" 1318 1334 source = "registry+https://github.com/rust-lang/crates.io-index" 1319 - checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" 1335 + checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" 1320 1336 dependencies = [ 1321 1337 "cfg-if", 1322 1338 "libc", 1323 - "wasi 0.13.3+wasi-0.2.2", 1324 - "windows-targets", 1339 + "r-efi", 1340 + "wasi 0.14.2+wasi-0.2.4", 1325 1341 ] 1326 1342 1327 1343 [[package]] ··· 1344 1360 1345 1361 [[package]] 1346 1362 name = "h2" 1347 - version = "0.4.7" 1363 + version = "0.4.8" 1348 1364 source = "registry+https://github.com/rust-lang/crates.io-index" 1349 - checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" 1365 + checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" 1350 1366 dependencies = [ 1351 1367 "atomic-waker", 1352 1368 "bytes", ··· 1354 1370 "futures-core", 1355 1371 "futures-sink", 1356 1372 "http", 1357 - "indexmap 2.7.1", 1373 + "indexmap 2.8.0", 1358 1374 "slab", 1359 1375 "tokio", 1360 1376 "tokio-util", ··· 1461 1477 1462 1478 [[package]] 1463 1479 name = "http" 1464 - version = "1.2.0" 1480 + version = "1.3.1" 1465 1481 source = "registry+https://github.com/rust-lang/crates.io-index" 1466 - checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" 1482 + checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 1467 1483 dependencies = [ 1468 1484 "bytes", 1469 1485 "fnv", ··· 1482 1498 1483 1499 [[package]] 1484 1500 name = "http-body-util" 1485 - version = "0.1.2" 1501 + version = "0.1.3" 1486 1502 source = "registry+https://github.com/rust-lang/crates.io-index" 1487 - checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" 1503 + checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 1488 1504 dependencies = [ 1489 1505 "bytes", 1490 - "futures-util", 1506 + "futures-core", 1491 1507 "http", 1492 1508 "http-body", 1493 1509 "pin-project-lite", ··· 1495 1511 1496 1512 [[package]] 1497 1513 name = "httparse" 1498 - version = "1.10.0" 1514 + version = "1.10.1" 1499 1515 source = "registry+https://github.com/rust-lang/crates.io-index" 1500 - checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" 1516 + checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 1501 1517 1502 1518 [[package]] 1503 1519 name = "httpdate" ··· 1556 1572 1557 1573 [[package]] 1558 1574 name = "iana-time-zone" 1559 - version = "0.1.61" 1575 + version = "0.1.62" 1560 1576 source = "registry+https://github.com/rust-lang/crates.io-index" 1561 - checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" 1577 + checksum = "b2fd658b06e56721792c5df4475705b6cda790e9298d19d2f8af083457bcd127" 1562 1578 dependencies = [ 1563 1579 "android_system_properties", 1564 1580 "core-foundation-sys", 1565 1581 "iana-time-zone-haiku", 1566 1582 "js-sys", 1583 + "log", 1567 1584 "wasm-bindgen", 1568 1585 "windows-core 0.52.0", 1569 1586 ] ··· 1618 1635 1619 1636 [[package]] 1620 1637 name = "icu_locid_transform_data" 1621 - version = "1.5.0" 1638 + version = "1.5.1" 1622 1639 source = "registry+https://github.com/rust-lang/crates.io-index" 1623 - checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" 1640 + checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" 1624 1641 1625 1642 [[package]] 1626 1643 name = "icu_normalizer" ··· 1642 1659 1643 1660 [[package]] 1644 1661 name = "icu_normalizer_data" 1645 - version = "1.5.0" 1662 + version = "1.5.1" 1646 1663 source = "registry+https://github.com/rust-lang/crates.io-index" 1647 - checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" 1664 + checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" 1648 1665 1649 1666 [[package]] 1650 1667 name = "icu_properties" ··· 1663 1680 1664 1681 [[package]] 1665 1682 name = "icu_properties_data" 1666 - version = "1.5.0" 1683 + version = "1.5.1" 1667 1684 source = "registry+https://github.com/rust-lang/crates.io-index" 1668 - checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" 1685 + checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" 1669 1686 1670 1687 [[package]] 1671 1688 name = "icu_provider" ··· 1735 1752 1736 1753 [[package]] 1737 1754 name = "indexmap" 1738 - version = "2.7.1" 1755 + version = "2.8.0" 1739 1756 source = "registry+https://github.com/rust-lang/crates.io-index" 1740 - checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" 1757 + checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" 1741 1758 dependencies = [ 1742 1759 "equivalent", 1743 1760 "hashbrown 0.15.2", ··· 1807 1824 1808 1825 [[package]] 1809 1826 name = "itoa" 1810 - version = "1.0.14" 1827 + version = "1.0.15" 1811 1828 source = "registry+https://github.com/rust-lang/crates.io-index" 1812 - checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" 1829 + checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 1813 1830 1814 1831 [[package]] 1815 1832 name = "jetstream" ··· 1833 1850 1834 1851 [[package]] 1835 1852 name = "jiff" 1836 - version = "0.2.4" 1853 + version = "0.2.5" 1837 1854 source = "registry+https://github.com/rust-lang/crates.io-index" 1838 - checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e" 1855 + checksum = "c102670231191d07d37a35af3eb77f1f0dbf7a71be51a962dcd57ea607be7260" 1839 1856 dependencies = [ 1840 1857 "jiff-static", 1841 1858 "log", ··· 1846 1863 1847 1864 [[package]] 1848 1865 name = "jiff-static" 1849 - version = "0.2.4" 1866 + version = "0.2.5" 1850 1867 source = "registry+https://github.com/rust-lang/crates.io-index" 1851 - checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9" 1868 + checksum = "4cdde31a9d349f1b1f51a0b3714a5940ac022976f4b49485fc04be052b183b4c" 1852 1869 dependencies = [ 1853 1870 "proc-macro2", 1854 1871 "quote", ··· 1897 1914 1898 1915 [[package]] 1899 1916 name = "libc" 1900 - version = "0.2.169" 1917 + version = "0.2.171" 1901 1918 source = "registry+https://github.com/rust-lang/crates.io-index" 1902 - checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" 1919 + checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" 1903 1920 1904 1921 [[package]] 1905 1922 name = "libloading" ··· 1955 1972 1956 1973 [[package]] 1957 1974 name = "libz-sys" 1958 - version = "1.1.21" 1975 + version = "1.1.22" 1959 1976 source = "registry+https://github.com/rust-lang/crates.io-index" 1960 - checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa" 1977 + checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" 1961 1978 dependencies = [ 1962 1979 "cc", 1963 1980 "pkg-config", ··· 1982 1999 checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" 1983 2000 1984 2001 [[package]] 2002 + name = "linux-raw-sys" 2003 + version = "0.9.3" 2004 + source = "registry+https://github.com/rust-lang/crates.io-index" 2005 + checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" 2006 + 2007 + [[package]] 1985 2008 name = "litemap" 1986 2009 version = "0.7.5" 1987 2010 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1999 2022 2000 2023 [[package]] 2001 2024 name = "log" 2002 - version = "0.4.26" 2025 + version = "0.4.27" 2003 2026 source = "registry+https://github.com/rust-lang/crates.io-index" 2004 - checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" 2027 + checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 2005 2028 2006 2029 [[package]] 2007 2030 name = "loom" ··· 2027 2050 2028 2051 [[package]] 2029 2052 name = "lsm-tree" 2030 - version = "2.6.6" 2031 - source = "registry+https://github.com/rust-lang/crates.io-index" 2032 - checksum = "49c29f6322847a38368942f42eb86c3875fb2e946276f9f3df805cc6ada80b81" 2053 + version = "2.7.0" 2054 + source = "git+https://github.com/fjall-rs/lsm-tree.git?branch=fix%2Flockless-ranges#c1684bdf57488a6195942fde5ea0c756dc0b6035" 2033 2055 dependencies = [ 2034 2056 "byteorder", 2035 2057 "crossbeam-skiplist", ··· 2090 2112 2091 2113 [[package]] 2092 2114 name = "mediatype" 2093 - version = "0.19.18" 2115 + version = "0.19.20" 2094 2116 source = "registry+https://github.com/rust-lang/crates.io-index" 2095 - checksum = "8878cd8d1b3c8c8ae4b2ba0a36652b7cf192f618a599a7fbdfa25cffd4ea72dd" 2117 + checksum = "33746aadcb41349ec291e7f2f0a3aa6834d1d7c58066fb4b01f68efc4c4b7631" 2096 2118 2097 2119 [[package]] 2098 2120 name = "memchr" ··· 2120 2142 "http-body-util", 2121 2143 "hyper", 2122 2144 "hyper-util", 2123 - "indexmap 2.7.1", 2145 + "indexmap 2.8.0", 2124 2146 "ipnet", 2125 2147 "metrics", 2126 2148 "metrics-util", ··· 2186 2208 2187 2209 [[package]] 2188 2210 name = "miniz_oxide" 2189 - version = "0.8.3" 2211 + version = "0.8.5" 2190 2212 source = "registry+https://github.com/rust-lang/crates.io-index" 2191 - checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" 2213 + checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" 2192 2214 dependencies = [ 2193 2215 "adler2", 2194 2216 ] ··· 2267 2289 2268 2290 [[package]] 2269 2291 name = "native-tls" 2270 - version = "0.2.13" 2292 + version = "0.2.14" 2271 2293 source = "registry+https://github.com/rust-lang/crates.io-index" 2272 - checksum = "0dab59f8e050d5df8e4dd87d9206fb6f65a483e20ac9fda365ade4fab353196c" 2294 + checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" 2273 2295 dependencies = [ 2274 2296 "libc", 2275 2297 "log", ··· 2359 2381 2360 2382 [[package]] 2361 2383 name = "once_cell" 2362 - version = "1.20.2" 2384 + version = "1.21.1" 2363 2385 source = "registry+https://github.com/rust-lang/crates.io-index" 2364 - checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 2386 + checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" 2365 2387 2366 2388 [[package]] 2367 2389 name = "openapiv3" ··· 2369 2391 source = "registry+https://github.com/rust-lang/crates.io-index" 2370 2392 checksum = "cc02deea53ffe807708244e5914f6b099ad7015a207ee24317c22112e17d9c5c" 2371 2393 dependencies = [ 2372 - "indexmap 2.7.1", 2394 + "indexmap 2.8.0", 2373 2395 "serde", 2374 2396 "serde_json", 2375 2397 ] 2376 2398 2377 2399 [[package]] 2378 2400 name = "openssl" 2379 - version = "0.10.70" 2401 + version = "0.10.71" 2380 2402 source = "registry+https://github.com/rust-lang/crates.io-index" 2381 - checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6" 2403 + checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" 2382 2404 dependencies = [ 2383 2405 "bitflags", 2384 2406 "cfg-if", ··· 2417 2439 2418 2440 [[package]] 2419 2441 name = "openssl-sys" 2420 - version = "0.9.105" 2442 + version = "0.9.106" 2421 2443 source = "registry+https://github.com/rust-lang/crates.io-index" 2422 - checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" 2444 + checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" 2423 2445 dependencies = [ 2424 2446 "cc", 2425 2447 "libc", ··· 2507 2529 2508 2530 [[package]] 2509 2531 name = "pkg-config" 2510 - version = "0.3.31" 2532 + version = "0.3.32" 2511 2533 source = "registry+https://github.com/rust-lang/crates.io-index" 2512 - checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" 2534 + checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 2513 2535 2514 2536 [[package]] 2515 2537 name = "portable-atomic" 2516 - version = "1.10.0" 2538 + version = "1.11.0" 2517 2539 source = "registry+https://github.com/rust-lang/crates.io-index" 2518 - checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" 2540 + checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" 2519 2541 2520 2542 [[package]] 2521 2543 name = "portable-atomic-util" ··· 2534 2556 2535 2557 [[package]] 2536 2558 name = "ppv-lite86" 2537 - version = "0.2.20" 2559 + version = "0.2.21" 2538 2560 source = "registry+https://github.com/rust-lang/crates.io-index" 2539 - checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 2561 + checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 2540 2562 dependencies = [ 2541 - "zerocopy 0.7.35", 2563 + "zerocopy 0.8.24", 2542 2564 ] 2543 2565 2544 2566 [[package]] 2545 2567 name = "proc-macro2" 2546 - version = "1.0.93" 2568 + version = "1.0.94" 2547 2569 source = "registry+https://github.com/rust-lang/crates.io-index" 2548 - checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" 2570 + checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" 2549 2571 dependencies = [ 2550 2572 "unicode-ident", 2551 2573 ] ··· 2559 2581 "bitflags", 2560 2582 "hex", 2561 2583 "procfs-core", 2562 - "rustix", 2584 + "rustix 0.38.44", 2563 2585 ] 2564 2586 2565 2587 [[package]] ··· 2589 2611 2590 2612 [[package]] 2591 2613 name = "quick_cache" 2592 - version = "0.6.11" 2614 + version = "0.6.12" 2593 2615 source = "registry+https://github.com/rust-lang/crates.io-index" 2594 - checksum = "0af25b4e960ffdf0dead61cf0cec0c2e44c76927bf933ab4f02e2858fb449397" 2616 + checksum = "8f8ed0655cbaf18a26966142ad23b95d8ab47221c50c4f73a1db7d0d2d6e3da8" 2595 2617 dependencies = [ 2596 2618 "equivalent", 2597 2619 "hashbrown 0.15.2", ··· 2599 2621 2600 2622 [[package]] 2601 2623 name = "quote" 2602 - version = "1.0.38" 2624 + version = "1.0.40" 2603 2625 source = "registry+https://github.com/rust-lang/crates.io-index" 2604 - checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 2626 + checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 2605 2627 dependencies = [ 2606 2628 "proc-macro2", 2607 2629 ] 2630 + 2631 + [[package]] 2632 + name = "r-efi" 2633 + version = "5.2.0" 2634 + source = "registry+https://github.com/rust-lang/crates.io-index" 2635 + checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" 2608 2636 2609 2637 [[package]] 2610 2638 name = "rand" ··· 2625 2653 dependencies = [ 2626 2654 "rand_chacha 0.9.0", 2627 2655 "rand_core 0.9.3", 2628 - "zerocopy 0.8.23", 2656 + "zerocopy 0.8.24", 2629 2657 ] 2630 2658 2631 2659 [[package]] ··· 2663 2691 source = "registry+https://github.com/rust-lang/crates.io-index" 2664 2692 checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" 2665 2693 dependencies = [ 2666 - "getrandom 0.3.1", 2694 + "getrandom 0.3.2", 2667 2695 ] 2668 2696 2669 2697 [[package]] ··· 2688 2716 2689 2717 [[package]] 2690 2718 name = "raw-cpuid" 2691 - version = "11.3.0" 2719 + version = "11.5.0" 2692 2720 source = "registry+https://github.com/rust-lang/crates.io-index" 2693 - checksum = "c6928fa44c097620b706542d428957635951bade7143269085389d42c8a4927e" 2721 + checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" 2694 2722 dependencies = [ 2695 2723 "bitflags", 2696 2724 ] 2697 2725 2698 2726 [[package]] 2699 2727 name = "redox_syscall" 2700 - version = "0.5.8" 2728 + version = "0.5.10" 2701 2729 source = "registry+https://github.com/rust-lang/crates.io-index" 2702 - checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" 2730 + checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" 2703 2731 dependencies = [ 2704 2732 "bitflags", 2705 2733 ] ··· 2717 2745 2718 2746 [[package]] 2719 2747 name = "ref-cast" 2720 - version = "1.0.23" 2748 + version = "1.0.24" 2721 2749 source = "registry+https://github.com/rust-lang/crates.io-index" 2722 - checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" 2750 + checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" 2723 2751 dependencies = [ 2724 2752 "ref-cast-impl", 2725 2753 ] 2726 2754 2727 2755 [[package]] 2728 2756 name = "ref-cast-impl" 2729 - version = "1.0.23" 2757 + version = "1.0.24" 2730 2758 source = "registry+https://github.com/rust-lang/crates.io-index" 2731 - checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" 2759 + checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" 2732 2760 dependencies = [ 2733 2761 "proc-macro2", 2734 2762 "quote", ··· 2848 2876 "bitflags", 2849 2877 "errno", 2850 2878 "libc", 2851 - "linux-raw-sys", 2879 + "linux-raw-sys 0.4.15", 2880 + "windows-sys 0.59.0", 2881 + ] 2882 + 2883 + [[package]] 2884 + name = "rustix" 2885 + version = "1.0.3" 2886 + source = "registry+https://github.com/rust-lang/crates.io-index" 2887 + checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96" 2888 + dependencies = [ 2889 + "bitflags", 2890 + "errno", 2891 + "libc", 2892 + "linux-raw-sys 0.9.3", 2852 2893 "windows-sys 0.59.0", 2853 2894 ] 2854 2895 ··· 2894 2935 2895 2936 [[package]] 2896 2937 name = "rustversion" 2897 - version = "1.0.19" 2938 + version = "1.0.20" 2898 2939 source = "registry+https://github.com/rust-lang/crates.io-index" 2899 - checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" 2940 + checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" 2900 2941 2901 2942 [[package]] 2902 2943 name = "ryu" 2903 - version = "1.0.19" 2944 + version = "1.0.20" 2904 2945 source = "registry+https://github.com/rust-lang/crates.io-index" 2905 - checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" 2946 + checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 2906 2947 2907 2948 [[package]] 2908 2949 name = "schannel" ··· 2996 3037 2997 3038 [[package]] 2998 3039 name = "serde_bytes" 2999 - version = "0.11.16" 3040 + version = "0.11.17" 3000 3041 source = "registry+https://github.com/rust-lang/crates.io-index" 3001 - checksum = "364fec0df39c49a083c9a8a18a23a6bcfd9af130fe9fe321d18520a0d113e09e" 3042 + checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" 3002 3043 dependencies = [ 3003 3044 "serde", 3004 3045 ] ··· 3032 3073 checksum = "9d2de91cf02bbc07cde38891769ccd5d4f073d22a40683aa4bc7a95781aaa2c4" 3033 3074 dependencies = [ 3034 3075 "form_urlencoded", 3035 - "indexmap 2.7.1", 3076 + "indexmap 2.8.0", 3036 3077 "itoa", 3037 3078 "ryu", 3038 3079 "serde", ··· 3052 3093 3053 3094 [[package]] 3054 3095 name = "serde_path_to_error" 3055 - version = "0.1.16" 3096 + version = "0.1.17" 3056 3097 source = "registry+https://github.com/rust-lang/crates.io-index" 3057 - checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" 3098 + checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" 3058 3099 dependencies = [ 3059 3100 "itoa", 3060 3101 "serde", ··· 3103 3144 "chrono", 3104 3145 "hex", 3105 3146 "indexmap 1.9.3", 3106 - "indexmap 2.7.1", 3147 + "indexmap 2.8.0", 3107 3148 "serde", 3108 3149 "serde_derive", 3109 3150 "serde_json", ··· 3230 3271 3231 3272 [[package]] 3232 3273 name = "smallvec" 3233 - version = "1.13.2" 3274 + version = "1.14.0" 3234 3275 source = "registry+https://github.com/rust-lang/crates.io-index" 3235 - checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 3276 + checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" 3236 3277 3237 3278 [[package]] 3238 3279 name = "socket2" ··· 3279 3320 3280 3321 [[package]] 3281 3322 name = "syn" 3282 - version = "2.0.98" 3323 + version = "2.0.100" 3283 3324 source = "registry+https://github.com/rust-lang/crates.io-index" 3284 - checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" 3325 + checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" 3285 3326 dependencies = [ 3286 3327 "proc-macro2", 3287 3328 "quote", ··· 3319 3360 3320 3361 [[package]] 3321 3362 name = "tempfile" 3322 - version = "3.16.0" 3363 + version = "3.19.1" 3323 3364 source = "registry+https://github.com/rust-lang/crates.io-index" 3324 - checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" 3365 + checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" 3325 3366 dependencies = [ 3326 - "cfg-if", 3327 3367 "fastrand", 3328 - "getrandom 0.3.1", 3368 + "getrandom 0.3.2", 3329 3369 "once_cell", 3330 - "rustix", 3370 + "rustix 1.0.3", 3331 3371 "windows-sys 0.59.0", 3332 3372 ] 3333 3373 ··· 3414 3454 3415 3455 [[package]] 3416 3456 name = "time" 3417 - version = "0.3.37" 3457 + version = "0.3.41" 3418 3458 source = "registry+https://github.com/rust-lang/crates.io-index" 3419 - checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" 3459 + checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" 3420 3460 dependencies = [ 3421 3461 "deranged", 3422 3462 "itoa", ··· 3431 3471 3432 3472 [[package]] 3433 3473 name = "time-core" 3434 - version = "0.1.2" 3474 + version = "0.1.4" 3435 3475 source = "registry+https://github.com/rust-lang/crates.io-index" 3436 - checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" 3476 + checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" 3437 3477 3438 3478 [[package]] 3439 3479 name = "time-macros" 3440 - version = "0.2.19" 3480 + version = "0.2.22" 3441 3481 source = "registry+https://github.com/rust-lang/crates.io-index" 3442 - checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" 3482 + checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" 3443 3483 dependencies = [ 3444 3484 "num-conv", 3445 3485 "time-core", ··· 3463 3503 3464 3504 [[package]] 3465 3505 name = "tokio" 3466 - version = "1.43.0" 3506 + version = "1.44.1" 3467 3507 source = "registry+https://github.com/rust-lang/crates.io-index" 3468 - checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" 3508 + checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" 3469 3509 dependencies = [ 3470 3510 "backtrace", 3471 3511 "bytes", ··· 3527 3567 3528 3568 [[package]] 3529 3569 name = "tokio-util" 3530 - version = "0.7.13" 3570 + version = "0.7.14" 3531 3571 source = "registry+https://github.com/rust-lang/crates.io-index" 3532 - checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" 3572 + checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" 3533 3573 dependencies = [ 3534 3574 "bytes", 3535 3575 "futures-core", ··· 3565 3605 source = "registry+https://github.com/rust-lang/crates.io-index" 3566 3606 checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" 3567 3607 dependencies = [ 3568 - "indexmap 2.7.1", 3608 + "indexmap 2.8.0", 3569 3609 "serde", 3570 3610 "serde_spanned", 3571 3611 "toml_datetime", ··· 3702 3742 3703 3743 [[package]] 3704 3744 name = "typenum" 3705 - version = "1.17.0" 3745 + version = "1.18.0" 3706 3746 source = "registry+https://github.com/rust-lang/crates.io-index" 3707 - checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 3747 + checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" 3708 3748 3709 3749 [[package]] 3710 3750 name = "ufos" ··· 3736 3776 3737 3777 [[package]] 3738 3778 name = "unicode-ident" 3739 - version = "1.0.16" 3779 + version = "1.0.18" 3740 3780 source = "registry+https://github.com/rust-lang/crates.io-index" 3741 - checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" 3781 + checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 3742 3782 3743 3783 [[package]] 3744 3784 name = "unsigned-varint" ··· 3795 3835 3796 3836 [[package]] 3797 3837 name = "uuid" 3798 - version = "1.15.1" 3838 + version = "1.16.0" 3799 3839 source = "registry+https://github.com/rust-lang/crates.io-index" 3800 - checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" 3840 + checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" 3801 3841 dependencies = [ 3802 - "getrandom 0.3.1", 3842 + "getrandom 0.3.2", 3803 3843 "serde", 3804 3844 ] 3805 3845 ··· 3811 3851 3812 3852 [[package]] 3813 3853 name = "value-log" 3814 - version = "1.5.5" 3854 + version = "1.7.2" 3815 3855 source = "registry+https://github.com/rust-lang/crates.io-index" 3816 - checksum = "f2398750880b2b9770afbd1a3e299b9e859d6143c299867eb35fdf484b7625d3" 3856 + checksum = "d65573c63cf768179763226edb8d614d8b314130a3f50422d6d375d3947c529f" 3817 3857 dependencies = [ 3818 3858 "byteorder", 3819 3859 "bytes", ··· 3824 3864 "quick_cache", 3825 3865 "rustc-hash 2.1.1", 3826 3866 "tempfile", 3867 + "varint-rs", 3827 3868 "xxhash-rust", 3828 3869 ] 3829 3870 ··· 3877 3918 3878 3919 [[package]] 3879 3920 name = "wasi" 3880 - version = "0.13.3+wasi-0.2.2" 3921 + version = "0.14.2+wasi-0.2.4" 3881 3922 source = "registry+https://github.com/rust-lang/crates.io-index" 3882 - checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" 3923 + checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 3883 3924 dependencies = [ 3884 3925 "wit-bindgen-rt", 3885 3926 ] ··· 4049 4090 ] 4050 4091 4051 4092 [[package]] 4093 + name = "windows-link" 4094 + version = "0.1.1" 4095 + source = "registry+https://github.com/rust-lang/crates.io-index" 4096 + checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" 4097 + 4098 + [[package]] 4052 4099 name = "windows-result" 4053 4100 version = "0.2.0" 4054 4101 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4160 4207 4161 4208 [[package]] 4162 4209 name = "wit-bindgen-rt" 4163 - version = "0.33.0" 4210 + version = "0.39.0" 4164 4211 source = "registry+https://github.com/rust-lang/crates.io-index" 4165 - checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" 4212 + checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 4166 4213 dependencies = [ 4167 4214 "bitflags", 4168 4215 ] ··· 4215 4262 source = "registry+https://github.com/rust-lang/crates.io-index" 4216 4263 checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 4217 4264 dependencies = [ 4218 - "byteorder", 4219 4265 "zerocopy-derive 0.7.35", 4220 4266 ] 4221 4267 4222 4268 [[package]] 4223 4269 name = "zerocopy" 4224 - version = "0.8.23" 4270 + version = "0.8.24" 4225 4271 source = "registry+https://github.com/rust-lang/crates.io-index" 4226 - checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" 4272 + checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" 4227 4273 dependencies = [ 4228 - "zerocopy-derive 0.8.23", 4274 + "zerocopy-derive 0.8.24", 4229 4275 ] 4230 4276 4231 4277 [[package]] ··· 4241 4287 4242 4288 [[package]] 4243 4289 name = "zerocopy-derive" 4244 - version = "0.8.23" 4290 + version = "0.8.24" 4245 4291 source = "registry+https://github.com/rust-lang/crates.io-index" 4246 - checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" 4292 + checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" 4247 4293 dependencies = [ 4248 4294 "proc-macro2", 4249 4295 "quote", ··· 4301 4347 4302 4348 [[package]] 4303 4349 name = "zstd" 4304 - version = "0.13.2" 4350 + version = "0.13.3" 4305 4351 source = "registry+https://github.com/rust-lang/crates.io-index" 4306 - checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" 4352 + checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" 4307 4353 dependencies = [ 4308 4354 "zstd-safe", 4309 4355 ] 4310 4356 4311 4357 [[package]] 4312 4358 name = "zstd-safe" 4313 - version = "7.2.1" 4359 + version = "7.2.4" 4314 4360 source = "registry+https://github.com/rust-lang/crates.io-index" 4315 - checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" 4361 + checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" 4316 4362 dependencies = [ 4317 4363 "zstd-sys", 4318 4364 ] 4319 4365 4320 4366 [[package]] 4321 4367 name = "zstd-sys" 4322 - version = "2.0.13+zstd.1.5.6" 4368 + version = "2.0.15+zstd.1.5.7" 4323 4369 source = "registry+https://github.com/rust-lang/crates.io-index" 4324 - checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" 4370 + checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" 4325 4371 dependencies = [ 4372 + "bindgen 0.71.1", 4326 4373 "cc", 4327 4374 "pkg-config", 4328 4375 ]
+3
Cargo.toml
··· 6 6 "jetstream", 7 7 "ufos", 8 8 ] 9 + 10 + [patch.crates-io] 11 + lsm-tree = { git = "https://github.com/fjall-rs/lsm-tree.git", branch = "fix/lockless-ranges" }
+19
cozy-setup (move to another repo).md
··· 334 334 - stop upstreaming requests to older instance in nginx 335 335 336 336 337 + - systemd unit for running: `sudo nano /etc/systemd/system/constellation.service` 338 + 339 + ```toml 340 + [Unit] 341 + Description=Constellation backlinks index 342 + After=network.target 343 + 344 + [Service] 345 + User=pi 346 + WorkingDirectory=/home/pi/links/constellation 347 + ExecStart=/home/pi/links/target/release/main --backend rocks --data /mnt/constellation-index/ --jetstream us-east-2 --backup /home/pi/backup/constellation-index --backup-interval 6 --max-old-backups 20 348 + LimitNOFILE=16384 349 + Restart=always 350 + 351 + [Install] 352 + WantedBy=multi-user.target 353 + ``` 354 + 355 + 337 356 - todo: overlayfs? would need to figure out builds/updates still, also i guess logs are currently written to sd? (oof) 338 357 - todo: cross-compile for raspi? 339 358
+2
jetstream/src/error.rs
··· 46 46 WebSocketCloseFailure, 47 47 #[error("failed to send ping or pong: {0}")] 48 48 PingPongError(#[from] tokio_tungstenite::tungstenite::Error), 49 + #[error("jetstream event receiver closed")] 50 + ReceiverClosedError, 49 51 }
+13 -6
jetstream/src/lib.rs
··· 382 382 websocket_task(dict, ws_stream, send_channel.clone(), &mut last_cursor) 383 383 .await 384 384 { 385 + if let JetstreamEventError::ReceiverClosedError = e { 386 + log::error!("Jetstream receiver channel closed. Exiting consumer."); 387 + return; 388 + } 385 389 log::error!("Jetstream closed after encountering error: {e:?}"); 386 390 } else { 387 391 log::error!("Jetstream connection closed cleanly"); 388 392 } 389 393 if t_connected.elapsed() > Duration::from_secs(success_threshold_s) { 390 - retry_attempt = 1; 394 + retry_attempt = 0; 391 395 } 392 396 } 393 397 ··· 404 408 405 409 if retry_attempt > 0 { 406 410 // Exponential backoff 407 - let delay = (base_delay_ms * (2_u64.pow(retry_attempt))).min(max_delay_ms); 408 - log::error!("Connection failed, retrying in {delay}ms..."); 411 + let delay = 412 + (base_delay_ms * (2_u64.saturating_pow(retry_attempt))).min(max_delay_ms); 413 + log::error!("Connection failed, retry #{retry_attempt} in {delay}ms..."); 409 414 tokio::time::sleep(Duration::from_millis(delay)).await; 410 415 log::info!("Attempting to reconnect..."); 411 416 } ··· 451 456 log::info!( 452 457 "All receivers for the Jetstream connection have been dropped, closing connection." 453 458 ); 454 - closing_connection = true; 459 + socket_write.close().await?; 460 + return Err(JetstreamEventError::ReceiverClosedError); 455 461 } else if let Some(last) = last_cursor.as_mut() { 456 462 *last = event_cursor; 457 463 } ··· 484 490 // We can assume that all receivers have been dropped, so we can close 485 491 // the connection and exit the task. 486 492 log::info!( 487 - "All receivers for the Jetstream connection have been dropped, closing connection..." 493 + "All receivers for the Jetstream connection have been dropped, closing connection." 488 494 ); 489 - closing_connection = true; 495 + socket_write.close().await?; 496 + return Err(JetstreamEventError::ReceiverClosedError); 490 497 } else if let Some(last) = last_cursor.as_mut() { 491 498 *last = event_cursor; 492 499 }
+6 -1
ufos/Cargo.toml
··· 9 9 clap = { version = "4.5.31", features = ["derive"] } 10 10 dropshot = "0.16.0" 11 11 env_logger = "0.11.7" 12 - fjall = { version = "2.6.7", features = ["bytes", "single_writer_tx"], default-features = false } 13 12 jetstream = { path = "../jetstream" } 14 13 log = "0.4.26" 15 14 lsm-tree = "2.6.6" ··· 22 21 23 22 [target.'cfg(not(target_env = "msvc"))'.dependencies] 24 23 tikv-jemallocator = "0.6.0" 24 + 25 + [dependencies.fjall] 26 + git = "https://github.com/fjall-rs/fjall.git" 27 + branch = "fix/lockless-ranges" 28 + features = ["bytes", "single_writer_tx"] 29 + default-features = false
+27
ufos/readme.md
··· 16 16 cross build --release --target arm-unknown-linux-gnueabihf && scp ../target/arm-unknown-linux-gnueabihf/release/ufos angel-hair.local:ufos 17 17 ``` 18 18 19 + for bonilla (rp4) 20 + 21 + ```bash 22 + cross build --release --target armv7-unknown-linux-gnueabihf && scp ../target/armv7-unknown-linux-gnueabihf/release/ufos pi@bonilla.local:ufos 23 + ``` 24 + 25 + glibc will cause problems when switching between (`GLIBC_2.25` message). clean up (next build will be slowww) 26 + 27 + ```bash 28 + cargo clean 29 + ``` 30 + 19 31 nginx forward proxy for websocket (run this on another host): 20 32 21 33 ```nginx ··· 95 107 ``` 96 108 97 109 try without info-level logs for better perf 110 + 111 + running on bonilla 112 + 113 + ```bash 114 + ./ufos --jetstream us-west-2 --jetstream-force --data /mnt/ufos-data-no-compression-2/ 115 + ``` 116 + 117 + (reusing data dir from angel-hair) 118 + 119 + 120 + ipv6 is having some trouble. but also maybe there's a deadlock somewhere 121 + 122 + ```bash 123 + sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1 124 + ```
+15 -8
ufos/src/consumer.rs
··· 19 19 const MAX_ACCOUNT_REMOVES: usize = 512; // hard limit, total account deletions. actually the least frequent event, but tiny. 20 20 const MAX_BATCHED_COLLECTIONS: usize = 64; // hard limit, MAX_BATCHED_RECORDS applies per collection 21 21 const MIN_BATCH_SPAN_SECS: f64 = 2.; // try to get a bit of rest a bit. 22 - const MAX_BATCH_SPAN_SECS: f64 = 10.; // hard limit of duration from oldest to latest event cursor within a batch, in seconds. 23 - 24 - const SEND_TIMEOUT_S: f64 = 6.; 22 + const MAX_BATCH_SPAN_SECS: f64 = 60.; // hard limit of duration from oldest to latest event cursor within a batch, in seconds. 25 23 26 - const BATCH_QUEUE_SIZE: usize = 32; 27 - // const BATCH_QUEUE_SIZE: usize = 4096; 24 + const SEND_TIMEOUT_S: f64 = 60.; 25 + const BATCH_QUEUE_SIZE: usize = 1024; // 4096 got OOM'd 28 26 29 27 #[derive(Debug)] 30 28 struct Batcher { ··· 38 36 cursor: Option<Cursor>, 39 37 no_compress: bool, 40 38 ) -> anyhow::Result<Receiver<EventBatch>> { 39 + let endpoint = DefaultJetstreamEndpoints::endpoint_or_shortcut(jetstream_endpoint); 40 + if endpoint == jetstream_endpoint { 41 + eprintln!("connecting to jetstream at {endpoint}"); 42 + } else { 43 + eprintln!("connecting to jetstream at {jetstream_endpoint} => {endpoint}"); 44 + } 41 45 let config: JetstreamConfig<serde_json::Value> = JetstreamConfig { 42 - endpoint: DefaultJetstreamEndpoints::endpoint_or_shortcut(jetstream_endpoint), 46 + endpoint, 43 47 compression: if no_compress { 44 48 JetstreamCompression::None 45 49 } else { ··· 124 128 if event_cursor.duration_since(earliest)?.as_secs_f64() > MIN_BATCH_SPAN_SECS 125 129 && self.batch_sender.capacity() == BATCH_QUEUE_SIZE 126 130 { 127 - log::warn!("queue empty: immediately sending batch."); 131 + log::trace!("queue empty: immediately sending batch."); 128 132 if let Err(send_err) = self 129 133 .batch_sender 130 134 .send(mem::take(&mut self.current_batch)) ··· 140 144 // holds up all consumer progress until it can send to the channel 141 145 // use this when the current batch is too full to add more to it 142 146 async fn send_current_batch_now(&mut self) -> anyhow::Result<()> { 143 - log::warn!("attempting to send batch now"); 147 + log::warn!( 148 + "attempting to send batch now (capacity: {})", 149 + self.batch_sender.capacity() 150 + ); 144 151 self.batch_sender 145 152 .send_timeout( 146 153 mem::take(&mut self.current_batch),
+54 -13
ufos/src/main.rs
··· 28 28 /// Location to store persist data to disk 29 29 #[arg(long)] 30 30 data: PathBuf, 31 + /// DEBUG: don't start the jetstream consumer or its write loop 32 + #[arg(long, action)] 33 + pause_writer: bool, 34 + /// DEBUG: force the rw loop to fall behind by pausing it 35 + #[arg(long, action)] 36 + pause_rw: bool, 31 37 } 32 38 33 - // #[tokio::main] 34 - #[tokio::main(flavor = "current_thread")] // TODO: move this to config via args 39 + // #[tokio::main(flavor = "current_thread")] // TODO: move this to config via args 40 + #[tokio::main] 35 41 async fn main() -> anyhow::Result<()> { 36 42 env_logger::init(); 37 43 ··· 39 45 let (storage, cursor) = 40 46 store::Storage::open(args.data, &args.jetstream, args.jetstream_force).await?; 41 47 42 - println!( 43 - "starting consumer with cursor: {cursor:?} from {:?} ago", 44 - cursor.clone().map(|c| c.elapsed()) 45 - ); 46 - let batches = consumer::consume(&args.jetstream, cursor, args.jetstream_no_zstd).await?; 47 - 48 48 println!("starting server with storage..."); 49 49 let serving = server::serve(storage.clone()); 50 50 51 - tokio::select! { 52 - v = serving => eprintln!("serving ended: {v:?}"), 53 - v = storage.receive(batches) => eprintln!("storage consumer ended: {v:?}"), 54 - v = storage.rw_loop() => eprintln!("storage rw-loop ended: {v:?}"), 55 - }; 51 + let t1 = tokio::task::spawn(async { 52 + let r = serving.await; 53 + log::warn!("serving ended with: {r:?}"); 54 + }); 55 + 56 + let t2: tokio::task::JoinHandle<anyhow::Result<()>> = tokio::task::spawn({ 57 + let storage = storage.clone(); 58 + async move { 59 + if !args.pause_writer { 60 + println!( 61 + "starting consumer with cursor: {cursor:?} from {:?} ago", 62 + cursor.clone().map(|c| c.elapsed()) 63 + ); 64 + let batches = 65 + consumer::consume(&args.jetstream, cursor, args.jetstream_no_zstd).await?; 66 + let r = storage.receive(batches).await; 67 + log::warn!("storage.receive ended with: {r:?}"); 68 + } else { 69 + log::info!("not starting jetstream or the write loop."); 70 + } 71 + Ok(()) 72 + } 73 + }); 74 + 75 + let t3 = tokio::task::spawn(async move { 76 + if !args.pause_rw { 77 + let r = storage.rw_loop().await; 78 + log::warn!("storage.rw_loop ended with: {r:?}"); 79 + } else { 80 + log::info!("not starting rw loop."); 81 + } 82 + }); 83 + 84 + // tokio::select! { 85 + // // v = serving => eprintln!("serving ended: {v:?}"), 86 + // v = storage.receive(batches) => eprintln!("storage consumer ended: {v:?}"), 87 + // v = storage.rw_loop() => eprintln!("storage rw-loop ended: {v:?}"), 88 + // }; 89 + 90 + log::trace!("tasks running. waiting."); 91 + t1.await?; 92 + log::trace!("serve task ended."); 93 + t2.await??; 94 + log::trace!("storage receive task ended."); 95 + t3.await?; 96 + log::trace!("storage rw task ended."); 56 97 57 98 println!("bye!"); 58 99
+88 -46
ufos/src/server.rs
··· 6 6 use dropshot::ConfigLogging; 7 7 use dropshot::ConfigLoggingLevel; 8 8 use dropshot::HttpError; 9 + use dropshot::HttpResponseHeaders; 9 10 use dropshot::HttpResponseOk; 10 11 use dropshot::Query; 11 12 use dropshot::RequestContext; 12 13 use dropshot::ServerBuilder; 13 14 use schemars::JsonSchema; 14 15 use serde::{Deserialize, Serialize}; 16 + use std::collections::HashMap; 15 17 use std::sync::Arc; 16 18 17 19 #[derive(Clone)] ··· 25 27 method = GET, 26 28 path = "/openapi", 27 29 }] 28 - async fn get_openapi( 29 - ctx: RequestContext<Context>, 30 - ) -> Result<HttpResponseOk<serde_json::Value>, HttpError> { 30 + async fn get_openapi(ctx: RequestContext<Context>) -> OkCorsResponse<serde_json::Value> { 31 31 let spec = (*ctx.context().spec).clone(); 32 - Ok(HttpResponseOk(spec)) 32 + ok_cors(spec) 33 33 } 34 34 35 35 #[derive(Debug, Serialize, JsonSchema)] ··· 44 44 method = GET, 45 45 path = "/meta" 46 46 }] 47 - async fn get_meta_info( 48 - ctx: RequestContext<Context>, 49 - ) -> Result<HttpResponseOk<MetaInfo>, HttpError> { 47 + async fn get_meta_info(ctx: RequestContext<Context>) -> OkCorsResponse<MetaInfo> { 50 48 let Context { storage, .. } = ctx.context(); 51 49 52 50 let failed_to_get = ··· 75 73 .map_err(failed_to_get("jetstream cursor"))? 76 74 .map(|c| c.to_raw_u64()); 77 75 78 - Ok(HttpResponseOk(MetaInfo { 76 + ok_cors(MetaInfo { 79 77 storage_info, 80 78 jetstream_endpoint, 81 79 jetstream_cursor, 82 80 mod_cursor, 83 - })) 81 + }) 84 82 } 85 83 86 84 #[derive(Debug, Deserialize, JsonSchema)] 87 - struct CollectionQuery { 85 + struct CollectionsQuery { 88 86 collection: String, // JsonSchema not implemented for Nsid :( 87 + } 88 + impl CollectionsQuery { 89 + fn to_multiple_nsids(&self) -> Result<Vec<Nsid>, String> { 90 + let mut out = Vec::with_capacity(self.collection.len()); 91 + for collection in self.collection.split(',') { 92 + let Ok(nsid) = Nsid::new(collection.to_string()) else { 93 + return Err(format!("collection {collection:?} was not a valid NSID")); 94 + }; 95 + out.push(nsid); 96 + } 97 + Ok(out) 98 + } 89 99 } 90 100 #[derive(Debug, Serialize, JsonSchema)] 91 101 struct ApiRecord { ··· 113 123 } 114 124 } 115 125 /// Get recent records by collection 126 + /// 127 + /// Multiple collections are supported. they will be delivered in one big array with no 128 + /// specified order. 116 129 #[endpoint { 117 130 method = GET, 118 131 path = "/records", 119 132 }] 120 133 async fn get_records_by_collection( 121 134 ctx: RequestContext<Context>, 122 - collection_query: Query<CollectionQuery>, 123 - ) -> Result<HttpResponseOk<Vec<ApiRecord>>, HttpError> { 124 - let Ok(collection) = Nsid::new(collection_query.into_inner().collection) else { 125 - return Err(HttpError::for_bad_request( 126 - None, 127 - "collection must be an NSID".to_string(), 128 - )); 129 - }; 135 + collection_query: Query<CollectionsQuery>, 136 + ) -> OkCorsResponse<Vec<ApiRecord>> { 130 137 let Context { storage, .. } = ctx.context(); 131 - let records = storage 132 - .get_collection_records(&collection, 100) 133 - .await 134 - .map_err(|e| HttpError::for_internal_error(e.to_string()))?; 135 138 136 - if records.is_empty() { 137 - return Err(HttpError::for_not_found( 138 - None, 139 - format!("no saved records for collection {collection:?}"), 140 - )); 141 - } 139 + let collections = collection_query 140 + .into_inner() 141 + .to_multiple_nsids() 142 + .map_err(|reason| HttpError::for_bad_request(None, reason))?; 142 143 143 - let api_records = records 144 - .into_iter() 145 - .map(|r| ApiRecord::from_create_record(r, &collection)) 146 - .collect(); 144 + let mut api_records = Vec::new(); 147 145 148 - Ok(HttpResponseOk(api_records)) 146 + // TODO: set up multiple db iterators and iterate them together with merge sort 147 + for collection in &collections { 148 + let records = storage 149 + .get_collection_records(collection, 100) 150 + .await 151 + .map_err(|e| HttpError::for_internal_error(e.to_string()))?; 152 + 153 + for record in records { 154 + let api_record = ApiRecord::from_create_record(record, collection); 155 + api_records.push(api_record); 156 + } 157 + } 158 + 159 + ok_cors(api_records) 149 160 } 150 161 151 162 /// Get total records seen by collection ··· 153 164 method = GET, 154 165 path = "/records/total-seen" 155 166 }] 156 - async fn get_asdf( 167 + async fn get_records_total_seen( 157 168 ctx: RequestContext<Context>, 158 - collection_query: Query<CollectionQuery>, 159 - ) -> Result<HttpResponseOk<u64>, HttpError> { 160 - let Ok(collection) = Nsid::new(collection_query.into_inner().collection) else { 161 - return Err(HttpError::for_bad_request( 162 - None, 163 - "collection must be an NSID".to_string(), 164 - )); 165 - }; 169 + collection_query: Query<CollectionsQuery>, 170 + ) -> OkCorsResponse<HashMap<String, u64>> { 171 + let Context { storage, .. } = ctx.context(); 172 + 173 + let collections = collection_query 174 + .into_inner() 175 + .to_multiple_nsids() 176 + .map_err(|reason| HttpError::for_bad_request(None, reason))?; 177 + 178 + let mut seen_by_collection = HashMap::with_capacity(collections.len()); 179 + 180 + for collection in &collections { 181 + let total = storage 182 + .get_collection_total_seen(collection) 183 + .await 184 + .map_err(|e| HttpError::for_internal_error(format!("boooo: {e:?}")))?; 185 + 186 + seen_by_collection.insert(collection.to_string(), total); 187 + } 188 + 189 + ok_cors(seen_by_collection) 190 + } 191 + 192 + /// Get top collections 193 + #[endpoint { 194 + method = GET, 195 + path = "/collections" 196 + }] 197 + async fn get_top_collections(ctx: RequestContext<Context>) -> OkCorsResponse<HashMap<String, u64>> { 166 198 let Context { storage, .. } = ctx.context(); 167 - let total = storage 168 - .get_collection_total_seen(&collection) 199 + let collections = storage 200 + .get_top_collections() 169 201 .await 170 202 .map_err(|e| HttpError::for_internal_error(format!("boooo: {e:?}")))?; 171 203 172 - Ok(HttpResponseOk(total)) 204 + ok_cors(collections) 173 205 } 174 206 175 207 pub async fn serve(storage: Storage) -> Result<(), String> { ··· 184 216 api.register(get_openapi).unwrap(); 185 217 api.register(get_meta_info).unwrap(); 186 218 api.register(get_records_by_collection).unwrap(); 187 - api.register(get_asdf).unwrap(); 219 + api.register(get_records_total_seen).unwrap(); 220 + api.register(get_top_collections).unwrap(); 188 221 189 222 let context = Context { 190 223 spec: Arc::new( ··· 204 237 .map_err(|error| format!("failed to start server: {}", error))? 205 238 .await 206 239 } 240 + 241 + /// awkward helpers 242 + type OkCorsResponse<T> = Result<HttpResponseHeaders<HttpResponseOk<T>>, HttpError>; 243 + fn ok_cors<T: Send + Sync + Serialize + JsonSchema>(t: T) -> OkCorsResponse<T> { 244 + let mut res = HttpResponseHeaders::new_unnamed(HttpResponseOk(t)); 245 + res.headers_mut() 246 + .insert("access-control-allow-origin", "*".parse().unwrap()); 247 + Ok(res) 248 + }
+257 -111
ufos/src/store.rs
··· 14 14 use jetstream::events::Cursor; 15 15 use std::collections::HashMap; 16 16 use std::path::{Path, PathBuf}; 17 + use std::sync::Arc; 17 18 use std::time::{Duration, Instant}; 18 - use tokio::{sync::mpsc::Receiver, time::sleep}; 19 + use tokio::sync::mpsc::Receiver; 20 + use tokio::time::sleep; 19 21 20 - /// Commit the RW batch immediately if this nubmer of events have been read off the mod queue 22 + /// Commit the RW batch immediately if this number of events have been read off the mod queue 21 23 const MAX_BATCHED_RW_EVENTS: usize = 18; 22 24 23 25 /// Commit the RW batch immediately if this number of records is reached ··· 27 29 /// - doing more work whenever scheduled means getting more CPU time in general 28 30 /// 29 31 /// this is higher than [MAX_BATCHED_RW_EVENTS] because account-deletes can have lots of items 30 - const MAX_BATCHED_RW_ITEMS: usize = 36; 32 + const MAX_BATCHED_RW_ITEMS: usize = 24; 33 + 34 + #[derive(Clone)] 35 + struct SerialDb { 36 + keyspace: Keyspace, 37 + partition: PartitionHandle, 38 + } 39 + 40 + struct FakeMutex<T> { 41 + thing: T, 42 + } 43 + impl<T: Clone> FakeMutex<T> { 44 + pub fn new(thing: T) -> Self { 45 + Self { thing } 46 + } 47 + pub async fn lock(&self) -> T { 48 + self.thing.clone() 49 + } 50 + } 31 51 32 52 /** 33 53 * data format, roughly: ··· 56 76 **/ 57 77 #[derive(Clone)] 58 78 pub struct Storage { 59 - keyspace: Keyspace, 60 - partition: PartitionHandle, 79 + /// horrible: gate all db access behind this to force global serialization to avoid deadlock 80 + db: Arc<FakeMutex<SerialDb>>, 61 81 } 62 82 63 83 impl Storage { ··· 68 88 PartitionCreateOptions::default().compression(CompressionType::None), 69 89 )?; 70 90 Ok(Self { 71 - keyspace, 72 - partition, 91 + db: Arc::new(FakeMutex::new(SerialDb { 92 + keyspace, 93 + partition, 94 + })), 73 95 }) 74 96 } 75 97 ··· 108 130 // TODO: see rw_loop: enforce single-thread. 109 131 loop { 110 132 let t_sleep = Instant::now(); 111 - sleep(Duration::from_secs_f64(0.3)).await; // TODO: minimize during replay 133 + sleep(Duration::from_secs_f64(0.8)).await; // TODO: minimize during replay 112 134 let slept_for = t_sleep.elapsed(); 113 135 let queue_size = receiver.len(); 114 136 115 137 if let Some(event_batch) = receiver.recv().await { 138 + log::trace!("write: received write batch"); 116 139 let batch_summary = summarize_batch(&event_batch); 117 140 118 141 let last = event_batch.last_jetstream_cursor.clone(); // TODO: get this from the data. track last in consumer. compute or track first. 119 142 120 - let keyspace = self.keyspace.clone(); 121 - let partition = self.partition.clone(); 143 + let db = self.db.lock().await; 144 + let keyspace = db.keyspace.clone(); 145 + let partition = db.partition.clone(); 122 146 123 147 let writer_t0 = Instant::now(); 148 + log::trace!("spawn_blocking for write batch"); 124 149 tokio::task::spawn_blocking(move || { 125 150 DBWriter { 126 151 keyspace, ··· 129 154 .write_batch(event_batch, last) 130 155 }) 131 156 .await??; 157 + log::trace!("write: back from blocking task, successfully wrote batch"); 132 158 let wrote_for = writer_t0.elapsed(); 159 + drop(db); 133 160 134 161 println!("{batch_summary}, slept {slept_for: <12?}, wrote {wrote_for: <11?}, queue: {queue_size}"); 135 162 } else { 163 + log::error!("store consumer: receive channel failed (dropped/closed?)"); 136 164 anyhow::bail!("receive channel closed"); 137 165 } 138 166 } ··· 142 170 pub async fn rw_loop(&self) -> anyhow::Result<()> { 143 171 // TODO: lock so that only one rw loop can possibly be run. or even better, take a mutable resource thing to enforce at compile time. 144 172 loop { 145 - sleep(Duration::from_secs_f64(0.001)).await; // todo: interval rate-limit instead 146 - let keyspace = self.keyspace.clone(); 147 - let partition = self.partition.clone(); 173 + sleep(Duration::from_secs_f64(0.1)).await; // todo: interval rate-limit instead 174 + 175 + let db = self.db.lock().await; 176 + let keyspace = db.keyspace.clone(); 177 + let partition = db.partition.clone(); 178 + 179 + log::trace!("rw: spawn blocking for batch..."); 148 180 tokio::task::spawn_blocking(move || -> anyhow::Result<()> { 181 + log::trace!("rw: getting rw cursor..."); 149 182 let mod_cursor = get_static::<ModCursorKey, ModCursorValue>(&partition)? 150 183 .unwrap_or(Cursor::from_start()); 151 184 let range = ModQueueItemKey::new(mod_cursor.clone()).range_to_prefix_end()?; 152 185 153 186 let mut db_batch = keyspace.batch(); 154 187 let mut batched_rw_items = 0; 188 + let mut any_tasks_found = false; 155 189 156 - for (i, pair) in partition.range(range.clone()).enumerate() { 157 - if i >= MAX_BATCHED_RW_EVENTS { 158 - break; 159 - } 190 + log::trace!("rw: iterating newer rw items..."); 160 191 161 - let (key_bytes, val_bytes) = pair?; 162 - let mod_key = match db_complete::<ModQueueItemKey>(&key_bytes) { 163 - Ok(k) => k, 164 - Err(EncodingError::WrongStaticPrefix(_, _)) => { 165 - panic!("wsp: mod queue empty."); 192 + 193 + //// ITER 194 + 195 + { 196 + let iterator = partition.range(range.clone()).enumerate(); 197 + 198 + for (i, pair) in iterator { 199 + log::trace!("rw: iterating {i}"); 200 + any_tasks_found = true; 201 + 202 + if i >= MAX_BATCHED_RW_EVENTS { 203 + break; 166 204 } 167 - otherwise => otherwise?, 168 - }; 169 205 170 - let mod_value: ModQueueItemValue = 171 - db_complete::<ModQueueItemStringValue>(&val_bytes)?.try_into()?; 206 + let (key_bytes, val_bytes) = pair?; 207 + let mod_key = match db_complete::<ModQueueItemKey>(&key_bytes) { 208 + Ok(k) => k, 209 + Err(EncodingError::WrongStaticPrefix(_, _)) => { 210 + panic!("wsp: mod queue empty."); 211 + } 212 + otherwise => otherwise?, 213 + }; 172 214 173 - batched_rw_items += DBWriter { 174 - keyspace: keyspace.clone(), 175 - partition: partition.clone(), 176 - } 177 - .write_rw(&mut db_batch, mod_key, mod_value)?; 215 + let mod_value: ModQueueItemValue = 216 + db_complete::<ModQueueItemStringValue>(&val_bytes)?.try_into()?; 217 + 218 + log::trace!("rw: iterating {i}: sending to batcher {mod_key:?} => {mod_value:?}"); 219 + batched_rw_items += DBWriter { 220 + keyspace: keyspace.clone(), 221 + partition: partition.clone(), 222 + } 223 + .write_rw(&mut db_batch, mod_key, mod_value)?; 224 + log::trace!("rw: iterating {i}: back from batcher."); 178 225 179 - if batched_rw_items >= MAX_BATCHED_RW_ITEMS { 180 - break; 226 + if batched_rw_items >= MAX_BATCHED_RW_ITEMS { 227 + log::trace!("rw: iterating {i}: batch big enough, breaking out."); 228 + break; 229 + } 181 230 } 231 + // drop(iterator); // moved -- must be dropped hopefully 182 232 } 183 233 184 - db_batch.commit()?; 234 + if !any_tasks_found { 235 + log::trace!("rw: skipping batch commit since apparently no items were added (this is normal, skipping is new)"); 236 + return Ok(()); 237 + } 238 + 239 + log::info!("rw: committing rw batch with {batched_rw_items} items (items != total inserts/deletes)..."); 240 + let r = db_batch.commit(); 241 + log::info!("rw: commit result: {r:?}"); 242 + r?; 185 243 Ok(()) 186 244 }) 187 245 .await??; 246 + log::trace!("rw: back from blocking for rw..."); 188 247 } 248 + // log::warn!("exited rw loop (rw task)"); 189 249 } 190 250 191 251 pub async fn get_collection_records( ··· 193 253 collection: &Nsid, 194 254 limit: usize, 195 255 ) -> anyhow::Result<Vec<CreateRecord>> { 196 - let partition = self.partition.clone(); 256 + let partition = self.db.lock().await.partition.clone(); 197 257 let prefix = ByCollectionKey::prefix_from_collection(collection.clone())?; 198 258 tokio::task::spawn_blocking(move || { 199 259 let mut output = Vec::new(); 200 - for pair in partition.prefix(&prefix).rev().take(limit) { 201 - let (k_bytes, v_bytes) = pair?; 202 - let (_, cursor) = db_complete::<ByCollectionKey>(&k_bytes)?.into(); 203 - let (did, rkey, record) = db_complete::<ByCollectionValue>(&v_bytes)?.into(); 204 - output.push(CreateRecord { 205 - did, 206 - rkey, 207 - record, 208 - cursor, 209 - }) 260 + 261 + ////// ITER 262 + { 263 + for pair in partition.prefix(&prefix).rev().take(limit) { 264 + let (k_bytes, v_bytes) = pair?; 265 + let (_, cursor) = db_complete::<ByCollectionKey>(&k_bytes)?.into(); 266 + let (did, rkey, record) = db_complete::<ByCollectionValue>(&v_bytes)?.into(); 267 + output.push(CreateRecord { 268 + did, 269 + rkey, 270 + record, 271 + cursor, 272 + }) 273 + } 210 274 } 211 275 Ok(output) 212 276 }) ··· 214 278 } 215 279 216 280 pub async fn get_meta_info(&self) -> anyhow::Result<StorageInfo> { 217 - let keyspace = self.keyspace.clone(); 218 - let partition = self.partition.clone(); 281 + let db = self.db.lock().await; 282 + let keyspace = db.keyspace.clone(); 283 + let partition = db.partition.clone(); 219 284 tokio::task::spawn_blocking(move || { 220 285 Ok(StorageInfo { 221 286 keyspace_disk_space: keyspace.disk_space(), ··· 228 293 } 229 294 230 295 pub async fn get_collection_total_seen(&self, collection: &Nsid) -> anyhow::Result<u64> { 231 - let partition = self.partition.clone(); 296 + let partition = self.db.lock().await.partition.clone(); 232 297 let collection = collection.clone(); 233 - tokio::task::spawn_blocking(move || get_unrolled_asdf(&partition, collection)).await? 298 + tokio::task::spawn_blocking(move || get_unrolled_collection_seen(&partition, collection)) 299 + .await? 300 + } 301 + 302 + pub async fn get_top_collections(&self) -> anyhow::Result<HashMap<String, u64>> { 303 + let partition = self.db.lock().await.partition.clone(); 304 + tokio::task::spawn_blocking(move || get_unrolled_top_collections(&partition)).await? 234 305 } 235 306 236 307 pub async fn get_jetstream_endpoint(&self) -> anyhow::Result<Option<JetstreamEndpointValue>> { 237 - let partition = self.partition.clone(); 308 + let partition = self.db.lock().await.partition.clone(); 238 309 tokio::task::spawn_blocking(move || { 239 310 get_static::<JetstreamEndpointKey, JetstreamEndpointValue>(&partition) 240 311 }) ··· 242 313 } 243 314 244 315 async fn set_jetstream_endpoint(&self, endpoint: &str) -> anyhow::Result<()> { 245 - let partition = self.partition.clone(); 316 + let partition = self.db.lock().await.partition.clone(); 246 317 let endpoint = endpoint.to_string(); 247 318 tokio::task::spawn_blocking(move || { 248 319 insert_static::<JetstreamEndpointKey>(&partition, JetstreamEndpointValue(endpoint)) ··· 251 322 } 252 323 253 324 pub async fn get_jetstream_cursor(&self) -> anyhow::Result<Option<Cursor>> { 254 - let partition = self.partition.clone(); 325 + let partition = self.db.lock().await.partition.clone(); 255 326 tokio::task::spawn_blocking(move || { 256 327 get_static::<JetstreamCursorKey, JetstreamCursorValue>(&partition) 257 328 }) ··· 259 330 } 260 331 261 332 pub async fn get_mod_cursor(&self) -> anyhow::Result<Option<Cursor>> { 262 - let partition = self.partition.clone(); 333 + let partition = self.db.lock().await.partition.clone(); 263 334 tokio::task::spawn_blocking(move || get_static::<ModCursorKey, ModCursorValue>(&partition)) 264 335 .await? 265 336 } ··· 310 381 } 311 382 312 383 /// Get stats that haven't been rolled up yet 313 - fn get_unrolled_asdf(partition: &PartitionHandle, collection: Nsid) -> anyhow::Result<u64> { 384 + fn get_unrolled_collection_seen( 385 + partition: &PartitionHandle, 386 + collection: Nsid, 387 + ) -> anyhow::Result<u64> { 314 388 let range = 315 389 if let Some(cursor_value) = get_static::<RollupCursorKey, RollupCursorValue>(partition)? { 316 390 eprintln!("found existing cursor"); ··· 325 399 326 400 let mut scanned = 0; 327 401 let mut rolled = 0; 402 + 403 + ////// ITER 404 + 405 + { 406 + for pair in partition.range(range) { 407 + let (key_bytes, value_bytes) = pair?; 408 + let key = db_complete::<ByCursorSeenKey>(&key_bytes)?; 409 + let val = db_complete::<ByCursorSeenValue>(&value_bytes)?; 410 + 411 + if *key.collection() == collection { 412 + let SeenCounter(n) = val; 413 + collection_total += n; 414 + rolled += 1; 415 + } 416 + scanned += 1; 417 + } 418 + } 419 + 420 + eprintln!("scanned: {scanned}, rolled: {rolled}"); 421 + 422 + Ok(collection_total) 423 + } 424 + 425 + fn get_unrolled_top_collections( 426 + partition: &PartitionHandle, 427 + ) -> anyhow::Result<HashMap<String, u64>> { 428 + let range = 429 + if let Some(cursor_value) = get_static::<RollupCursorKey, RollupCursorValue>(partition)? { 430 + eprintln!("found existing cursor"); 431 + let key: ByCursorSeenKey = cursor_value.into(); 432 + key.range_from()? 433 + } else { 434 + eprintln!("cursor from start."); 435 + ByCursorSeenKey::full_range()? 436 + }; 437 + 438 + let mut res = HashMap::new(); 439 + let mut scanned = 0; 440 + 328 441 for pair in partition.range(range) { 329 442 let (key_bytes, value_bytes) = pair?; 330 443 let key = db_complete::<ByCursorSeenKey>(&key_bytes)?; 331 - let val = db_complete::<ByCursorSeenValue>(&value_bytes)?; 444 + let SeenCounter(n) = db_complete(&value_bytes)?; 445 + 446 + *res.entry(key.collection().to_string()).or_default() += n; 332 447 333 - if *key.collection() == collection { 334 - let SeenCounter(n) = val; 335 - collection_total += n; 336 - rolled += 1; 337 - } 338 448 scanned += 1; 339 449 } 340 450 341 - eprintln!("scanned: {scanned}, rolled: {rolled}"); 451 + eprintln!("scanned: {scanned} seen-counts."); 342 452 343 - Ok(collection_total) 453 + Ok(res) 344 454 } 345 455 346 456 impl DBWriter { ··· 352 462 if let Some(cursor) = last { 353 463 insert_batch_static::<JetstreamCursorKey>(&mut db_batch, &self.partition, cursor)?; 354 464 } 355 - Ok(db_batch.commit()?) 465 + log::info!("write: committing write batch..."); 466 + let r = db_batch.commit(); 467 + log::info!("write: commit result: {r:?}"); 468 + r?; 469 + Ok(()) 356 470 } 357 471 358 472 fn write_rw( ··· 367 481 368 482 let items_modified = match mod_value { 369 483 ModQueueItemValue::DeleteAccount(did) => { 484 + log::trace!("rw: batcher: delete account..."); 370 485 let (items, finished) = self.delete_account(db_batch, mod_cursor, did)?; 486 + log::trace!("rw: batcher: back from delete account (finished? {finished})"); 371 487 if finished { 372 488 // only remove the queued rw task if we have actually completed its account removal work 373 489 remove_batch::<ModQueueItemKey>(db_batch, &self.partition, mod_key)?; 490 + items + 1 491 + } else { 492 + items 374 493 } 375 - items 376 494 } 377 495 ModQueueItemValue::DeleteRecord(did, collection, rkey) => { 496 + log::trace!("rw: batcher: delete record..."); 497 + let items = self.delete_record(db_batch, mod_cursor, did, collection, rkey)?; 498 + log::trace!("rw: batcher: back from delete record"); 378 499 remove_batch::<ModQueueItemKey>(db_batch, &self.partition, mod_key)?; 379 - self.delete_record(db_batch, mod_cursor, did, collection, rkey)? 500 + items + 1 380 501 } 381 502 ModQueueItemValue::UpdateRecord(did, collection, rkey, record) => { 503 + let items = 504 + self.update_record(db_batch, mod_cursor, did, collection, rkey, record)?; 382 505 remove_batch::<ModQueueItemKey>(db_batch, &self.partition, mod_key)?; 383 - self.update_record(db_batch, mod_cursor, did, collection, rkey, record)? 506 + items + 1 384 507 } 385 508 }; 386 509 Ok(items_modified) ··· 420 543 rkey: RecordKey, 421 544 ) -> anyhow::Result<usize> { 422 545 let key_prefix_bytes = 423 - ByIdKey::record_prefix(did, collection.clone(), rkey).to_db_bytes()?; 546 + ByIdKey::record_prefix(did.clone(), collection.clone(), rkey.clone()).to_db_bytes()?; 547 + 548 + // put the cursor of the actual deletion event in to prevent prefix iter from touching newer docs 549 + let key_limit = 550 + ByIdKey::new(did, collection.clone(), rkey, cursor.clone()).to_db_bytes()?; 424 551 425 552 let mut items_removed = 0; 426 - for pair in self.partition.prefix(&key_prefix_bytes) { 427 - // find all (hopefully 1) 428 - let (key_bytes, _) = pair?; 429 - let key = db_complete::<ByIdKey>(&key_bytes)?; 430 - let found_cursor = key.cursor(); 431 - if found_cursor > cursor { 432 - // we are *only* allowed to delete records that came before the record delete event 433 - eprintln!("delete_record: found (and ignoring) newer version(s). key: {key:?}"); 434 - break; 435 - } 436 553 437 - // remove the by_id entry 438 - db_batch.remove(&self.partition, key_bytes); 439 - 440 - // remove its record sample 441 - let by_collection_key_bytes = 442 - ByCollectionKey::new(collection.clone(), found_cursor).to_db_bytes()?; 443 - db_batch.remove(&self.partition, by_collection_key_bytes); 554 + log::trace!("delete_record: iterate over up to current cursor..."); 444 555 445 - items_removed += 1; 446 - } 556 + ////////// ITER 447 557 448 - if items_removed > 1 { 449 - eprintln!("odd, removed {items_removed} records for one record removal:"); 450 - for (i, pair) in self.partition.prefix(&key_prefix_bytes).enumerate() { 558 + { 559 + for (i, pair) in self 560 + .partition 561 + .range(key_prefix_bytes..key_limit) 562 + .enumerate() 563 + { 564 + log::trace!("delete_record iter {i}: found"); 451 565 // find all (hopefully 1) 452 566 let (key_bytes, _) = pair?; 453 - let found_cursor = db_complete::<ByIdKey>(&key_bytes)?.cursor(); 567 + let key = db_complete::<ByIdKey>(&key_bytes)?; 568 + let found_cursor = key.cursor(); 454 569 if found_cursor > cursor { 455 - break; 570 + // we are *only* allowed to delete records that came before the record delete event 571 + // log::trace!("delete_record: found (and ignoring) newer version(s). key: {key:?}"); 572 + panic!("wtf, found newer version than cursor limit we tried to set."); 573 + // break; 456 574 } 457 575 458 - let key = db_complete::<ByIdKey>(&key_bytes)?; 459 - eprintln!(" {i}: key {key:?}"); 576 + // remove the by_id entry 577 + db_batch.remove(&self.partition, key_bytes); 578 + 579 + // remove its record sample 580 + let by_collection_key_bytes = 581 + ByCollectionKey::new(collection.clone(), found_cursor).to_db_bytes()?; 582 + db_batch.remove(&self.partition, by_collection_key_bytes); 583 + 584 + items_removed += 1; 460 585 } 461 586 } 587 + 588 + // if items_removed > 1 { 589 + // log::trace!("odd, removed {items_removed} records for one record removal:"); 590 + // for (i, pair) in self.partition.prefix(&key_prefix_bytes).enumerate() { 591 + // // find all (hopefully 1) 592 + // let (key_bytes, _) = pair?; 593 + // let found_cursor = db_complete::<ByIdKey>(&key_bytes)?.cursor(); 594 + // if found_cursor > cursor { 595 + // break; 596 + // } 597 + 598 + // let key = db_complete::<ByIdKey>(&key_bytes)?; 599 + // log::trace!(" {i}: key {key:?}"); 600 + // } 601 + // } 462 602 Ok(items_removed) 463 603 } 464 604 ··· 471 611 let key_prefix_bytes = ByIdKey::did_prefix(did).to_db_bytes()?; 472 612 473 613 let mut items_added = 0; 474 - for pair in self.partition.prefix(&key_prefix_bytes) { 475 - let (key_bytes, _) = pair?; 476 614 477 - let (_, collection, _rkey, found_cursor) = db_complete::<ByIdKey>(&key_bytes)?.into(); 478 - if found_cursor > cursor { 479 - eprintln!( 480 - "delete account: found (and ignoring) newer records than the delete event??" 481 - ); 482 - continue; 483 - } 615 + ////////// ITER 484 616 485 - // remove the by_id entry 486 - db_batch.remove(&self.partition, key_bytes); 617 + { 618 + for pair in self.partition.prefix(&key_prefix_bytes) { 619 + let (key_bytes, _) = pair?; 487 620 488 - // remove its record sample 489 - let by_collection_key_bytes = 490 - ByCollectionKey::new(collection, found_cursor).to_db_bytes()?; 491 - db_batch.remove(&self.partition, by_collection_key_bytes); 621 + let (_, collection, _rkey, found_cursor) = 622 + db_complete::<ByIdKey>(&key_bytes)?.into(); 623 + if found_cursor > cursor { 624 + log::trace!( 625 + "delete account: found (and ignoring) newer records than the delete event??" 626 + ); 627 + continue; 628 + } 492 629 493 - items_added += 1; 494 - if items_added >= MAX_BATCHED_RW_ITEMS { 495 - return Ok((items_added, false)); // there might be more records but we've done enough for this batch 630 + // remove the by_id entry 631 + db_batch.remove(&self.partition, key_bytes); 632 + 633 + // remove its record sample 634 + let by_collection_key_bytes = 635 + ByCollectionKey::new(collection, found_cursor).to_db_bytes()?; 636 + db_batch.remove(&self.partition, by_collection_key_bytes); 637 + 638 + items_added += 1; 639 + if items_added >= MAX_BATCHED_RW_ITEMS { 640 + return Ok((items_added, false)); // there might be more records but we've done enough for this batch 641 + } 496 642 } 497 643 } 498 644