Major refactor to handler traits
Added `IntoGiteratedHandler`, which is the new trait for handler functions. This allows us to finally get rid of the Object and ObjectOperation bounds that resulted in hacks around the newer features of the unified stack. Squashed commit of the following: commit 62e1ecf76ee31cda0bab4602d9d00fa0dc2f9158 Author: Amber <[email protected]> Date: Wed Oct 11 09:31:11 2023 -0500 Update commit dfd2d1b0b5d81ee3bc48f0321c6aceaa677e3b8b Author: Amber <[email protected]> Date: Wed Oct 11 09:31:07 2023 -0500 Major refactor to handler traits Added `IntoGiteratedHandler`, which is the new trait for handler functions. This allows us to finally get rid of the Object and ObjectOperation bounds that resulted in hacks around the newer features of the unified stack. Removed dead and legacy code. I think... commit 57b4b398eff32e69f2f4b9700e42a1277a4d1055 Author: Amber <[email protected]> Date: Sun Oct 1 23:05:10 2023 -0500 New handler trait for giterated stack Refactor the old handler trait so it is more generic and can be used for specific kinds of handlers
parent: tbd commit: 90c4780
Showing 30 changed files with 3011 insertions and 2362 deletions
Cargo.lock
@@ -115,6 +115,15 @@ dependencies = [ | ||
115 | 115 | ] |
116 | 116 | |
117 | 117 | [[package]] |
118 | name = "async-lock" | |
119 | version = "2.8.0" | |
120 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
121 | checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" | |
122 | dependencies = [ | |
123 | "event-listener", | |
124 | ] | |
125 | ||
126 | [[package]] | |
118 | 127 | name = "async-trait" |
119 | 128 | version = "0.1.73" |
120 | 129 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -122,7 +131,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" | ||
122 | 131 | dependencies = [ |
123 | 132 | "proc-macro2", |
124 | 133 | "quote", |
125 | "syn 2.0.37", | |
134 | "syn 2.0.38", | |
126 | 135 | ] |
127 | 136 | |
128 | 137 | [[package]] |
@@ -222,10 +231,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||
222 | 231 | checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" |
223 | 232 | |
224 | 233 | [[package]] |
234 | name = "bytecount" | |
235 | version = "0.6.4" | |
236 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
237 | checksum = "ad152d03a2c813c80bb94fedbf3a3f02b28f793e39e7c214c8a0bcc196343de7" | |
238 | ||
239 | [[package]] | |
225 | 240 | name = "byteorder" |
226 | version = "1.4.3" | |
241 | version = "1.5.0" | |
227 | 242 | source = "registry+https://github.com/rust-lang/crates.io-index" |
228 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" | |
243 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" | |
229 | 244 | |
230 | 245 | [[package]] |
231 | 246 | name = "bytes" |
@@ -234,6 +249,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||
234 | 249 | checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" |
235 | 250 | |
236 | 251 | [[package]] |
252 | name = "camino" | |
253 | version = "1.1.6" | |
254 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
255 | checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" | |
256 | dependencies = [ | |
257 | "serde", | |
258 | ] | |
259 | ||
260 | [[package]] | |
261 | name = "cargo-platform" | |
262 | version = "0.1.4" | |
263 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
264 | checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" | |
265 | dependencies = [ | |
266 | "serde", | |
267 | ] | |
268 | ||
269 | [[package]] | |
270 | name = "cargo_metadata" | |
271 | version = "0.14.2" | |
272 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
273 | checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" | |
274 | dependencies = [ | |
275 | "camino", | |
276 | "cargo-platform", | |
277 | "semver", | |
278 | "serde", | |
279 | "serde_json", | |
280 | ] | |
281 | ||
282 | [[package]] | |
237 | 283 | name = "cc" |
238 | 284 | version = "1.0.83" |
239 | 285 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -348,6 +394,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||
348 | 394 | checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" |
349 | 395 | |
350 | 396 | [[package]] |
397 | name = "crossbeam-channel" | |
398 | version = "0.5.8" | |
399 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
400 | checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" | |
401 | dependencies = [ | |
402 | "cfg-if", | |
403 | "crossbeam-utils", | |
404 | ] | |
405 | ||
406 | [[package]] | |
407 | name = "crossbeam-epoch" | |
408 | version = "0.9.15" | |
409 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
410 | checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" | |
411 | dependencies = [ | |
412 | "autocfg", | |
413 | "cfg-if", | |
414 | "crossbeam-utils", | |
415 | "memoffset", | |
416 | "scopeguard", | |
417 | ] | |
418 | ||
419 | [[package]] | |
351 | 420 | name = "crossbeam-queue" |
352 | 421 | version = "0.3.8" |
353 | 422 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -484,23 +553,21 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" | ||
484 | 553 | |
485 | 554 | [[package]] |
486 | 555 | name = "errno" |
487 | version = "0.3.3" | |
556 | version = "0.3.5" | |
488 | 557 | source = "registry+https://github.com/rust-lang/crates.io-index" |
489 | checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" | |
558 | checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" | |
490 | 559 | dependencies = [ |
491 | "errno-dragonfly", | |
492 | 560 | "libc", |
493 | 561 | "windows-sys", |
494 | 562 | ] |
495 | 563 | |
496 | 564 | [[package]] |
497 | name = "errno-dragonfly" | |
498 | version = "0.1.2" | |
565 | name = "error-chain" | |
566 | version = "0.12.4" | |
499 | 567 | source = "registry+https://github.com/rust-lang/crates.io-index" |
500 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" | |
568 | checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" | |
501 | 569 | dependencies = [ |
502 | "cc", | |
503 | "libc", | |
570 | "version_check", | |
504 | 571 | ] |
505 | 572 | |
506 | 573 | [[package]] |
@@ -635,7 +702,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" | ||
635 | 702 | dependencies = [ |
636 | 703 | "proc-macro2", |
637 | 704 | "quote", |
638 | "syn 2.0.37", | |
705 | "syn 2.0.38", | |
639 | 706 | ] |
640 | 707 | |
641 | 708 | [[package]] |
@@ -745,6 +812,24 @@ dependencies = [ | ||
745 | 812 | ] |
746 | 813 | |
747 | 814 | [[package]] |
815 | name = "giterated-cache" | |
816 | version = "0.1.0" | |
817 | dependencies = [ | |
818 | "anyhow", | |
819 | "async-trait", | |
820 | "bincode", | |
821 | "futures-util", | |
822 | "giterated-models", | |
823 | "giterated-stack", | |
824 | "moka", | |
825 | "serde", | |
826 | "serde_json", | |
827 | "thiserror", | |
828 | "tokio", | |
829 | "tracing", | |
830 | ] | |
831 | ||
832 | [[package]] | |
748 | 833 | name = "giterated-daemon" |
749 | 834 | version = "0.1.0" |
750 | 835 | dependencies = [ |
@@ -821,6 +906,12 @@ dependencies = [ | ||
821 | 906 | ] |
822 | 907 | |
823 | 908 | [[package]] |
909 | name = "glob" | |
910 | version = "0.3.1" | |
911 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
912 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" | |
913 | ||
914 | [[package]] | |
824 | 915 | name = "h2" |
825 | 916 | version = "0.3.21" |
826 | 917 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -850,9 +941,9 @@ dependencies = [ | ||
850 | 941 | |
851 | 942 | [[package]] |
852 | 943 | name = "hashbrown" |
853 | version = "0.14.0" | |
944 | version = "0.14.1" | |
854 | 945 | source = "registry+https://github.com/rust-lang/crates.io-index" |
855 | checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" | |
946 | checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" | |
856 | 947 | dependencies = [ |
857 | 948 | "ahash 0.8.3", |
858 | 949 | "allocator-api2", |
@@ -864,7 +955,7 @@ version = "0.8.4" | ||
864 | 955 | source = "registry+https://github.com/rust-lang/crates.io-index" |
865 | 956 | checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" |
866 | 957 | dependencies = [ |
867 | "hashbrown 0.14.0", | |
958 | "hashbrown 0.14.1", | |
868 | 959 | ] |
869 | 960 | |
870 | 961 | [[package]] |
@@ -1051,12 +1142,12 @@ dependencies = [ | ||
1051 | 1142 | |
1052 | 1143 | [[package]] |
1053 | 1144 | name = "indexmap" |
1054 | version = "2.0.0" | |
1145 | version = "2.0.2" | |
1055 | 1146 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1056 | checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" | |
1147 | checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" | |
1057 | 1148 | dependencies = [ |
1058 | 1149 | "equivalent", |
1059 | "hashbrown 0.14.0", | |
1150 | "hashbrown 0.14.1", | |
1060 | 1151 | ] |
1061 | 1152 | |
1062 | 1153 | [[package]] |
@@ -1091,9 +1182,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" | ||
1091 | 1182 | |
1092 | 1183 | [[package]] |
1093 | 1184 | name = "jobserver" |
1094 | version = "0.1.26" | |
1185 | version = "0.1.27" | |
1095 | 1186 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1096 | checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" | |
1187 | checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" | |
1097 | 1188 | dependencies = [ |
1098 | 1189 | "libc", |
1099 | 1190 | ] |
@@ -1132,9 +1223,9 @@ dependencies = [ | ||
1132 | 1223 | |
1133 | 1224 | [[package]] |
1134 | 1225 | name = "libc" |
1135 | version = "0.2.148" | |
1226 | version = "0.2.149" | |
1136 | 1227 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1137 | checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" | |
1228 | checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" | |
1138 | 1229 | |
1139 | 1230 | [[package]] |
1140 | 1231 | name = "libgit2-sys" |
@@ -1152,9 +1243,9 @@ dependencies = [ | ||
1152 | 1243 | |
1153 | 1244 | [[package]] |
1154 | 1245 | name = "libm" |
1155 | version = "0.2.7" | |
1246 | version = "0.2.8" | |
1156 | 1247 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1157 | checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" | |
1248 | checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" | |
1158 | 1249 | |
1159 | 1250 | [[package]] |
1160 | 1251 | name = "libsqlite3-sys" |
@@ -1195,9 +1286,9 @@ dependencies = [ | ||
1195 | 1286 | |
1196 | 1287 | [[package]] |
1197 | 1288 | name = "linux-raw-sys" |
1198 | version = "0.4.7" | |
1289 | version = "0.4.10" | |
1199 | 1290 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1200 | checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" | |
1291 | checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" | |
1201 | 1292 | |
1202 | 1293 | [[package]] |
1203 | 1294 | name = "lock_api" |
@@ -1216,6 +1307,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1216 | 1307 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" |
1217 | 1308 | |
1218 | 1309 | [[package]] |
1310 | name = "mach2" | |
1311 | version = "0.4.1" | |
1312 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1313 | checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8" | |
1314 | dependencies = [ | |
1315 | "libc", | |
1316 | ] | |
1317 | ||
1318 | [[package]] | |
1219 | 1319 | name = "md-5" |
1220 | 1320 | version = "0.10.6" |
1221 | 1321 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1227,9 +1327,18 @@ dependencies = [ | ||
1227 | 1327 | |
1228 | 1328 | [[package]] |
1229 | 1329 | name = "memchr" |
1230 | version = "2.6.3" | |
1330 | version = "2.6.4" | |
1231 | 1331 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1232 | checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" | |
1332 | checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" | |
1333 | ||
1334 | [[package]] | |
1335 | name = "memoffset" | |
1336 | version = "0.9.0" | |
1337 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1338 | checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" | |
1339 | dependencies = [ | |
1340 | "autocfg", | |
1341 | ] | |
1233 | 1342 | |
1234 | 1343 | [[package]] |
1235 | 1344 | name = "mime" |
@@ -1264,6 +1373,30 @@ dependencies = [ | ||
1264 | 1373 | ] |
1265 | 1374 | |
1266 | 1375 | [[package]] |
1376 | name = "moka" | |
1377 | version = "0.12.1" | |
1378 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1379 | checksum = "d8017ec3548ffe7d4cef7ac0e12b044c01164a74c0f3119420faeaf13490ad8b" | |
1380 | dependencies = [ | |
1381 | "async-lock", | |
1382 | "async-trait", | |
1383 | "crossbeam-channel", | |
1384 | "crossbeam-epoch", | |
1385 | "crossbeam-utils", | |
1386 | "futures-util", | |
1387 | "once_cell", | |
1388 | "parking_lot", | |
1389 | "quanta", | |
1390 | "rustc_version", | |
1391 | "skeptic", | |
1392 | "smallvec", | |
1393 | "tagptr", | |
1394 | "thiserror", | |
1395 | "triomphe", | |
1396 | "uuid", | |
1397 | ] | |
1398 | ||
1399 | [[package]] | |
1267 | 1400 | name = "native-tls" |
1268 | 1401 | version = "0.2.11" |
1269 | 1402 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1352,9 +1485,9 @@ dependencies = [ | ||
1352 | 1485 | |
1353 | 1486 | [[package]] |
1354 | 1487 | name = "num-traits" |
1355 | version = "0.2.16" | |
1488 | version = "0.2.17" | |
1356 | 1489 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1357 | checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" | |
1490 | checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" | |
1358 | 1491 | dependencies = [ |
1359 | 1492 | "autocfg", |
1360 | 1493 | "libm", |
@@ -1414,7 +1547,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" | ||
1414 | 1547 | dependencies = [ |
1415 | 1548 | "proc-macro2", |
1416 | 1549 | "quote", |
1417 | "syn 2.0.37", | |
1550 | "syn 2.0.38", | |
1418 | 1551 | ] |
1419 | 1552 | |
1420 | 1553 | [[package]] |
@@ -1570,14 +1703,41 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" | ||
1570 | 1703 | |
1571 | 1704 | [[package]] |
1572 | 1705 | name = "proc-macro2" |
1573 | version = "1.0.67" | |
1706 | version = "1.0.69" | |
1574 | 1707 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1575 | checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" | |
1708 | checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" | |
1576 | 1709 | dependencies = [ |
1577 | 1710 | "unicode-ident", |
1578 | 1711 | ] |
1579 | 1712 | |
1580 | 1713 | [[package]] |
1714 | name = "pulldown-cmark" | |
1715 | version = "0.9.3" | |
1716 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1717 | checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" | |
1718 | dependencies = [ | |
1719 | "bitflags 1.3.2", | |
1720 | "memchr", | |
1721 | "unicase", | |
1722 | ] | |
1723 | ||
1724 | [[package]] | |
1725 | name = "quanta" | |
1726 | version = "0.11.1" | |
1727 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1728 | checksum = "a17e662a7a8291a865152364c20c7abc5e60486ab2001e8ec10b24862de0b9ab" | |
1729 | dependencies = [ | |
1730 | "crossbeam-utils", | |
1731 | "libc", | |
1732 | "mach2", | |
1733 | "once_cell", | |
1734 | "raw-cpuid", | |
1735 | "wasi", | |
1736 | "web-sys", | |
1737 | "winapi", | |
1738 | ] | |
1739 | ||
1740 | [[package]] | |
1581 | 1741 | name = "quote" |
1582 | 1742 | version = "1.0.33" |
1583 | 1743 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1617,6 +1777,15 @@ dependencies = [ | ||
1617 | 1777 | ] |
1618 | 1778 | |
1619 | 1779 | [[package]] |
1780 | name = "raw-cpuid" | |
1781 | version = "10.7.0" | |
1782 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1783 | checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" | |
1784 | dependencies = [ | |
1785 | "bitflags 1.3.2", | |
1786 | ] | |
1787 | ||
1788 | [[package]] | |
1620 | 1789 | name = "redox_syscall" |
1621 | 1790 | version = "0.3.5" |
1622 | 1791 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1627,9 +1796,9 @@ dependencies = [ | ||
1627 | 1796 | |
1628 | 1797 | [[package]] |
1629 | 1798 | name = "reqwest" |
1630 | version = "0.11.20" | |
1799 | version = "0.11.22" | |
1631 | 1800 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1632 | checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" | |
1801 | checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" | |
1633 | 1802 | dependencies = [ |
1634 | 1803 | "base64 0.21.4", |
1635 | 1804 | "bytes", |
@@ -1655,6 +1824,7 @@ dependencies = [ | ||
1655 | 1824 | "serde", |
1656 | 1825 | "serde_json", |
1657 | 1826 | "serde_urlencoded", |
1827 | "system-configuration", | |
1658 | 1828 | "tokio", |
1659 | 1829 | "tokio-native-tls", |
1660 | 1830 | "tokio-rustls", |
@@ -1718,10 +1888,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1718 | 1888 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" |
1719 | 1889 | |
1720 | 1890 | [[package]] |
1891 | name = "rustc_version" | |
1892 | version = "0.4.0" | |
1893 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1894 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" | |
1895 | dependencies = [ | |
1896 | "semver", | |
1897 | ] | |
1898 | ||
1899 | [[package]] | |
1721 | 1900 | name = "rustix" |
1722 | version = "0.38.14" | |
1901 | version = "0.38.18" | |
1723 | 1902 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1724 | checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f" | |
1903 | checksum = "5a74ee2d7c2581cd139b42447d7d9389b889bdaad3a73f1ebb16f2a3237bb19c" | |
1725 | 1904 | dependencies = [ |
1726 | 1905 | "bitflags 2.4.0", |
1727 | 1906 | "errno", |
@@ -1780,6 +1959,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1780 | 1959 | checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" |
1781 | 1960 | |
1782 | 1961 | [[package]] |
1962 | name = "same-file" | |
1963 | version = "1.0.6" | |
1964 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
1965 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" | |
1966 | dependencies = [ | |
1967 | "winapi-util", | |
1968 | ] | |
1969 | ||
1970 | [[package]] | |
1783 | 1971 | name = "schannel" |
1784 | 1972 | version = "0.1.22" |
1785 | 1973 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -1839,9 +2027,9 @@ dependencies = [ | ||
1839 | 2027 | |
1840 | 2028 | [[package]] |
1841 | 2029 | name = "semver" |
1842 | version = "1.0.19" | |
2030 | version = "1.0.20" | |
1843 | 2031 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1844 | checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" | |
2032 | checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" | |
1845 | 2033 | dependencies = [ |
1846 | 2034 | "serde", |
1847 | 2035 | ] |
@@ -1863,7 +2051,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" | ||
1863 | 2051 | dependencies = [ |
1864 | 2052 | "proc-macro2", |
1865 | 2053 | "quote", |
1866 | "syn 2.0.37", | |
2054 | "syn 2.0.38", | |
1867 | 2055 | ] |
1868 | 2056 | |
1869 | 2057 | [[package]] |
@@ -1922,9 +2110,9 @@ dependencies = [ | ||
1922 | 2110 | |
1923 | 2111 | [[package]] |
1924 | 2112 | name = "sharded-slab" |
1925 | version = "0.1.4" | |
2113 | version = "0.1.7" | |
1926 | 2114 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1927 | checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" | |
2115 | checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" | |
1928 | 2116 | dependencies = [ |
1929 | 2117 | "lazy_static", |
1930 | 2118 | ] |
@@ -1961,6 +2149,21 @@ dependencies = [ | ||
1961 | 2149 | ] |
1962 | 2150 | |
1963 | 2151 | [[package]] |
2152 | name = "skeptic" | |
2153 | version = "0.13.7" | |
2154 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
2155 | checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" | |
2156 | dependencies = [ | |
2157 | "bytecount", | |
2158 | "cargo_metadata", | |
2159 | "error-chain", | |
2160 | "glob", | |
2161 | "pulldown-cmark", | |
2162 | "tempfile", | |
2163 | "walkdir", | |
2164 | ] | |
2165 | ||
2166 | [[package]] | |
1964 | 2167 | name = "slab" |
1965 | 2168 | version = "0.4.9" |
1966 | 2169 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -2067,7 +2270,7 @@ dependencies = [ | ||
2067 | 2270 | "futures-util", |
2068 | 2271 | "hashlink", |
2069 | 2272 | "hex", |
2070 | "indexmap 2.0.0", | |
2273 | "indexmap 2.0.2", | |
2071 | 2274 | "log", |
2072 | 2275 | "memchr", |
2073 | 2276 | "native-tls", |
@@ -2261,9 +2464,9 @@ dependencies = [ | ||
2261 | 2464 | |
2262 | 2465 | [[package]] |
2263 | 2466 | name = "syn" |
2264 | version = "2.0.37" | |
2467 | version = "2.0.38" | |
2265 | 2468 | source = "registry+https://github.com/rust-lang/crates.io-index" |
2266 | checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" | |
2469 | checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" | |
2267 | 2470 | dependencies = [ |
2268 | 2471 | "proc-macro2", |
2269 | 2472 | "quote", |
@@ -2271,6 +2474,33 @@ dependencies = [ | ||
2271 | 2474 | ] |
2272 | 2475 | |
2273 | 2476 | [[package]] |
2477 | name = "system-configuration" | |
2478 | version = "0.5.1" | |
2479 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
2480 | checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" | |
2481 | dependencies = [ | |
2482 | "bitflags 1.3.2", | |
2483 | "core-foundation", | |
2484 | "system-configuration-sys", | |
2485 | ] | |
2486 | ||
2487 | [[package]] | |
2488 | name = "system-configuration-sys" | |
2489 | version = "0.5.0" | |
2490 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
2491 | checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" | |
2492 | dependencies = [ | |
2493 | "core-foundation-sys", | |
2494 | "libc", | |
2495 | ] | |
2496 | ||
2497 | [[package]] | |
2498 | name = "tagptr" | |
2499 | version = "0.2.0" | |
2500 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
2501 | checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" | |
2502 | ||
2503 | [[package]] | |
2274 | 2504 | name = "tempfile" |
2275 | 2505 | version = "3.8.0" |
2276 | 2506 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -2300,7 +2530,7 @@ checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" | ||
2300 | 2530 | dependencies = [ |
2301 | 2531 | "proc-macro2", |
2302 | 2532 | "quote", |
2303 | "syn 2.0.37", | |
2533 | "syn 2.0.38", | |
2304 | 2534 | ] |
2305 | 2535 | |
2306 | 2536 | [[package]] |
@@ -2358,9 +2588,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" | ||
2358 | 2588 | |
2359 | 2589 | [[package]] |
2360 | 2590 | name = "tokio" |
2361 | version = "1.32.0" | |
2591 | version = "1.33.0" | |
2362 | 2592 | source = "registry+https://github.com/rust-lang/crates.io-index" |
2363 | checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" | |
2593 | checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" | |
2364 | 2594 | dependencies = [ |
2365 | 2595 | "backtrace", |
2366 | 2596 | "bytes", |
@@ -2383,7 +2613,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" | ||
2383 | 2613 | dependencies = [ |
2384 | 2614 | "proc-macro2", |
2385 | 2615 | "quote", |
2386 | "syn 2.0.37", | |
2616 | "syn 2.0.38", | |
2387 | 2617 | ] |
2388 | 2618 | |
2389 | 2619 | [[package]] |
@@ -2475,7 +2705,7 @@ version = "0.19.15" | ||
2475 | 2705 | source = "registry+https://github.com/rust-lang/crates.io-index" |
2476 | 2706 | checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" |
2477 | 2707 | dependencies = [ |
2478 | "indexmap 2.0.0", | |
2708 | "indexmap 2.0.2", | |
2479 | 2709 | "serde", |
2480 | 2710 | "serde_spanned", |
2481 | 2711 | "toml_datetime", |
@@ -2509,7 +2739,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" | ||
2509 | 2739 | dependencies = [ |
2510 | 2740 | "proc-macro2", |
2511 | 2741 | "quote", |
2512 | "syn 2.0.37", | |
2742 | "syn 2.0.38", | |
2513 | 2743 | ] |
2514 | 2744 | |
2515 | 2745 | [[package]] |
@@ -2558,6 +2788,12 @@ dependencies = [ | ||
2558 | 2788 | ] |
2559 | 2789 | |
2560 | 2790 | [[package]] |
2791 | name = "triomphe" | |
2792 | version = "0.1.9" | |
2793 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
2794 | checksum = "0eee8098afad3fb0c54a9007aab6804558410503ad676d4633f9c2559a00ac0f" | |
2795 | ||
2796 | [[package]] | |
2561 | 2797 | name = "try-lock" |
2562 | 2798 | version = "0.2.4" |
2563 | 2799 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -2590,6 +2826,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||
2590 | 2826 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" |
2591 | 2827 | |
2592 | 2828 | [[package]] |
2829 | name = "unicase" | |
2830 | version = "2.7.0" | |
2831 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
2832 | checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" | |
2833 | dependencies = [ | |
2834 | "version_check", | |
2835 | ] | |
2836 | ||
2837 | [[package]] | |
2593 | 2838 | name = "unicode-bidi" |
2594 | 2839 | version = "0.3.13" |
2595 | 2840 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -2657,6 +2902,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||
2657 | 2902 | checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" |
2658 | 2903 | |
2659 | 2904 | [[package]] |
2905 | name = "uuid" | |
2906 | version = "1.4.1" | |
2907 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
2908 | checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" | |
2909 | dependencies = [ | |
2910 | "getrandom", | |
2911 | ] | |
2912 | ||
2913 | [[package]] | |
2660 | 2914 | name = "valuable" |
2661 | 2915 | version = "0.1.0" |
2662 | 2916 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -2675,6 +2929,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||
2675 | 2929 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" |
2676 | 2930 | |
2677 | 2931 | [[package]] |
2932 | name = "walkdir" | |
2933 | version = "2.4.0" | |
2934 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
2935 | checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" | |
2936 | dependencies = [ | |
2937 | "same-file", | |
2938 | "winapi-util", | |
2939 | ] | |
2940 | ||
2941 | [[package]] | |
2678 | 2942 | name = "want" |
2679 | 2943 | version = "0.3.1" |
2680 | 2944 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -2710,7 +2974,7 @@ dependencies = [ | ||
2710 | 2974 | "once_cell", |
2711 | 2975 | "proc-macro2", |
2712 | 2976 | "quote", |
2713 | "syn 2.0.37", | |
2977 | "syn 2.0.38", | |
2714 | 2978 | "wasm-bindgen-shared", |
2715 | 2979 | ] |
2716 | 2980 | |
@@ -2744,7 +3008,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" | ||
2744 | 3008 | dependencies = [ |
2745 | 3009 | "proc-macro2", |
2746 | 3010 | "quote", |
2747 | "syn 2.0.37", | |
3011 | "syn 2.0.38", | |
2748 | 3012 | "wasm-bindgen-backend", |
2749 | 3013 | "wasm-bindgen-shared", |
2750 | 3014 | ] |
@@ -2794,6 +3058,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||
2794 | 3058 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" |
2795 | 3059 | |
2796 | 3060 | [[package]] |
3061 | name = "winapi-util" | |
3062 | version = "0.1.6" | |
3063 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
3064 | checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" | |
3065 | dependencies = [ | |
3066 | "winapi", | |
3067 | ] | |
3068 | ||
3069 | [[package]] | |
2797 | 3070 | name = "winapi-x86_64-pc-windows-gnu" |
2798 | 3071 | version = "0.4.0" |
2799 | 3072 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -2876,9 +3149,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" | ||
2876 | 3149 | |
2877 | 3150 | [[package]] |
2878 | 3151 | name = "winnow" |
2879 | version = "0.5.15" | |
3152 | version = "0.5.16" | |
2880 | 3153 | source = "registry+https://github.com/rust-lang/crates.io-index" |
2881 | checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" | |
3154 | checksum = "037711d82167854aff2018dfd193aa0fef5370f456732f0d5a0c59b0f1b4b907" | |
2882 | 3155 | dependencies = [ |
2883 | 3156 | "memchr", |
2884 | 3157 | ] |
Cargo.toml
@@ -2,5 +2,6 @@ | ||
2 | 2 | members = [ |
3 | 3 | "giterated-daemon", |
4 | 4 | "giterated-models", |
5 | "giterated-stack" | |
5 | "giterated-stack", | |
6 | "giterated-cache" | |
6 | 7 | ] |
6 | 7 | \ No newline at end of file |
giterated-cache/Cargo.toml
@@ -0,0 +1,20 @@ | ||
1 | [package] | |
2 | name = "giterated-cache" | |
3 | version = "0.1.0" | |
4 | edition = "2021" | |
5 | ||
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
7 | ||
8 | [dependencies] | |
9 | giterated-models = { path = "../giterated-models" } | |
10 | async-trait = "0.1" | |
11 | serde = { version = "1.0.188", features = [ "derive" ]} | |
12 | serde_json = "1.0" | |
13 | bincode = "1.3" | |
14 | futures-util = "0.3" | |
15 | tracing = "0.1" | |
16 | tokio = { version = "1.32", features = [ "full" ] } | |
17 | anyhow = "1" | |
18 | thiserror = "1" | |
19 | giterated-stack = { path = "../giterated-stack" } | |
20 | moka = { version = "0.12.0", features = ["future"] } |
giterated-cache/src/cache_get.rs
@@ -0,0 +1,16 @@ | ||
1 | // use std::sync::Arc; | |
2 | ||
3 | // use giterated_models::error::OperationError; | |
4 | // use giterated_stack::GiteratedStack; | |
5 | // use serde_json::Value; | |
6 | ||
7 | // use crate::{cache_update::AnyObject, CacheSubstack}; | |
8 | ||
9 | // pub async fn try_value_get( | |
10 | // object: AnyObject<'_>, | |
11 | // value_name: &str, | |
12 | // cache: CacheSubstack, | |
13 | // stack: Arc<GiteratedStack>, | |
14 | // ) -> Result<Value, OperationError<anyhow::Error>> { | |
15 | // todo!() | |
16 | // } |
giterated-cache/src/cache_update.rs
@@ -0,0 +1,348 @@ | ||
1 | // use std::{any::Any, pin::Pin, process::Output, sync::Arc}; | |
2 | ||
3 | // use futures_util::{future::LocalBoxFuture, Future, FutureExt}; | |
4 | // use giterated_models::{ | |
5 | // error::{ExtractorError, OperationError, RepositoryError}, | |
6 | // object::GiteratedObject, | |
7 | // operation::GiteratedOperation, | |
8 | // repository::{Repository, RepositoryBranch, RepositoryBranchesRequest}, | |
9 | // settings::SetSetting, | |
10 | // user::{DisplayName, User}, | |
11 | // value::{GetValue, GiteratedObjectValue}, | |
12 | // }; | |
13 | // use giterated_stack::{ | |
14 | // AuthorizedUser, FromOperationState, GiteratedStack, MissingValue, StackOperationState, | |
15 | // }; | |
16 | ||
17 | // use crate::CacheSubstack; | |
18 | ||
19 | // async fn value_update( | |
20 | // object: AnyObject<'_>, | |
21 | // value: AnyValue<'_>, | |
22 | // cache: CacheSubstack, | |
23 | // stack: Arc<GiteratedStack>, | |
24 | // ) -> Result<(), anyhow::Error> { | |
25 | // todo!() | |
26 | // } | |
27 | ||
28 | // pub struct AnyObject<'o>(&'o (dyn Any + Send + Sync)); | |
29 | ||
30 | // pub struct AnyValue<'v>(&'v (dyn Any + Send + Sync)); | |
31 | ||
32 | // #[async_trait::async_trait(?Send)] | |
33 | // pub trait GiteratedHandler<RequiredParameters, AdditionalParameters, State, OperationState, Output> | |
34 | // { | |
35 | // async fn handle( | |
36 | // &self, | |
37 | // parameters: RequiredParameters, | |
38 | // additional_parameters: AdditionalParameters, | |
39 | // state: Arc<State>, | |
40 | // operation_state: &OperationState, | |
41 | // ) -> Output; | |
42 | // } | |
43 | ||
44 | // #[async_trait::async_trait(?Send)] | |
45 | // impl<R1, S, O, Output, F, Fut> GiteratedHandler<(R1,), (), S, O, Output> for F | |
46 | // where | |
47 | // F: FnMut(R1, S, &O) -> Fut, | |
48 | // Fut: Future<Output = Output>, | |
49 | // S: 'static, | |
50 | // R1: 'static, | |
51 | // { | |
52 | // async fn handle( | |
53 | // &self, | |
54 | // parameters: (R1,), | |
55 | // additional_parameters: (), | |
56 | // state: Arc<S>, | |
57 | // operation_state: &O, | |
58 | // ) -> Output { | |
59 | // todo!() | |
60 | // } | |
61 | // } | |
62 | ||
63 | // #[async_trait::async_trait(?Send)] | |
64 | // impl<R1, A1, S, O, Output, F, Fut> GiteratedHandler<(R1,), (A1,), S, O, Output> for F | |
65 | // where | |
66 | // F: FnMut(R1, S, &O, A1) -> Fut, | |
67 | // Fut: Future<Output = Output>, | |
68 | // S: 'static, | |
69 | // R1: 'static, | |
70 | // A1: 'static + HandlerResolvable<(R1,), O, A1>, | |
71 | // { | |
72 | // async fn handle( | |
73 | // &self, | |
74 | // parameters: (R1,), | |
75 | // additional_parameters: (A1,), | |
76 | // state: Arc<S>, | |
77 | // operation_state: &O, | |
78 | // ) -> Output { | |
79 | // todo!() | |
80 | // } | |
81 | // } | |
82 | ||
83 | // #[async_trait::async_trait(?Send)] | |
84 | // impl<R1, A1, A2, S, O, Output, F, Fut> GiteratedHandler<(R1,), (A1, A2), S, O, Output> for F | |
85 | // where | |
86 | // F: FnMut(R1, S, &O, A1, A2) -> Fut, | |
87 | // Fut: Future<Output = Output>, | |
88 | // S: 'static, | |
89 | // R1: 'static, | |
90 | // A1: 'static + HandlerResolvable<(R1,), O, A1>, | |
91 | // A2: 'static + HandlerResolvable<(R1,), O, A2>, | |
92 | // { | |
93 | // async fn handle( | |
94 | // &self, | |
95 | // parameters: (R1,), | |
96 | // additional_parameters: (A1, A2), | |
97 | // state: Arc<S>, | |
98 | // operation_state: &O, | |
99 | // ) -> Output { | |
100 | // todo!() | |
101 | // } | |
102 | // } | |
103 | ||
104 | // #[async_trait::async_trait(?Send)] | |
105 | // impl<R1, A1, A2, A3, S, O, Output, F, Fut> GiteratedHandler<(R1,), (A1, A2, A3), S, O, Output> for F | |
106 | // where | |
107 | // F: FnMut(R1, S, &O, A1, A2, A3) -> Fut, | |
108 | // Fut: Future<Output = Output>, | |
109 | // S: 'static, | |
110 | // R1: 'static, | |
111 | // A1: 'static + HandlerResolvable<(R1,), O, A1>, | |
112 | // A2: 'static + HandlerResolvable<(R1,), O, A2>, | |
113 | // A3: 'static + HandlerResolvable<(R1,), O, A3>, | |
114 | // { | |
115 | // async fn handle( | |
116 | // &self, | |
117 | // parameters: (R1,), | |
118 | // additional_parameters: (A1, A2, A3), | |
119 | // state: Arc<S>, | |
120 | // operation_state: &O, | |
121 | // ) -> Output { | |
122 | // todo!() | |
123 | // } | |
124 | // } | |
125 | ||
126 | // #[async_trait::async_trait(?Send)] | |
127 | // impl<R1, R2, S, O, Output, F, Fut> GiteratedHandler<(R1, R2), (), S, O, Output> for F | |
128 | // where | |
129 | // F: FnMut(R1, R2, S, &O) -> Fut, | |
130 | // Fut: Future<Output = Output>, | |
131 | // S: 'static, | |
132 | // R1: 'static, | |
133 | // R2: 'static, | |
134 | // { | |
135 | // async fn handle( | |
136 | // &self, | |
137 | // parameters: (R1, R2), | |
138 | // additional_parameters: (), | |
139 | // state: Arc<S>, | |
140 | // operation_state: &O, | |
141 | // ) -> Output { | |
142 | // todo!() | |
143 | // } | |
144 | // } | |
145 | ||
146 | // #[async_trait::async_trait(?Send)] | |
147 | // impl<R1, R2, A1, S, O, Output, F, Fut> GiteratedHandler<(R1, R2), (A1,), S, O, Output> for F | |
148 | // where | |
149 | // F: FnMut(R1, R2, S, &O, A1) -> Fut, | |
150 | // Fut: Future<Output = Output>, | |
151 | // S: 'static, | |
152 | // R1: 'static, | |
153 | // R2: 'static, | |
154 | // A1: 'static + HandlerResolvable<(R1, R2), O, A1>, | |
155 | // { | |
156 | // async fn handle( | |
157 | // &self, | |
158 | // parameters: (R1, R2), | |
159 | // additional_parameters: (A1,), | |
160 | // state: Arc<S>, | |
161 | // operation_state: &O, | |
162 | // ) -> Output { | |
163 | // todo!() | |
164 | // } | |
165 | // } | |
166 | ||
167 | // #[async_trait::async_trait(?Send)] | |
168 | // impl<R1, R2, A1, A2, S, O, Output, F, Fut> GiteratedHandler<(R1, R2), (A1, A2), S, O, Output> for F | |
169 | // where | |
170 | // F: FnMut(R1, R2, S, &O, A1, A2) -> Fut, | |
171 | // Fut: Future<Output = Output>, | |
172 | // S: 'static, | |
173 | // R1: 'static, | |
174 | // R2: 'static, | |
175 | // A1: 'static + HandlerResolvable<(R1, R2), O, A1>, | |
176 | // A2: 'static + HandlerResolvable<(R1, R2), O, A2>, | |
177 | // { | |
178 | // async fn handle( | |
179 | // &self, | |
180 | // parameters: (R1, R2), | |
181 | // additional_parameters: (A1, A2), | |
182 | // state: Arc<S>, | |
183 | // operation_state: &O, | |
184 | // ) -> Output { | |
185 | // todo!() | |
186 | // } | |
187 | // } | |
188 | ||
189 | // #[async_trait::async_trait(?Send)] | |
190 | // impl<R1, R2, A1, A2, A3, S, O, Output, F, Fut> | |
191 | // GiteratedHandler<(R1, R2), (A1, A2, A3), S, O, Output> for F | |
192 | // where | |
193 | // F: FnMut(R1, R2, S, &O, A1, A2, A3) -> Fut, | |
194 | // Fut: Future<Output = Output>, | |
195 | // S: 'static, | |
196 | // R1: 'static, | |
197 | // R2: 'static, | |
198 | // A1: 'static + HandlerResolvable<(R1, R2), O, A1>, | |
199 | // A2: 'static + HandlerResolvable<(R1, R2), O, A2>, | |
200 | // A3: 'static + HandlerResolvable<(R1, R2), O, A3>, | |
201 | // { | |
202 | // async fn handle( | |
203 | // &self, | |
204 | // parameters: (R1, R2), | |
205 | // additional_parameters: (A1, A2, A3), | |
206 | // state: Arc<S>, | |
207 | // operation_state: &O, | |
208 | // ) -> Output { | |
209 | // todo!() | |
210 | // } | |
211 | // } | |
212 | ||
213 | // #[async_trait::async_trait(?Send)] | |
214 | // impl<R1, R2, R3, S, O, Output, F, Fut> GiteratedHandler<(R1, R2, R3), (), S, O, Output> for F | |
215 | // where | |
216 | // F: FnMut(R1, R2, R3, S, &O) -> Fut, | |
217 | // Fut: Future<Output = Output>, | |
218 | // S: 'static, | |
219 | // R1: 'static, | |
220 | // R2: 'static, | |
221 | // R3: 'static, | |
222 | // { | |
223 | // async fn handle( | |
224 | // &self, | |
225 | // parameters: (R1, R2, R3), | |
226 | // additional_parameters: (), | |
227 | // state: Arc<S>, | |
228 | // operation_state: &O, | |
229 | // ) -> Output { | |
230 | // todo!() | |
231 | // } | |
232 | // } | |
233 | ||
234 | // fn test_fn<O, A, S, V, F>(handler: F) | |
235 | // where | |
236 | // F: GiteratedHandler<(O, V), A, S, StackOperationState, Result<(), anyhow::Error>>, | |
237 | // O: GiteratedObject, | |
238 | // V: GiteratedObjectValue<Object = O>, | |
239 | // { | |
240 | // } | |
241 | ||
242 | // fn other_fn() { | |
243 | // let a = String::from("a"); | |
244 | // let test = move |object: User, | |
245 | // value: GetValue, | |
246 | // state: (), | |
247 | // operation_state: &StackOperationState, | |
248 | // authorized_user: AuthorizedUser| { async move { () } }; | |
249 | ||
250 | // let wrapper = HandlerWrapper::<(User, GetValue), _>::new((), test); | |
251 | // } | |
252 | ||
253 | // pub struct HandlerWrapper<P, O> { | |
254 | // func: Box<dyn Fn(P, StackOperationState) -> LocalBoxFuture<'static, O>>, | |
255 | // state: Arc<dyn Any + Send + Sync>, | |
256 | // } | |
257 | ||
258 | // impl<P, O> HandlerWrapper<P, O> { | |
259 | // pub fn new<S, F, A>(state: S, handler: F) -> Self | |
260 | // where | |
261 | // F: GiteratedHandler<P, A, S, StackOperationState, O>, | |
262 | // S: Send + Sync + 'static, | |
263 | // A: HandlerResolvableGroup<P>, | |
264 | // { | |
265 | // let state = Arc::new(state); | |
266 | ||
267 | // let func = |required: P, operation_state: StackOperationState| { | |
268 | // // async move { handler.handle(required, (), state, &operation_state) }.boxed_local() | |
269 | // todo!() | |
270 | // }; | |
271 | ||
272 | // Self { | |
273 | // func: Box::new(func), | |
274 | // state, | |
275 | // } | |
276 | // } | |
277 | // } | |
278 | ||
279 | // #[async_trait::async_trait(?Send)] | |
280 | // pub trait HandlerResolvable<RequiredParameters, OperationState, Output> { | |
281 | // async fn from_handler_state( | |
282 | // required_parameters: &RequiredParameters, | |
283 | // operation_state: &OperationState, | |
284 | // ) -> Output; | |
285 | // } | |
286 | ||
287 | // #[async_trait::async_trait(?Send)] | |
288 | // impl HandlerResolvable<(User, GetValue), StackOperationState, Self> for Arc<GiteratedStack> { | |
289 | // async fn from_handler_state( | |
290 | // required_parameters: &(User, GetValue), | |
291 | // operation_state: &StackOperationState, | |
292 | // ) -> Self { | |
293 | // todo!() | |
294 | // } | |
295 | // } | |
296 | ||
297 | // // #[async_trait::async_trait(?Send)] | |
298 | // // impl<O, D, T> HandlerResolvable<(O, D), StackOperationState, T> for T | |
299 | // // where | |
300 | // // O: GiteratedObject, | |
301 | // // D: GiteratedOperation<O>, | |
302 | // // T: FromOperationState<O, D>, | |
303 | // // { | |
304 | // // async fn from_handler_state( | |
305 | // // required_parameters: &(O, D), | |
306 | // // operation_state: &StackOperationState, | |
307 | // // ) -> T { | |
308 | // // todo!() | |
309 | // // } | |
310 | // // } | |
311 | ||
312 | // #[async_trait::async_trait(?Send)] | |
313 | // pub trait HandlerResolvableGroup<RequiredParameters> { | |
314 | // async fn group_from_handler_state( | |
315 | // required_parameters: &RequiredParameters, | |
316 | // operation_state: &StackOperationState, | |
317 | // ) -> Self; | |
318 | // } | |
319 | ||
320 | // #[async_trait::async_trait(?Send)] | |
321 | // impl<RequiredParameters, A1> HandlerResolvableGroup<RequiredParameters> for (A1,) | |
322 | // where | |
323 | // A1: HandlerResolvable<RequiredParameters, StackOperationState, A1>, | |
324 | // { | |
325 | // async fn group_from_handler_state( | |
326 | // required_parameters: &RequiredParameters, | |
327 | // operation_state: &StackOperationState, | |
328 | // ) -> (A1,) { | |
329 | // (A1::from_handler_state(required_parameters, operation_state).await,) | |
330 | // } | |
331 | // } | |
332 | ||
333 | // #[async_trait::async_trait(?Send)] | |
334 | // impl<RequiredParameters, A1, A2> HandlerResolvableGroup<RequiredParameters> for (A1, A2) | |
335 | // where | |
336 | // A1: HandlerResolvable<RequiredParameters, StackOperationState, A1>, | |
337 | // A2: HandlerResolvable<RequiredParameters, StackOperationState, A2>, | |
338 | // { | |
339 | // async fn group_from_handler_state( | |
340 | // required_parameters: &RequiredParameters, | |
341 | // operation_state: &StackOperationState, | |
342 | // ) -> (A1, A2) { | |
343 | // ( | |
344 | // A1::from_handler_state(required_parameters, operation_state).await, | |
345 | // A2::from_handler_state(required_parameters, operation_state).await, | |
346 | // ) | |
347 | // } | |
348 | // } |
giterated-cache/src/lib.rs
@@ -0,0 +1,25 @@ | ||
1 | // pub mod cache_get; | |
2 | // pub mod cache_update; | |
3 | ||
4 | // use giterated_stack::{ObjectValuePair, SubstackBuilder}; | |
5 | // use moka::future::Cache; | |
6 | // use serde_json::Value; | |
7 | ||
8 | // #[derive(Clone)] | |
9 | // pub struct CacheSubstack { | |
10 | // cache: Cache<ObjectValuePair, Value>, | |
11 | // } | |
12 | ||
13 | // impl Default for CacheSubstack { | |
14 | // fn default() -> Self { | |
15 | // Self { | |
16 | // cache: Cache::new(20_000), | |
17 | // } | |
18 | // } | |
19 | // } | |
20 | ||
21 | // impl CacheSubstack { | |
22 | // pub fn into_substack(self) -> SubstackBuilder<Self> { | |
23 | // todo!() | |
24 | // } | |
25 | // } |
giterated-daemon/src/backend/mod.rs
@@ -25,9 +25,8 @@ use giterated_models::repository::{ | ||
25 | 25 | RepositoryLastCommitOfFileRequest, RepositoryStatistics, RepositoryStatisticsRequest, |
26 | 26 | RepositorySummary, RepositoryTreeEntry, |
27 | 27 | }; |
28 | use giterated_models::settings::AnySetting; | |
28 | ||
29 | 29 | use giterated_models::user::User; |
30 | use giterated_models::value::AnyValue; | |
31 | 30 | |
32 | 31 | #[async_trait] |
33 | 32 | pub trait RepositoryBackend { |
@@ -137,14 +136,6 @@ pub trait AuthBackend { | ||
137 | 136 | |
138 | 137 | #[async_trait::async_trait] |
139 | 138 | pub trait UserBackend: AuthBackend { |
140 | async fn get_value(&mut self, user: &User, name: &str) -> Result<AnyValue<User>, Error>; | |
141 | async fn get_setting(&mut self, user: &User, name: &str) -> Result<AnySetting, Error>; | |
142 | async fn write_setting( | |
143 | &mut self, | |
144 | user: &User, | |
145 | name: &str, | |
146 | setting: &Value, | |
147 | ) -> Result<(), Error>; | |
148 | 139 | async fn exists(&mut self, user: &User) -> Result<bool, Error>; |
149 | 140 | async fn repositories_for_user( |
150 | 141 | &mut self, |
@@ -155,22 +146,14 @@ pub trait UserBackend: AuthBackend { | ||
155 | 146 | |
156 | 147 | #[async_trait::async_trait] |
157 | 148 | pub trait MetadataBackend { |
158 | async fn user_get(&mut self, user: &User, name: &str) -> Result<AnySetting, Error>; | |
159 | async fn user_write( | |
160 | &mut self, | |
161 | user: &User, | |
162 | name: &str, | |
163 | setting: AnySetting, | |
164 | ) -> Result<(), Error>; | |
165 | async fn repository_get( | |
166 | &mut self, | |
167 | repository: &Repository, | |
168 | name: &str, | |
169 | ) -> Result<AnySetting, Error>; | |
149 | async fn user_get(&mut self, user: &User, name: &str) -> Result<Value, Error>; | |
150 | async fn user_write(&mut self, user: &User, name: &str, setting: Value) -> Result<(), Error>; | |
151 | async fn repository_get(&mut self, repository: &Repository, name: &str) | |
152 | -> Result<Value, Error>; | |
170 | 153 | async fn repository_write( |
171 | 154 | &mut self, |
172 | 155 | repository: &Repository, |
173 | 156 | name: &str, |
174 | setting: AnySetting, | |
157 | setting: Value, | |
175 | 158 | ) -> Result<(), Error>; |
176 | 159 | } |
giterated-daemon/src/backend/settings.rs
@@ -3,10 +3,11 @@ use std::sync::Arc; | ||
3 | 3 | use anyhow::Error; |
4 | 4 | |
5 | 5 | use giterated_models::repository::Repository; |
6 | use giterated_models::settings::AnySetting; | |
6 | ||
7 | 7 | use giterated_models::user::User; |
8 | 8 | |
9 | 9 | use giterated_stack::GiteratedStack; |
10 | use serde_json::Value; | |
10 | 11 | use sqlx::PgPool; |
11 | 12 | use tokio::sync::OnceCell; |
12 | 13 | |
@@ -19,7 +20,7 @@ pub struct DatabaseSettings { | ||
19 | 20 | |
20 | 21 | #[async_trait::async_trait] |
21 | 22 | impl MetadataBackend for DatabaseSettings { |
22 | async fn user_get(&mut self, user: &User, name: &str) -> Result<AnySetting, Error> { | |
23 | async fn user_get(&mut self, user: &User, name: &str) -> Result<Value, Error> { | |
23 | 24 | let row = sqlx::query_as!( |
24 | 25 | UserSettingRow, |
25 | 26 | "SELECT * FROM user_settings WHERE username = $1 AND name = $2", |
@@ -33,12 +34,7 @@ impl MetadataBackend for DatabaseSettings { | ||
33 | 34 | |
34 | 35 | Ok(setting) |
35 | 36 | } |
36 | async fn user_write( | |
37 | &mut self, | |
38 | user: &User, | |
39 | name: &str, | |
40 | value: AnySetting, | |
41 | ) -> Result<(), Error> { | |
37 | async fn user_write(&mut self, user: &User, name: &str, value: Value) -> Result<(), Error> { | |
42 | 38 | sqlx::query!("INSERT INTO user_settings VALUES ($1, $2, $3) ON CONFLICT (username, name) DO UPDATE SET value = $3", |
43 | 39 | user.username, name, serde_json::to_string(&value)?) |
44 | 40 | .execute(&self.pg_pool).await?; |
@@ -50,7 +46,7 @@ impl MetadataBackend for DatabaseSettings { | ||
50 | 46 | &mut self, |
51 | 47 | repository: &Repository, |
52 | 48 | name: &str, |
53 | ) -> Result<AnySetting, Error> { | |
49 | ) -> Result<Value, Error> { | |
54 | 50 | let row = sqlx::query_as!( |
55 | 51 | RepositorySettingRow, |
56 | 52 | "SELECT * FROM repository_settings WHERE repository = $1 AND name = $2", |
@@ -68,7 +64,7 @@ impl MetadataBackend for DatabaseSettings { | ||
68 | 64 | &mut self, |
69 | 65 | repository: &Repository, |
70 | 66 | name: &str, |
71 | value: AnySetting, | |
67 | value: Value, | |
72 | 68 | ) -> Result<(), Error> { |
73 | 69 | sqlx::query!("INSERT INTO repository_settings VALUES ($1, $2, $3) ON CONFLICT (repository, name) DO UPDATE SET value = $3", |
74 | 70 | repository.to_string(), name, serde_json::to_string(&value)?) |
giterated-daemon/src/backend/user.rs
@@ -5,9 +5,8 @@ use giterated_models::authenticated::UserAuthenticationToken; | ||
5 | 5 | use giterated_models::instance::{AuthenticationTokenRequest, Instance, RegisterAccountRequest}; |
6 | 6 | |
7 | 7 | use giterated_models::repository::{Repository, RepositorySummary}; |
8 | use giterated_models::settings::{AnySetting, Setting}; | |
9 | use giterated_models::user::{Bio, DisplayName, User, UserParseError}; | |
10 | use giterated_models::value::AnyValue; | |
8 | use giterated_models::user::User; | |
9 | ||
11 | 10 | use giterated_stack::AuthenticatedUser; |
12 | 11 | use std::sync::Arc; |
13 | 12 | |
@@ -22,7 +21,7 @@ use rsa::{ | ||
22 | 21 | }; |
23 | 22 | |
24 | 23 | use secrecy::ExposeSecret; |
25 | use serde_json::Value; | |
24 | ||
26 | 25 | use sqlx::{Either, PgPool}; |
27 | 26 | use tokio::sync::Mutex; |
28 | 27 | |
@@ -56,36 +55,6 @@ impl UserAuth { | ||
56 | 55 | |
57 | 56 | #[async_trait::async_trait] |
58 | 57 | impl UserBackend for UserAuth { |
59 | async fn get_value(&mut self, user: &User, name: &str) -> Result<AnyValue<User>, Error> { | |
60 | Ok(match name { | |
61 | "display_name" => unsafe { | |
62 | AnyValue::from_raw(self.get_setting(user, DisplayName::name()).await?.0) | |
63 | }, | |
64 | "bio" => unsafe { AnyValue::from_raw(self.get_setting(user, Bio::name()).await?.0) }, | |
65 | _ => { | |
66 | return Err(UserParseError.into()); | |
67 | } | |
68 | }) | |
69 | } | |
70 | async fn get_setting(&mut self, user: &User, name: &str) -> Result<AnySetting, Error> { | |
71 | let mut provider = self.settings_provider.lock().await; | |
72 | ||
73 | Ok(provider.user_get(user, name).await?) | |
74 | } | |
75 | ||
76 | async fn write_setting( | |
77 | &mut self, | |
78 | user: &User, | |
79 | name: &str, | |
80 | setting: &Value, | |
81 | ) -> Result<(), Error> { | |
82 | let mut provider = self.settings_provider.lock().await; | |
83 | ||
84 | provider | |
85 | .user_write(user, name, AnySetting(setting.clone())) | |
86 | .await | |
87 | } | |
88 | ||
89 | 58 | async fn exists(&mut self, user: &User) -> Result<bool, Error> { |
90 | 59 | Ok(sqlx::query_as!( |
91 | 60 | UserRow, |
giterated-daemon/src/database_backend/handler.rs
@@ -1,11 +1,8 @@ | ||
1 | 1 | use std::sync::Arc; |
2 | 2 | |
3 | use futures_util::{future::LocalBoxFuture, FutureExt}; | |
4 | 3 | use giterated_models::{ |
5 | 4 | authenticated::UserAuthenticationToken, |
6 | error::{ | |
7 | GetValueError, InstanceError, IntoInternalError, OperationError, RepositoryError, UserError, | |
8 | }, | |
5 | error::{InstanceError, IntoInternalError, OperationError, RepositoryError, UserError}, | |
9 | 6 | instance::{ |
10 | 7 | AuthenticationTokenRequest, Instance, RegisterAccountRequest, RepositoryCreateRequest, |
11 | 8 | }, |
@@ -18,584 +15,384 @@ use giterated_models::{ | ||
18 | 15 | RepositoryInfoRequest, RepositoryLastCommitOfFileRequest, RepositoryStatistics, |
19 | 16 | RepositoryStatisticsRequest, RepositorySummary, RepositoryView, Visibility, |
20 | 17 | }, |
21 | settings::{GetSetting, GetSettingError}, | |
22 | user::{Bio, DisplayName, User, UserRepositoriesRequest}, | |
23 | value::{AnyValue, GetValueTyped}, | |
18 | user::{User, UserRepositoriesRequest}, | |
24 | 19 | }; |
25 | use giterated_stack::{AuthenticatedUser, AuthorizedInstance, GiteratedStack, StackOperationState}; | |
26 | use serde_json::Value; | |
20 | use giterated_stack::{AuthenticatedUser, GiteratedStack, StackOperationState}; | |
27 | 21 | |
28 | 22 | use super::DatabaseBackend; |
29 | 23 | |
30 | pub fn user_get_repositories( | |
31 | object: &User, | |
24 | pub async fn user_get_repositories( | |
25 | object: User, | |
32 | 26 | _operation: UserRepositoriesRequest, |
33 | 27 | state: DatabaseBackend, |
34 | 28 | _operation_state: StackOperationState, |
35 | 29 | requester: Option<AuthenticatedUser>, |
36 | ) -> LocalBoxFuture<'static, Result<Vec<RepositorySummary>, OperationError<UserError>>> { | |
30 | ) -> Result<Vec<RepositorySummary>, OperationError<UserError>> { | |
37 | 31 | let object = object.clone(); |
38 | 32 | |
39 | async move { | |
40 | let mut user_backend = state.user_backend.lock().await; | |
41 | let repositories_response = user_backend | |
42 | .repositories_for_user(&requester, &object) | |
43 | .await | |
44 | .as_internal_error()?; | |
45 | drop(user_backend); | |
46 | let mut repositories_backend = state.repository_backend.lock().await; | |
47 | ||
48 | let mut repositories = vec![]; | |
49 | ||
50 | for repository in repositories_response { | |
51 | if repositories_backend | |
52 | .exists(&requester, &repository.repository) | |
53 | .await | |
54 | .as_internal_error()? | |
55 | { | |
56 | repositories.push(repository); | |
57 | } | |
58 | } | |
59 | ||
60 | Ok(repositories) | |
61 | } | |
62 | .boxed_local() | |
63 | } | |
33 | let mut user_backend = state.user_backend.lock().await; | |
34 | let repositories_response = user_backend | |
35 | .repositories_for_user(&requester, &object) | |
36 | .await | |
37 | .as_internal_error()?; | |
38 | drop(user_backend); | |
39 | let mut repositories_backend = state.repository_backend.lock().await; | |
64 | 40 | |
65 | pub fn user_get_value( | |
66 | object: &User, | |
67 | operation: GetValueTyped<AnyValue<User>>, | |
68 | state: DatabaseBackend, | |
69 | ) -> LocalBoxFuture<'static, Result<AnyValue<User>, OperationError<GetValueError>>> { | |
70 | let object = object.clone(); | |
41 | let mut repositories = vec![]; | |
71 | 42 | |
72 | async move { | |
73 | let mut user_backend = state.user_backend.lock().await; | |
74 | let value = user_backend | |
75 | .get_value(&object, &operation.value_name) | |
43 | for repository in repositories_response { | |
44 | if repositories_backend | |
45 | .exists(&requester, &repository.repository) | |
76 | 46 | .await |
77 | .as_internal_error()?; | |
78 | ||
79 | Ok(value) | |
47 | .as_internal_error()? | |
48 | { | |
49 | repositories.push(repository); | |
50 | } | |
80 | 51 | } |
81 | .boxed_local() | |
82 | } | |
83 | ||
84 | pub fn user_get_setting( | |
85 | object: &User, | |
86 | operation: GetSetting, | |
87 | state: DatabaseBackend, | |
88 | ) -> LocalBoxFuture<'static, Result<Value, OperationError<GetSettingError>>> { | |
89 | let object = object.clone(); | |
90 | ||
91 | async move { | |
92 | let mut user_backend = state.user_backend.lock().await; | |
93 | let value = user_backend | |
94 | .get_setting(&object, &operation.setting_name) | |
95 | .await | |
96 | .as_internal_error()?; | |
97 | 52 | |
98 | Ok(value.0) | |
99 | } | |
100 | .boxed_local() | |
53 | Ok(repositories) | |
101 | 54 | } |
102 | 55 | |
103 | pub fn repository_info( | |
104 | object: &Repository, | |
56 | pub async fn repository_info( | |
57 | object: Repository, | |
105 | 58 | operation: RepositoryInfoRequest, |
106 | 59 | state: DatabaseBackend, |
107 | 60 | operation_state: StackOperationState, |
108 | 61 | backend: Arc<GiteratedStack>, |
109 | 62 | requester: Option<AuthenticatedUser>, |
110 | ) -> LocalBoxFuture<'static, Result<RepositoryView, OperationError<RepositoryError>>> { | |
111 | let object = object.clone(); | |
112 | ||
113 | async move { | |
114 | let mut object = backend | |
115 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
116 | .await | |
117 | .unwrap(); | |
118 | let mut repository_backend = state.repository_backend.lock().await; | |
119 | let tree = repository_backend | |
120 | .repository_file_inspect( | |
121 | &requester, | |
122 | object.object(), | |
123 | &RepositoryFileInspectRequest { | |
124 | extra_metadata: operation.extra_metadata, | |
125 | path: operation.path, | |
126 | rev: operation.rev.clone(), | |
127 | }, | |
128 | ) | |
63 | ) -> Result<RepositoryView, OperationError<RepositoryError>> { | |
64 | let mut object = backend | |
65 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
66 | .await | |
67 | .unwrap(); | |
68 | let mut repository_backend = state.repository_backend.lock().await; | |
69 | let tree = repository_backend | |
70 | .repository_file_inspect( | |
71 | &requester, | |
72 | object.object(), | |
73 | &RepositoryFileInspectRequest { | |
74 | extra_metadata: operation.extra_metadata, | |
75 | path: operation.path.clone(), | |
76 | rev: operation.rev.clone(), | |
77 | }, | |
78 | ) | |
79 | .await | |
80 | .as_internal_error()?; | |
81 | ||
82 | let statistics = repository_backend | |
83 | .repository_get_statistics( | |
84 | &requester, | |
85 | object.object(), | |
86 | &RepositoryStatisticsRequest { | |
87 | rev: operation.rev.clone(), | |
88 | }, | |
89 | ) | |
90 | .await | |
91 | .as_internal_error()?; | |
92 | drop(repository_backend); | |
93 | ||
94 | let info = RepositoryView { | |
95 | name: object.object().name.clone(), | |
96 | owner: object.object().owner.clone(), | |
97 | description: object.get::<Description>(&operation_state).await.ok(), | |
98 | visibility: object | |
99 | .get::<Visibility>(&operation_state) | |
129 | 100 | .await |
130 | .as_internal_error()?; | |
131 | ||
132 | let statistics = repository_backend | |
133 | .repository_get_statistics( | |
134 | &requester, | |
135 | object.object(), | |
136 | &RepositoryStatisticsRequest { | |
137 | rev: operation.rev.clone(), | |
138 | }, | |
139 | ) | |
101 | .as_internal_error()?, | |
102 | default_branch: object | |
103 | .get::<DefaultBranch>(&operation_state) | |
140 | 104 | .await |
141 | .as_internal_error()?; | |
142 | drop(repository_backend); | |
143 | ||
144 | let info = RepositoryView { | |
145 | name: object.object().name.clone(), | |
146 | owner: object.object().owner.clone(), | |
147 | description: object.get::<Description>(&operation_state).await.ok(), | |
148 | visibility: object | |
149 | .get::<Visibility>(&operation_state) | |
150 | .await | |
151 | .as_internal_error()?, | |
152 | default_branch: object | |
153 | .get::<DefaultBranch>(&operation_state) | |
154 | .await | |
155 | .as_internal_error()?, | |
156 | // TODO: Can't be a simple get function, this needs to be returned alongside the tree as this differs depending on the rev and path. | |
157 | latest_commit: object.get::<LatestCommit>(&operation_state).await.ok(), | |
158 | stats: statistics, | |
159 | tree_rev: operation.rev, | |
160 | tree, | |
161 | }; | |
162 | ||
163 | Ok(info) | |
164 | } | |
165 | .boxed_local() | |
105 | .as_internal_error()?, | |
106 | // TODO: Can't be a simple get function, this needs to be returned alongside the tree as this differs depending on the rev and path. | |
107 | latest_commit: object.get::<LatestCommit>(&operation_state).await.ok(), | |
108 | stats: statistics, | |
109 | tree_rev: operation.rev.clone(), | |
110 | tree, | |
111 | }; | |
112 | ||
113 | Ok(info) | |
166 | 114 | } |
167 | 115 | |
168 | pub fn repository_get_statistics( | |
169 | object: &Repository, | |
116 | pub async fn repository_get_statistics( | |
117 | object: Repository, | |
170 | 118 | operation: RepositoryStatisticsRequest, |
171 | 119 | state: DatabaseBackend, |
172 | 120 | operation_state: StackOperationState, |
173 | 121 | backend: Arc<GiteratedStack>, |
174 | 122 | requester: Option<AuthenticatedUser>, |
175 | ) -> LocalBoxFuture<'static, Result<RepositoryStatistics, OperationError<RepositoryError>>> { | |
176 | let object = object.clone(); | |
177 | ||
178 | async move { | |
179 | let object = backend | |
180 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
181 | .await | |
182 | .unwrap(); | |
183 | ||
184 | let mut repository_backend = state.repository_backend.lock().await; | |
185 | let statistics = repository_backend | |
186 | .repository_get_statistics( | |
187 | &requester, | |
188 | object.object(), | |
189 | &RepositoryStatisticsRequest { rev: operation.rev }, | |
190 | ) | |
191 | .await | |
192 | .as_internal_error()?; | |
193 | drop(repository_backend); | |
194 | ||
195 | Ok(statistics) | |
196 | } | |
197 | .boxed_local() | |
123 | ) -> Result<RepositoryStatistics, OperationError<RepositoryError>> { | |
124 | let object = backend | |
125 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
126 | .await | |
127 | .unwrap(); | |
128 | ||
129 | let mut repository_backend = state.repository_backend.lock().await; | |
130 | let statistics = repository_backend | |
131 | .repository_get_statistics( | |
132 | &requester, | |
133 | object.object(), | |
134 | &RepositoryStatisticsRequest { | |
135 | rev: operation.rev.clone(), | |
136 | }, | |
137 | ) | |
138 | .await | |
139 | .as_internal_error()?; | |
140 | drop(repository_backend); | |
141 | ||
142 | Ok(statistics) | |
198 | 143 | } |
199 | 144 | |
200 | pub fn repository_get_branches( | |
201 | object: &Repository, | |
145 | pub async fn repository_get_branches( | |
146 | object: Repository, | |
202 | 147 | operation: RepositoryBranchesRequest, |
203 | 148 | state: DatabaseBackend, |
204 | 149 | operation_state: StackOperationState, |
205 | 150 | backend: Arc<GiteratedStack>, |
206 | 151 | requester: Option<AuthenticatedUser>, |
207 | ) -> LocalBoxFuture<'static, Result<Vec<RepositoryBranch>, OperationError<RepositoryError>>> { | |
208 | let object = object.clone(); | |
209 | ||
210 | async move { | |
211 | let object = backend | |
212 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
213 | .await | |
214 | .unwrap(); | |
215 | ||
216 | let mut repository_backend = state.repository_backend.lock().await; | |
217 | let branches = repository_backend | |
218 | .repository_get_branches(&requester, object.object(), &operation) | |
219 | .await | |
220 | .as_internal_error()?; | |
221 | drop(repository_backend); | |
222 | ||
223 | Ok(branches) | |
224 | } | |
225 | .boxed_local() | |
152 | ) -> Result<Vec<RepositoryBranch>, OperationError<RepositoryError>> { | |
153 | let object = backend | |
154 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
155 | .await | |
156 | .unwrap(); | |
157 | ||
158 | let mut repository_backend = state.repository_backend.lock().await; | |
159 | let branches = repository_backend | |
160 | .repository_get_branches(&requester, object.object(), &operation) | |
161 | .await | |
162 | .as_internal_error()?; | |
163 | drop(repository_backend); | |
164 | ||
165 | Ok(branches) | |
226 | 166 | } |
227 | 167 | |
228 | pub fn repository_file_from_id( | |
229 | object: &Repository, | |
168 | pub async fn repository_file_from_id( | |
169 | object: Repository, | |
230 | 170 | operation: RepositoryFileFromIdRequest, |
231 | 171 | state: DatabaseBackend, |
232 | 172 | operation_state: StackOperationState, |
233 | 173 | backend: Arc<GiteratedStack>, |
234 | 174 | |
235 | 175 | requester: Option<AuthenticatedUser>, |
236 | ) -> LocalBoxFuture<'static, Result<RepositoryFile, OperationError<RepositoryError>>> { | |
237 | let object = object.clone(); | |
238 | ||
239 | async move { | |
240 | let object = backend | |
241 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
242 | .await | |
243 | .unwrap(); | |
244 | ||
245 | let mut repository_backend = state.repository_backend.lock().await; | |
246 | let file = repository_backend | |
247 | .repository_file_from_id( | |
248 | &requester, | |
249 | object.object(), | |
250 | &RepositoryFileFromIdRequest(operation.0), | |
251 | ) | |
252 | .await | |
253 | .as_internal_error()?; | |
254 | drop(repository_backend); | |
255 | ||
256 | Ok(file) | |
257 | } | |
258 | .boxed_local() | |
176 | ) -> Result<RepositoryFile, OperationError<RepositoryError>> { | |
177 | let object = backend | |
178 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
179 | .await | |
180 | .unwrap(); | |
181 | ||
182 | let mut repository_backend = state.repository_backend.lock().await; | |
183 | let file = repository_backend | |
184 | .repository_file_from_id( | |
185 | &requester, | |
186 | object.object(), | |
187 | &RepositoryFileFromIdRequest(operation.0.clone()), | |
188 | ) | |
189 | .await | |
190 | .as_internal_error()?; | |
191 | drop(repository_backend); | |
192 | ||
193 | Ok(file) | |
259 | 194 | } |
260 | 195 | |
261 | pub fn repository_file_from_path( | |
262 | object: &Repository, | |
196 | pub async fn repository_file_from_path( | |
197 | object: Repository, | |
263 | 198 | operation: RepositoryFileFromPathRequest, |
264 | 199 | state: DatabaseBackend, |
265 | 200 | operation_state: StackOperationState, |
266 | 201 | backend: Arc<GiteratedStack>, |
267 | 202 | requester: Option<AuthenticatedUser>, |
268 | ) -> LocalBoxFuture<'static, Result<(RepositoryFile, String), OperationError<RepositoryError>>> { | |
269 | let object = object.clone(); | |
270 | ||
271 | async move { | |
272 | let object = backend | |
273 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
274 | .await | |
275 | .unwrap(); | |
276 | ||
277 | let mut repository_backend = state.repository_backend.lock().await; | |
278 | let file = repository_backend | |
279 | .repository_file_from_path( | |
280 | &requester, | |
281 | object.object(), | |
282 | &RepositoryFileFromPathRequest { | |
283 | rev: operation.rev, | |
284 | path: operation.path, | |
285 | }, | |
286 | ) | |
287 | .await | |
288 | .as_internal_error()?; | |
289 | drop(repository_backend); | |
290 | ||
291 | Ok(file) | |
292 | } | |
293 | .boxed_local() | |
203 | ) -> Result<(RepositoryFile, String), OperationError<RepositoryError>> { | |
204 | let object = backend | |
205 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
206 | .await | |
207 | .unwrap(); | |
208 | ||
209 | let mut repository_backend = state.repository_backend.lock().await; | |
210 | let file = repository_backend | |
211 | .repository_file_from_path( | |
212 | &requester, | |
213 | object.object(), | |
214 | &RepositoryFileFromPathRequest { | |
215 | rev: operation.rev.clone(), | |
216 | path: operation.path.clone(), | |
217 | }, | |
218 | ) | |
219 | .await | |
220 | .as_internal_error()?; | |
221 | drop(repository_backend); | |
222 | ||
223 | Ok(file) | |
294 | 224 | } |
295 | 225 | |
296 | pub fn repository_last_commit_of_file( | |
297 | object: &Repository, | |
226 | pub async fn repository_last_commit_of_file( | |
227 | object: Repository, | |
298 | 228 | operation: RepositoryLastCommitOfFileRequest, |
299 | 229 | state: DatabaseBackend, |
300 | 230 | operation_state: StackOperationState, |
301 | 231 | backend: Arc<GiteratedStack>, |
302 | 232 | requester: Option<AuthenticatedUser>, |
303 | ) -> LocalBoxFuture<'static, Result<Commit, OperationError<RepositoryError>>> { | |
304 | let object = object.clone(); | |
305 | ||
306 | async move { | |
307 | let object = backend | |
308 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
309 | .await | |
310 | .unwrap(); | |
311 | ||
312 | let mut repository_backend = state.repository_backend.lock().await; | |
313 | let commit = repository_backend | |
314 | .repository_last_commit_of_file( | |
315 | &requester, | |
316 | object.object(), | |
317 | &RepositoryLastCommitOfFileRequest { | |
318 | start_commit: operation.start_commit, | |
319 | path: operation.path, | |
320 | }, | |
321 | ) | |
322 | .await | |
323 | .as_internal_error()?; | |
324 | drop(repository_backend); | |
325 | ||
326 | Ok(commit) | |
327 | } | |
328 | .boxed_local() | |
233 | ) -> Result<Commit, OperationError<RepositoryError>> { | |
234 | let object = backend | |
235 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
236 | .await | |
237 | .unwrap(); | |
238 | ||
239 | let mut repository_backend = state.repository_backend.lock().await; | |
240 | let commit = repository_backend | |
241 | .repository_last_commit_of_file( | |
242 | &requester, | |
243 | object.object(), | |
244 | &RepositoryLastCommitOfFileRequest { | |
245 | start_commit: operation.start_commit.clone(), | |
246 | path: operation.path.clone(), | |
247 | }, | |
248 | ) | |
249 | .await | |
250 | .as_internal_error()?; | |
251 | drop(repository_backend); | |
252 | ||
253 | Ok(commit) | |
329 | 254 | } |
330 | 255 | |
331 | pub fn repository_commit_by_id( | |
332 | object: &Repository, | |
256 | pub async fn repository_commit_by_id( | |
257 | object: Repository, | |
333 | 258 | operation: RepositoryCommitFromIdRequest, |
334 | 259 | state: DatabaseBackend, |
335 | 260 | operation_state: StackOperationState, |
336 | 261 | backend: Arc<GiteratedStack>, |
337 | 262 | requester: Option<AuthenticatedUser>, |
338 | ) -> LocalBoxFuture<'static, Result<Commit, OperationError<RepositoryError>>> { | |
339 | let object = object.clone(); | |
340 | ||
341 | async move { | |
342 | let object = backend | |
343 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
344 | .await | |
345 | .unwrap(); | |
346 | ||
347 | let mut repository_backend = state.repository_backend.lock().await; | |
348 | let commit = repository_backend | |
349 | .repository_commit_from_id( | |
350 | &requester, | |
351 | object.object(), | |
352 | &RepositoryCommitFromIdRequest(operation.0), | |
353 | ) | |
354 | .await | |
355 | .as_internal_error()?; | |
356 | drop(repository_backend); | |
357 | ||
358 | Ok(commit) | |
359 | } | |
360 | .boxed_local() | |
263 | ) -> Result<Commit, OperationError<RepositoryError>> { | |
264 | let object = backend | |
265 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
266 | .await | |
267 | .unwrap(); | |
268 | ||
269 | let mut repository_backend = state.repository_backend.lock().await; | |
270 | let commit = repository_backend | |
271 | .repository_commit_from_id( | |
272 | &requester, | |
273 | object.object(), | |
274 | &RepositoryCommitFromIdRequest(operation.0.clone()), | |
275 | ) | |
276 | .await | |
277 | .as_internal_error()?; | |
278 | drop(repository_backend); | |
279 | ||
280 | Ok(commit) | |
361 | 281 | } |
362 | 282 | |
363 | pub fn repository_diff( | |
364 | object: &Repository, | |
283 | pub async fn repository_diff( | |
284 | object: Repository, | |
365 | 285 | operation: RepositoryDiffRequest, |
366 | 286 | state: DatabaseBackend, |
367 | 287 | operation_state: StackOperationState, |
368 | 288 | backend: Arc<GiteratedStack>, |
369 | 289 | requester: Option<AuthenticatedUser>, |
370 | ) -> LocalBoxFuture<'static, Result<RepositoryDiff, OperationError<RepositoryError>>> { | |
371 | let object = object.clone(); | |
372 | ||
373 | async move { | |
374 | let object = backend | |
375 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
376 | .await | |
377 | .unwrap(); | |
378 | ||
379 | let mut repository_backend = state.repository_backend.lock().await; | |
380 | let diff = repository_backend | |
381 | .repository_diff(&requester, object.object(), &operation) | |
382 | .await | |
383 | .as_internal_error()?; | |
384 | drop(repository_backend); | |
385 | ||
386 | Ok(diff) | |
387 | } | |
388 | .boxed_local() | |
290 | ) -> Result<RepositoryDiff, OperationError<RepositoryError>> { | |
291 | let object = backend | |
292 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
293 | .await | |
294 | .unwrap(); | |
295 | ||
296 | let mut repository_backend = state.repository_backend.lock().await; | |
297 | let diff = repository_backend | |
298 | .repository_diff(&requester, object.object(), &operation) | |
299 | .await | |
300 | .as_internal_error()?; | |
301 | drop(repository_backend); | |
302 | ||
303 | Ok(diff) | |
389 | 304 | } |
390 | 305 | |
391 | pub fn repository_diff_patch( | |
392 | object: &Repository, | |
306 | pub async fn repository_diff_patch( | |
307 | object: Repository, | |
393 | 308 | operation: RepositoryDiffPatchRequest, |
394 | 309 | state: DatabaseBackend, |
395 | 310 | operation_state: StackOperationState, |
396 | 311 | backend: Arc<GiteratedStack>, |
397 | 312 | requester: Option<AuthenticatedUser>, |
398 | ) -> LocalBoxFuture<'static, Result<String, OperationError<RepositoryError>>> { | |
399 | let object = object.clone(); | |
400 | ||
401 | async move { | |
402 | let object = backend | |
403 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
404 | .await | |
405 | .unwrap(); | |
406 | ||
407 | let mut repository_backend = state.repository_backend.lock().await; | |
408 | let patch = repository_backend | |
409 | .repository_diff_patch(&requester, object.object(), &operation) | |
410 | .await | |
411 | .as_internal_error()?; | |
412 | drop(repository_backend); | |
413 | ||
414 | Ok(patch) | |
415 | } | |
416 | .boxed_local() | |
313 | ) -> Result<String, OperationError<RepositoryError>> { | |
314 | let object = backend | |
315 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
316 | .await | |
317 | .unwrap(); | |
318 | ||
319 | let mut repository_backend = state.repository_backend.lock().await; | |
320 | let patch = repository_backend | |
321 | .repository_diff_patch(&requester, object.object(), &operation) | |
322 | .await | |
323 | .as_internal_error()?; | |
324 | drop(repository_backend); | |
325 | ||
326 | Ok(patch) | |
417 | 327 | } |
418 | 328 | |
419 | pub fn repository_commit_before( | |
420 | object: &Repository, | |
329 | pub async fn repository_commit_before( | |
330 | object: Repository, | |
421 | 331 | operation: RepositoryCommitBeforeRequest, |
422 | 332 | state: DatabaseBackend, |
423 | 333 | operation_state: StackOperationState, |
424 | 334 | backend: Arc<GiteratedStack>, |
425 | 335 | requester: Option<AuthenticatedUser>, |
426 | ) -> LocalBoxFuture<'static, Result<Commit, OperationError<RepositoryError>>> { | |
427 | let object = object.clone(); | |
428 | ||
429 | async move { | |
430 | let object = backend | |
431 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
432 | .await | |
433 | .unwrap(); | |
434 | ||
435 | let mut repository_backend = state.repository_backend.lock().await; | |
436 | let file = repository_backend | |
437 | .repository_commit_before(&requester, object.object(), &operation) | |
438 | .await | |
439 | .as_internal_error()?; | |
440 | drop(repository_backend); | |
441 | ||
442 | Ok(file) | |
443 | } | |
444 | .boxed_local() | |
336 | ) -> Result<Commit, OperationError<RepositoryError>> { | |
337 | let object = backend | |
338 | .get_object::<Repository>(&object.to_string(), &operation_state) | |
339 | .await | |
340 | .unwrap(); | |
341 | ||
342 | let mut repository_backend = state.repository_backend.lock().await; | |
343 | let file = repository_backend | |
344 | .repository_commit_before(&requester, object.object(), &operation) | |
345 | .await | |
346 | .as_internal_error()?; | |
347 | drop(repository_backend); | |
348 | ||
349 | Ok(file) | |
445 | 350 | } |
446 | 351 | |
447 | pub fn instance_authentication_request( | |
448 | object: &Instance, | |
352 | pub async fn instance_authentication_request( | |
353 | object: Instance, | |
449 | 354 | operation: AuthenticationTokenRequest, |
450 | 355 | state: DatabaseBackend, |
356 | _operation_state: StackOperationState, | |
451 | 357 | // Authorizes the request for SAME-INSTANCE |
452 | _authorized_instance: AuthorizedInstance, | |
453 | ) -> LocalBoxFuture<'static, Result<UserAuthenticationToken, OperationError<InstanceError>>> { | |
454 | let object = object.clone(); | |
455 | async move { | |
456 | let mut backend = state.user_backend.lock().await; | |
457 | ||
458 | backend.login(&object, operation).await.as_internal_error() | |
459 | } | |
460 | .boxed_local() | |
358 | // _authorized_instance: AuthorizedInstance, | |
359 | ) -> Result<UserAuthenticationToken, OperationError<InstanceError>> { | |
360 | let mut backend = state.user_backend.lock().await; | |
361 | ||
362 | backend | |
363 | .login(&object, operation.clone()) | |
364 | .await | |
365 | .as_internal_error() | |
461 | 366 | } |
462 | 367 | |
463 | pub fn instance_registration_request( | |
464 | _object: &Instance, | |
368 | pub async fn instance_registration_request( | |
369 | _object: Instance, | |
465 | 370 | operation: RegisterAccountRequest, |
466 | 371 | state: DatabaseBackend, |
467 | // Authorizes the request for SAME-INSTANCE | |
468 | _authorized_instance: AuthorizedInstance, | |
469 | ) -> LocalBoxFuture<'static, Result<UserAuthenticationToken, OperationError<InstanceError>>> { | |
470 | async move { | |
471 | let mut backend = state.user_backend.lock().await; | |
472 | ||
473 | backend.register(operation).await.as_internal_error() | |
474 | } | |
475 | .boxed_local() | |
372 | _operation_state: StackOperationState, // Authorizes the request for SAME-INSTANCE | |
373 | // _authorized_instance: AuthorizedInstance, | |
374 | ) -> Result<UserAuthenticationToken, OperationError<InstanceError>> { | |
375 | let mut backend = state.user_backend.lock().await; | |
376 | ||
377 | backend | |
378 | .register(operation.clone()) | |
379 | .await | |
380 | .as_internal_error() | |
476 | 381 | } |
477 | 382 | |
478 | pub fn instance_create_repository_request( | |
479 | _object: &Instance, | |
383 | pub async fn instance_create_repository_request( | |
384 | _object: Instance, | |
480 | 385 | operation: RepositoryCreateRequest, |
481 | 386 | state: DatabaseBackend, |
387 | _operation_state: StackOperationState, | |
482 | 388 | requester: AuthenticatedUser, |
483 | 389 | // Authorizes the request for SAME-INSTANCE |
484 | _authorized_instance: AuthorizedInstance, | |
485 | ) -> LocalBoxFuture<'static, Result<Repository, OperationError<InstanceError>>> { | |
486 | async move { | |
487 | let mut backend = state.repository_backend.lock().await; | |
488 | ||
489 | backend | |
490 | .create_repository(&requester, &operation) | |
491 | .await | |
492 | .as_internal_error() | |
493 | } | |
494 | .boxed_local() | |
495 | } | |
496 | ||
497 | pub fn user_get_value_display_name( | |
498 | object: &User, | |
499 | _operation: GetValueTyped<DisplayName>, | |
500 | _state: DatabaseBackend, | |
501 | stack: Arc<GiteratedStack>, // _requester: AuthorizedUser, | |
502 | ) -> LocalBoxFuture<'static, Result<DisplayName, OperationError<GetValueError>>> { | |
503 | let object = object.clone(); | |
504 | ||
505 | async move { | |
506 | stack | |
507 | .new_get_setting::<_, DisplayName>(&object) | |
508 | .await | |
509 | .as_internal_error() | |
510 | } | |
511 | .boxed_local() | |
512 | } | |
513 | ||
514 | pub fn user_get_value_bio( | |
515 | object: &User, | |
516 | _operation: GetValueTyped<Bio>, | |
517 | _state: DatabaseBackend, | |
518 | stack: Arc<GiteratedStack>, | |
519 | ) -> LocalBoxFuture<'static, Result<Bio, OperationError<GetValueError>>> { | |
520 | let object = object.clone(); | |
521 | ||
522 | async move { | |
523 | stack | |
524 | .new_get_setting::<_, Bio>(&object) | |
525 | .await | |
526 | .as_internal_error() | |
527 | } | |
528 | .boxed_local() | |
529 | } | |
530 | ||
531 | pub fn repository_get_value_description( | |
532 | object: &Repository, | |
533 | _operation: GetValueTyped<Description>, | |
534 | _state: DatabaseBackend, | |
535 | stack: Arc<GiteratedStack>, | |
536 | ) -> LocalBoxFuture<'static, Result<Description, OperationError<GetValueError>>> { | |
537 | let object = object.clone(); | |
538 | ||
539 | async move { | |
540 | stack | |
541 | .new_get_setting::<_, Description>(&object) | |
542 | .await | |
543 | .as_internal_error() | |
544 | } | |
545 | .boxed_local() | |
546 | } | |
547 | ||
548 | pub fn repository_get_value_visibility( | |
549 | object: &Repository, | |
550 | _operation: GetValueTyped<Visibility>, | |
551 | _state: DatabaseBackend, | |
552 | stack: Arc<GiteratedStack>, | |
553 | ) -> LocalBoxFuture<'static, Result<Visibility, OperationError<GetValueError>>> { | |
554 | let object = object.clone(); | |
555 | ||
556 | async move { | |
557 | stack | |
558 | .new_get_setting::<_, Visibility>(&object) | |
559 | .await | |
560 | .as_internal_error() | |
561 | } | |
562 | .boxed_local() | |
563 | } | |
564 | ||
565 | pub fn repository_get_default_branch( | |
566 | object: &Repository, | |
567 | _operation: GetValueTyped<DefaultBranch>, | |
568 | _state: DatabaseBackend, | |
569 | stack: Arc<GiteratedStack>, | |
570 | ) -> LocalBoxFuture<'static, Result<DefaultBranch, OperationError<GetValueError>>> { | |
571 | let object = object.clone(); | |
572 | ||
573 | async move { | |
574 | stack | |
575 | .new_get_setting::<_, DefaultBranch>(&object) | |
576 | .await | |
577 | .as_internal_error() | |
578 | } | |
579 | .boxed_local() | |
580 | } | |
581 | ||
582 | pub fn repository_get_latest_commit( | |
583 | object: &Repository, | |
584 | _operation: GetValueTyped<LatestCommit>, | |
585 | state: DatabaseBackend, | |
586 | _stack: Arc<GiteratedStack>, | |
587 | ) -> LocalBoxFuture<'static, Result<LatestCommit, OperationError<GetValueError>>> { | |
588 | let _object = object.clone(); | |
589 | ||
590 | async move { | |
591 | let _backend = state.repository_backend.lock().await; | |
592 | ||
593 | // stack | |
594 | // .new_get_setting::<_, LatestCommit>(&*object) | |
595 | // .await | |
596 | // .as_internal_error() | |
597 | ||
598 | Ok(LatestCommit(None)) | |
599 | } | |
600 | .boxed_local() | |
390 | // _authorized_instance: AuthorizedInstance, | |
391 | ) -> Result<Repository, OperationError<InstanceError>> { | |
392 | let mut backend = state.repository_backend.lock().await; | |
393 | ||
394 | backend | |
395 | .create_repository(&requester, &operation) | |
396 | .await | |
397 | .as_internal_error() | |
601 | 398 | } |
giterated-daemon/src/database_backend/mod.rs
@@ -5,16 +5,13 @@ use std::any::Any; | ||
5 | 5 | use std::sync::Arc; |
6 | 6 | |
7 | 7 | use anyhow::Context; |
8 | use giterated_models::error::OperationError; | |
8 | ||
9 | 9 | use giterated_models::instance::Instance; |
10 | use giterated_models::object::{GiteratedObject, Object, ObjectRequestError}; | |
11 | use giterated_models::object_backend::ObjectBackend; | |
12 | use giterated_models::operation::GiteratedOperation; | |
13 | 10 | use giterated_models::repository::{DefaultBranch, Description, Repository, Visibility}; |
14 | 11 | use giterated_models::user::{Bio, DisplayName, User}; |
15 | 12 | use giterated_stack::provider::MetadataProvider; |
16 | use giterated_stack::{GiteratedStack, ObjectMeta, SubstackBuilder}; | |
17 | use giterated_stack::{SettingMeta, StackOperationState}; | |
13 | use giterated_stack::SettingMeta; | |
14 | use giterated_stack::{AnyObject, AnySetting, GiteratedStack, ObjectMeta, SubstackBuilder}; | |
18 | 15 | use serde_json::Value; |
19 | 16 | use sqlx::PgPool; |
20 | 17 | use std::fmt::Debug; |
@@ -27,37 +24,10 @@ use self::handler::{ | ||
27 | 24 | instance_authentication_request, instance_create_repository_request, |
28 | 25 | instance_registration_request, repository_commit_before, repository_commit_by_id, |
29 | 26 | repository_diff, repository_diff_patch, repository_file_from_id, repository_file_from_path, |
30 | repository_get_branches, repository_get_default_branch, repository_get_latest_commit, | |
31 | repository_get_statistics, repository_get_value_description, repository_get_value_visibility, | |
32 | repository_info, repository_last_commit_of_file, user_get_repositories, user_get_value_bio, | |
33 | user_get_value_display_name, | |
27 | repository_get_branches, repository_get_statistics, repository_info, | |
28 | repository_last_commit_of_file, user_get_repositories, | |
34 | 29 | }; |
35 | 30 | |
36 | #[derive(Clone, Debug)] | |
37 | pub struct Foobackend {} | |
38 | ||
39 | #[async_trait::async_trait(?Send)] | |
40 | impl ObjectBackend<StackOperationState> for Foobackend { | |
41 | async fn object_operation<O: GiteratedObject + Debug, D: GiteratedOperation<O> + Debug>( | |
42 | &self, | |
43 | _object: O, | |
44 | _operation: &str, | |
45 | _payload: D, | |
46 | _operation_state: &StackOperationState, | |
47 | ) -> Result<D::Success, OperationError<D::Failure>> { | |
48 | // We don't handle operations with this backend | |
49 | Err(OperationError::Unhandled) | |
50 | } | |
51 | ||
52 | async fn get_object<O: GiteratedObject + Debug>( | |
53 | &self, | |
54 | _object_str: &str, | |
55 | _operation_state: &StackOperationState, | |
56 | ) -> Result<Object<StackOperationState, O, Self>, OperationError<ObjectRequestError>> { | |
57 | Err(OperationError::Unhandled) | |
58 | } | |
59 | } | |
60 | ||
61 | 31 | /// A backend implementation which attempts to resolve data from the instance's database. |
62 | 32 | #[derive(Clone)] |
63 | 33 | #[allow(unused)] |
@@ -105,8 +75,6 @@ impl DatabaseBackend { | ||
105 | 75 | .value_setting::<Repository, Visibility>() |
106 | 76 | .value_setting::<Repository, DefaultBranch>(); |
107 | 77 | |
108 | builder.value(repository_get_latest_commit); | |
109 | ||
110 | 78 | builder |
111 | 79 | .operation(user_get_repositories) |
112 | 80 | .operation(instance_registration_request) |
@@ -141,18 +109,18 @@ impl MetadataProvider for DatabaseBackend { | ||
141 | 109 | |
142 | 110 | async fn write( |
143 | 111 | &self, |
144 | object: &(dyn Any + Send + Sync), | |
112 | object: AnyObject, | |
145 | 113 | _object_meta: &ObjectMeta, |
146 | setting: &(dyn Any + Send + Sync), | |
114 | setting: AnySetting, | |
147 | 115 | setting_meta: &SettingMeta, |
148 | 116 | ) -> Result<(), anyhow::Error> { |
149 | if let Some(repository) = object.downcast_ref::<Repository>() { | |
117 | if let Some(repository) = object.0.downcast_ref::<Repository>() { | |
150 | 118 | sqlx::query!("INSERT INTO repository_settings VALUES ($1, $2, $3) ON CONFLICT (repository, name) DO UPDATE SET value = $3", |
151 | 119 | repository.to_string(), setting_meta.name, serde_json::to_string(&(setting_meta.serialize)(setting).unwrap())?) |
152 | 120 | .execute(&self.pool).await?; |
153 | 121 | |
154 | 122 | Ok(()) |
155 | } else if let Some(user) = object.downcast_ref::<User>() { | |
123 | } else if let Some(user) = object.0.downcast_ref::<User>() { | |
156 | 124 | sqlx::query!("INSERT INTO user_settings VALUES ($1, $2, $3) ON CONFLICT (username, name) DO UPDATE SET value = $3", |
157 | 125 | user.username, setting_meta.name, serde_json::to_string(&(setting_meta.serialize)(setting).unwrap())?) |
158 | 126 | .execute(&self.pool).await?; |
@@ -165,11 +133,11 @@ impl MetadataProvider for DatabaseBackend { | ||
165 | 133 | |
166 | 134 | async fn read( |
167 | 135 | &self, |
168 | object: &(dyn Any + Send + Sync), | |
136 | object: AnyObject, | |
169 | 137 | _object_meta: &ObjectMeta, |
170 | 138 | setting_meta: &SettingMeta, |
171 | 139 | ) -> Result<Value, anyhow::Error> { |
172 | if let Some(repository) = object.downcast_ref::<Repository>() { | |
140 | if let Some(repository) = object.0.downcast_ref::<Repository>() { | |
173 | 141 | let row = sqlx::query_as!( |
174 | 142 | RepositorySettingRow, |
175 | 143 | "SELECT * FROM repository_settings WHERE repository = $1 AND name = $2", |
@@ -183,7 +151,7 @@ impl MetadataProvider for DatabaseBackend { | ||
183 | 151 | serde_json::from_str(&row.value).context("deserializing setting from database")?; |
184 | 152 | |
185 | 153 | Ok(setting) |
186 | } else if let Some(user) = object.downcast_ref::<User>() { | |
154 | } else if let Some(user) = object.0.downcast_ref::<User>() { | |
187 | 155 | info!("User for {}", setting_meta.name); |
188 | 156 | let row = sqlx::query_as!( |
189 | 157 | UserSettingRow, |
giterated-models/src/authenticated.rs
@@ -12,8 +12,8 @@ use serde::{Deserialize, Serialize}; | ||
12 | 12 | use crate::{ |
13 | 13 | instance::Instance, |
14 | 14 | message::GiteratedMessage, |
15 | object::{AnyObject, GiteratedObject}, | |
16 | operation::{AnyOperation, GiteratedOperation}, | |
15 | object::{GiteratedObject, NetworkAnyObject}, | |
16 | operation::{GiteratedOperation, NetworkAnyOperation}, | |
17 | 17 | user::User, |
18 | 18 | }; |
19 | 19 | |
@@ -39,11 +39,11 @@ pub struct AuthenticatedPayload { | ||
39 | 39 | } |
40 | 40 | |
41 | 41 | impl AuthenticatedPayload { |
42 | pub fn into_message(self) -> GiteratedMessage<AnyObject, AnyOperation> { | |
42 | pub fn into_message(self) -> GiteratedMessage<NetworkAnyObject, NetworkAnyOperation> { | |
43 | 43 | GiteratedMessage { |
44 | object: AnyObject(self.object), | |
44 | object: NetworkAnyObject(self.object), | |
45 | 45 | operation: self.operation, |
46 | payload: AnyOperation(self.payload), | |
46 | payload: NetworkAnyOperation(self.payload), | |
47 | 47 | } |
48 | 48 | } |
49 | 49 | } |
giterated-models/src/error.rs
@@ -2,7 +2,7 @@ use std::fmt::Display; | ||
2 | 2 | |
3 | 3 | use serde::{Deserialize, Serialize}; |
4 | 4 | |
5 | #[derive(Debug, thiserror::Error, Deserialize, Serialize)] | |
5 | #[derive(Debug, thiserror::Error, Deserialize, Serialize, Clone)] | |
6 | 6 | pub enum InstanceError { |
7 | 7 | #[error("registration failed")] |
8 | 8 | RegistrationFailure, |
@@ -10,19 +10,19 @@ pub enum InstanceError { | ||
10 | 10 | AuthenticationFailed, |
11 | 11 | } |
12 | 12 | |
13 | #[derive(Debug, thiserror::Error, Serialize, Deserialize)] | |
13 | #[derive(Debug, thiserror::Error, Serialize, Deserialize, Clone)] | |
14 | 14 | pub enum RepositoryError {} |
15 | 15 | |
16 | #[derive(Debug, thiserror::Error, Deserialize, Serialize)] | |
16 | #[derive(Debug, thiserror::Error, Deserialize, Serialize, Clone)] | |
17 | 17 | pub enum UserError {} |
18 | 18 | |
19 | #[derive(Debug, thiserror::Error, Serialize, Deserialize)] | |
19 | #[derive(Debug, thiserror::Error, Serialize, Deserialize, Clone)] | |
20 | 20 | pub enum GetValueError { |
21 | 21 | #[error("invalid object")] |
22 | 22 | InvalidObject, |
23 | 23 | } |
24 | 24 | |
25 | #[derive(Debug, thiserror::Error)] | |
25 | #[derive(Debug, thiserror::Error, Clone)] | |
26 | 26 | #[error("unauthorized")] |
27 | 27 | pub struct UnauthorizedError; |
28 | 28 |
giterated-models/src/message.rs
@@ -1,8 +1,8 @@ | ||
1 | 1 | use serde::Serialize; |
2 | 2 | |
3 | 3 | use crate::{ |
4 | object::{AnyObject, GiteratedObject}, | |
5 | operation::{AnyOperation, GiteratedOperation}, | |
4 | object::{GiteratedObject, NetworkAnyObject}, | |
5 | operation::{GiteratedOperation, NetworkAnyOperation}, | |
6 | 6 | }; |
7 | 7 | use std::fmt::Debug; |
8 | 8 | |
@@ -42,7 +42,7 @@ mod string { | ||
42 | 42 | } |
43 | 43 | } |
44 | 44 | |
45 | impl GiteratedMessage<AnyObject, AnyOperation> { | |
45 | impl GiteratedMessage<NetworkAnyObject, NetworkAnyOperation> { | |
46 | 46 | pub fn try_into<O: GiteratedObject, V: GiteratedOperation<O>>( |
47 | 47 | &self, |
48 | 48 | ) -> Result<GiteratedMessage<O, V>, ()> { |
giterated-models/src/object.rs
@@ -10,8 +10,8 @@ use crate::{ | ||
10 | 10 | error::{GetValueError, OperationError}, |
11 | 11 | object_backend::ObjectBackend, |
12 | 12 | operation::GiteratedOperation, |
13 | settings::{AnySetting, GetSetting, GetSettingError, SetSetting, SetSettingError, Setting}, | |
14 | value::{GetValueTyped, GiteratedObjectValue}, | |
13 | settings::{GetSetting, GetSettingError, SetSetting, SetSettingError, Setting}, | |
14 | value::{GetValue, GiteratedObjectValue}, | |
15 | 15 | }; |
16 | 16 | |
17 | 17 | mod operations; |
@@ -75,15 +75,15 @@ impl< | ||
75 | 75 | ) -> Result<V, OperationError<GetValueError>> { |
76 | 76 | let result = self |
77 | 77 | .request( |
78 | GetValueTyped::<V> { | |
78 | GetValue { | |
79 | 79 | value_name: V::value_name().to_string(), |
80 | ty: Default::default(), | |
81 | 80 | }, |
82 | 81 | operation_state, |
83 | 82 | ) |
84 | .await; | |
83 | .await | |
84 | .unwrap(); | |
85 | 85 | |
86 | Ok(result?) | |
86 | Ok(serde_json::from_value(result).unwrap()) | |
87 | 87 | } |
88 | 88 | |
89 | 89 | pub async fn get_setting<S: Setting + Send + Clone + Debug>( |
@@ -108,7 +108,7 @@ impl< | ||
108 | 108 | self.request( |
109 | 109 | SetSetting { |
110 | 110 | setting_name: S::name().to_string(), |
111 | value: AnySetting(serde_json::to_value(setting).unwrap()), | |
111 | value: serde_json::to_value(setting).unwrap(), | |
112 | 112 | }, |
113 | 113 | operation_state, |
114 | 114 | ) |
@@ -119,7 +119,11 @@ impl< | ||
119 | 119 | &mut self, |
120 | 120 | request: R, |
121 | 121 | operation_state: &I, |
122 | ) -> Result<R::Success, OperationError<R::Failure>> { | |
122 | ) -> Result<R::Success, OperationError<R::Failure>> | |
123 | where | |
124 | R::Success: Clone, | |
125 | R::Failure: Clone, | |
126 | { | |
123 | 127 | self.backend |
124 | 128 | .object_operation( |
125 | 129 | self.inner.clone(), |
giterated-models/src/object/operations.rs
@@ -9,7 +9,7 @@ use super::GiteratedObject; | ||
9 | 9 | #[derive(Debug, Serialize, Deserialize, Clone)] |
10 | 10 | pub struct ObjectRequest(pub String); |
11 | 11 | |
12 | #[derive(Serialize, Deserialize)] | |
12 | #[derive(Serialize, Deserialize, Clone)] | |
13 | 13 | pub struct ObjectResponse(pub String); |
14 | 14 | |
15 | 15 | impl GiteratedOperation<Instance> for ObjectRequest { |
@@ -18,7 +18,7 @@ impl GiteratedOperation<Instance> for ObjectRequest { | ||
18 | 18 | type Failure = ObjectRequestError; |
19 | 19 | } |
20 | 20 | |
21 | #[derive(Debug, thiserror::Error, Serialize, Deserialize)] | |
21 | #[derive(Debug, Clone, thiserror::Error, Serialize, Deserialize)] | |
22 | 22 | pub enum ObjectRequestError { |
23 | 23 | #[error("error decoding the object")] |
24 | 24 | Deserialization(String), |
@@ -27,9 +27,9 @@ pub enum ObjectRequestError { | ||
27 | 27 | #[derive(Clone, Debug, Serialize, Deserialize)] |
28 | 28 | #[serde(transparent)] |
29 | 29 | #[repr(transparent)] |
30 | pub struct AnyObject(pub String); | |
30 | pub struct NetworkAnyObject(pub String); | |
31 | 31 | |
32 | impl GiteratedObject for AnyObject { | |
32 | impl GiteratedObject for NetworkAnyObject { | |
33 | 33 | fn object_name() -> &'static str { |
34 | 34 | "any" |
35 | 35 | } |
@@ -39,13 +39,13 @@ impl GiteratedObject for AnyObject { | ||
39 | 39 | } |
40 | 40 | } |
41 | 41 | |
42 | impl Display for AnyObject { | |
42 | impl Display for NetworkAnyObject { | |
43 | 43 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
44 | 44 | f.write_str(&self.0) |
45 | 45 | } |
46 | 46 | } |
47 | 47 | |
48 | impl FromStr for AnyObject { | |
48 | impl FromStr for NetworkAnyObject { | |
49 | 49 | type Err = Infallible; |
50 | 50 | |
51 | 51 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
giterated-models/src/object_backend.rs
@@ -17,7 +17,9 @@ pub trait ObjectBackend<S: Clone + Send + Sync>: Sized + Clone + Send { | ||
17 | 17 | ) -> Result<D::Success, OperationError<D::Failure>> |
18 | 18 | where |
19 | 19 | O: GiteratedObject + Debug + 'static, |
20 | D: GiteratedOperation<O> + Debug + 'static; | |
20 | D: GiteratedOperation<O> + Debug + 'static, | |
21 | D::Success: Clone, | |
22 | D::Failure: Clone; | |
21 | 23 | |
22 | 24 | async fn get_object<O: GiteratedObject + Debug + 'static>( |
23 | 25 | &self, |
giterated-models/src/operation.rs
@@ -18,9 +18,9 @@ pub trait GiteratedOperation<O: GiteratedObject>: | ||
18 | 18 | #[derive(Clone, Debug, Serialize, Deserialize)] |
19 | 19 | #[serde(transparent)] |
20 | 20 | #[repr(transparent)] |
21 | pub struct AnyOperation(pub Vec<u8>); | |
21 | pub struct NetworkAnyOperation(pub Vec<u8>); | |
22 | 22 | |
23 | impl<O: GiteratedObject> GiteratedOperation<O> for AnyOperation { | |
23 | impl<O: GiteratedObject> GiteratedOperation<O> for NetworkAnyOperation { | |
24 | 24 | type Success = Vec<u8>; |
25 | 25 | |
26 | 26 | type Failure = Vec<u8>; |
giterated-models/src/settings/mod.rs
@@ -1,18 +1,13 @@ | ||
1 | 1 | mod operations; |
2 | 2 | |
3 | use std::{any::Any, sync::Arc}; | |
4 | ||
3 | 5 | pub use operations::*; |
4 | use serde::{de::DeserializeOwned, Deserialize, Serialize}; | |
5 | use serde_json::Value; | |
6 | use serde::{de::DeserializeOwned, Serialize}; | |
6 | 7 | |
7 | 8 | pub trait Setting: Serialize + DeserializeOwned + Send + Sync { |
8 | 9 | fn name() -> &'static str; |
9 | 10 | } |
10 | 11 | |
11 | #[derive(Debug, Clone, Serialize, Deserialize)] | |
12 | pub struct AnySetting(pub Value); | |
13 | ||
14 | impl Setting for AnySetting { | |
15 | fn name() -> &'static str { | |
16 | "any" | |
17 | } | |
18 | } | |
12 | #[derive(Debug, Clone)] | |
13 | pub struct AnySetting(pub Arc<dyn Any + Send + Sync>); |
giterated-models/src/settings/operations.rs
@@ -6,8 +6,6 @@ use thiserror::Error; | ||
6 | 6 | |
7 | 7 | use crate::{object::GiteratedObject, operation::GiteratedOperation}; |
8 | 8 | |
9 | use super::AnySetting; | |
10 | ||
11 | 9 | #[derive(Serialize, Deserialize, Debug, Clone)] |
12 | 10 | pub struct GetSetting { |
13 | 11 | pub setting_name: String, |
@@ -23,12 +21,12 @@ impl<O: GiteratedObject> GiteratedOperation<O> for GetSetting { | ||
23 | 21 | type Failure = GetSettingError; |
24 | 22 | } |
25 | 23 | |
26 | #[derive(Error, Debug, Serialize, Deserialize)] | |
24 | #[derive(Error, Debug, Serialize, Deserialize, Clone)] | |
27 | 25 | pub enum GetSettingError {} |
28 | 26 | #[derive(Serialize, Deserialize, Debug, Clone)] |
29 | 27 | pub struct SetSetting { |
30 | 28 | pub setting_name: String, |
31 | pub value: AnySetting, | |
29 | pub value: Value, | |
32 | 30 | } |
33 | 31 | |
34 | 32 | impl<O: GiteratedObject> GiteratedOperation<O> for SetSetting { |
@@ -41,5 +39,5 @@ impl<O: GiteratedObject> GiteratedOperation<O> for SetSetting { | ||
41 | 39 | type Failure = SetSettingError; |
42 | 40 | } |
43 | 41 | |
44 | #[derive(Error, Debug, Serialize, Deserialize)] | |
42 | #[derive(Error, Debug, Serialize, Deserialize, Clone)] | |
45 | 43 | pub enum SetSettingError {} |
giterated-models/src/value.rs
@@ -26,7 +26,6 @@ impl<O: GiteratedObject + Send> GiteratedOperation<O> for GetValue { | ||
26 | 26 | |
27 | 27 | #[derive(Serialize, Deserialize, Debug, Clone)] |
28 | 28 | pub struct GetValueTyped<V: GiteratedObjectValue> { |
29 | pub value_name: String, | |
30 | 29 | pub ty: PhantomData<V>, |
31 | 30 | } |
32 | 31 |
giterated-stack/src/handler/handler_impl.rs
@@ -0,0 +1,272 @@ | ||
1 | use futures_util::Future; | |
2 | use giterated_models::error::OperationError; | |
3 | ||
4 | use crate::{HandlerResolvable, IntoGiteratedHandler}; | |
5 | ||
6 | #[async_trait::async_trait(?Send)] | |
7 | impl<R1, S, OS, Success, Failure, H, Fut> | |
8 | IntoGiteratedHandler<(R1,), (), S, OS, Result<Success, OperationError<Failure>>> for H | |
9 | where | |
10 | H: FnMut(R1, S, OS) -> Fut + Clone, | |
11 | Fut: Future<Output = Result<Success, OperationError<Failure>>> + 'static, | |
12 | Success: 'static, | |
13 | Failure: 'static, | |
14 | R1: 'static, | |
15 | S: 'static, | |
16 | OS: 'static, | |
17 | { | |
18 | type Future = Fut; | |
19 | ||
20 | async fn handle( | |
21 | &self, | |
22 | parameters: (R1,), | |
23 | state: S, | |
24 | operation_state: OS, | |
25 | ) -> Result<Success, OperationError<Failure>> { | |
26 | let (r1,) = parameters; | |
27 | (self.clone())(r1, state, operation_state).await | |
28 | } | |
29 | } | |
30 | ||
31 | #[async_trait::async_trait(?Send)] | |
32 | impl<R1, A1, S, OS, Success, Failure, H, Fut> | |
33 | IntoGiteratedHandler<(R1,), (A1,), S, OS, Result<Success, OperationError<Failure>>> for H | |
34 | where | |
35 | H: FnMut(R1, S, OS, A1) -> Fut + Clone, | |
36 | Fut: Future<Output = Result<Success, OperationError<Failure>>> + 'static, | |
37 | Success: 'static, | |
38 | Failure: 'static, | |
39 | R1: 'static, | |
40 | S: 'static, | |
41 | OS: 'static, | |
42 | A1: HandlerResolvable<(R1,), OS>, | |
43 | A1::Error: Into<anyhow::Error>, | |
44 | { | |
45 | type Future = Fut; | |
46 | ||
47 | async fn handle( | |
48 | &self, | |
49 | parameters: (R1,), | |
50 | state: S, | |
51 | operation_state: OS, | |
52 | ) -> Result<Success, OperationError<Failure>> { | |
53 | let a1 = A1::from_handler_state(¶meters, &operation_state) | |
54 | .await | |
55 | .map_err(|e| OperationError::Internal(e.into()))?; | |
56 | let (r1,) = parameters; | |
57 | (self.clone())(r1, state, operation_state, a1).await | |
58 | } | |
59 | } | |
60 | ||
61 | #[async_trait::async_trait(?Send)] | |
62 | impl<R1, A1, A2, S, OS, Success, Failure, H, Fut> | |
63 | IntoGiteratedHandler<(R1,), (A1, A2), S, OS, Result<Success, OperationError<Failure>>> for H | |
64 | where | |
65 | H: FnMut(R1, S, OS, A1, A2) -> Fut + Clone, | |
66 | Fut: Future<Output = Result<Success, OperationError<Failure>>> + 'static, | |
67 | Success: 'static, | |
68 | Failure: 'static, | |
69 | R1: 'static, | |
70 | S: 'static, | |
71 | OS: 'static, | |
72 | A1: HandlerResolvable<(R1,), OS>, | |
73 | A1::Error: Into<anyhow::Error>, | |
74 | A2: HandlerResolvable<(R1,), OS>, | |
75 | A2::Error: Into<anyhow::Error>, | |
76 | { | |
77 | type Future = Fut; | |
78 | ||
79 | async fn handle( | |
80 | &self, | |
81 | parameters: (R1,), | |
82 | state: S, | |
83 | operation_state: OS, | |
84 | ) -> Result<Success, OperationError<Failure>> { | |
85 | let a1 = A1::from_handler_state(¶meters, &operation_state) | |
86 | .await | |
87 | .map_err(|e| OperationError::Internal(e.into()))?; | |
88 | let a2 = A2::from_handler_state(¶meters, &operation_state) | |
89 | .await | |
90 | .map_err(|e| OperationError::Internal(e.into()))?; | |
91 | let (r1,) = parameters; | |
92 | (self.clone())(r1, state, operation_state, a1, a2).await | |
93 | } | |
94 | } | |
95 | ||
96 | #[async_trait::async_trait(?Send)] | |
97 | impl<R1, A1, A2, A3, S, OS, Success, Failure, H, Fut> | |
98 | IntoGiteratedHandler<(R1,), (A1, A2, A3), S, OS, Result<Success, OperationError<Failure>>> for H | |
99 | where | |
100 | H: FnMut(R1, S, OS, A1, A2, A3) -> Fut + Clone, | |
101 | Fut: Future<Output = Result<Success, OperationError<Failure>>> + 'static, | |
102 | Success: 'static, | |
103 | Failure: 'static, | |
104 | R1: 'static, | |
105 | S: 'static, | |
106 | OS: 'static, | |
107 | A1: HandlerResolvable<(R1,), OS>, | |
108 | A1::Error: Into<anyhow::Error>, | |
109 | A2: HandlerResolvable<(R1,), OS>, | |
110 | A2::Error: Into<anyhow::Error>, | |
111 | A3: HandlerResolvable<(R1,), OS>, | |
112 | A3::Error: Into<anyhow::Error>, | |
113 | { | |
114 | type Future = Fut; | |
115 | ||
116 | async fn handle( | |
117 | &self, | |
118 | parameters: (R1,), | |
119 | state: S, | |
120 | operation_state: OS, | |
121 | ) -> Result<Success, OperationError<Failure>> { | |
122 | let a1 = A1::from_handler_state(¶meters, &operation_state) | |
123 | .await | |
124 | .map_err(|e| OperationError::Internal(e.into()))?; | |
125 | let a2 = A2::from_handler_state(¶meters, &operation_state) | |
126 | .await | |
127 | .map_err(|e| OperationError::Internal(e.into()))?; | |
128 | let a3 = A3::from_handler_state(¶meters, &operation_state) | |
129 | .await | |
130 | .map_err(|e| OperationError::Internal(e.into()))?; | |
131 | let (r1,) = parameters; | |
132 | (self.clone())(r1, state, operation_state, a1, a2, a3).await | |
133 | } | |
134 | } | |
135 | ||
136 | #[async_trait::async_trait(?Send)] | |
137 | impl<R1, R2, S, OS, Success, Failure, H, Fut> | |
138 | IntoGiteratedHandler<(R1, R2), (), S, OS, Result<Success, OperationError<Failure>>> for H | |
139 | where | |
140 | H: FnMut(R1, R2, S, OS) -> Fut + Clone, | |
141 | Fut: Future<Output = Result<Success, OperationError<Failure>>> + 'static, | |
142 | Success: 'static, | |
143 | Failure: 'static, | |
144 | R1: 'static, | |
145 | R2: 'static, | |
146 | S: 'static, | |
147 | OS: 'static, | |
148 | { | |
149 | type Future = Fut; | |
150 | ||
151 | async fn handle( | |
152 | &self, | |
153 | parameters: (R1, R2), | |
154 | state: S, | |
155 | operation_state: OS, | |
156 | ) -> Result<Success, OperationError<Failure>> { | |
157 | let (r1, r2) = parameters; | |
158 | (self.clone())(r1, r2, state, operation_state).await | |
159 | } | |
160 | } | |
161 | ||
162 | #[async_trait::async_trait(?Send)] | |
163 | impl<R1, R2, A1, S, OS, Success, Failure, H, Fut> | |
164 | IntoGiteratedHandler<(R1, R2), (A1,), S, OS, Result<Success, OperationError<Failure>>> for H | |
165 | where | |
166 | H: FnMut(R1, R2, S, OS, A1) -> Fut + Clone, | |
167 | Fut: Future<Output = Result<Success, OperationError<Failure>>> + 'static, | |
168 | Success: 'static, | |
169 | Failure: 'static, | |
170 | R1: 'static, | |
171 | R2: 'static, | |
172 | S: 'static, | |
173 | OS: 'static, | |
174 | A1: HandlerResolvable<(R1, R2), OS>, | |
175 | A1::Error: Into<anyhow::Error>, | |
176 | { | |
177 | type Future = Fut; | |
178 | ||
179 | async fn handle( | |
180 | &self, | |
181 | parameters: (R1, R2), | |
182 | state: S, | |
183 | operation_state: OS, | |
184 | ) -> Result<Success, OperationError<Failure>> { | |
185 | let a1 = A1::from_handler_state(¶meters, &operation_state) | |
186 | .await | |
187 | .map_err(|e| OperationError::Internal(e.into()))?; | |
188 | ||
189 | let (r1, r2) = parameters; | |
190 | (self.clone())(r1, r2, state, operation_state, a1).await | |
191 | } | |
192 | } | |
193 | ||
194 | #[async_trait::async_trait(?Send)] | |
195 | impl<R1, R2, A1, A2, S, OS, Success, Failure, H, Fut> | |
196 | IntoGiteratedHandler<(R1, R2), (A1, A2), S, OS, Result<Success, OperationError<Failure>>> for H | |
197 | where | |
198 | H: FnMut(R1, R2, S, OS, A1, A2) -> Fut + Clone, | |
199 | Fut: Future<Output = Result<Success, OperationError<Failure>>> + 'static, | |
200 | Success: 'static, | |
201 | Failure: 'static, | |
202 | R1: 'static, | |
203 | R2: 'static, | |
204 | S: 'static, | |
205 | OS: 'static, | |
206 | A1: HandlerResolvable<(R1, R2), OS>, | |
207 | A1::Error: Into<anyhow::Error>, | |
208 | A2: HandlerResolvable<(R1, R2), OS>, | |
209 | A2::Error: Into<anyhow::Error>, | |
210 | { | |
211 | type Future = Fut; | |
212 | ||
213 | async fn handle( | |
214 | &self, | |
215 | parameters: (R1, R2), | |
216 | state: S, | |
217 | operation_state: OS, | |
218 | ) -> Result<Success, OperationError<Failure>> { | |
219 | let a1 = A1::from_handler_state(¶meters, &operation_state) | |
220 | .await | |
221 | .map_err(|e| OperationError::Internal(e.into()))?; | |
222 | let a2 = A2::from_handler_state(¶meters, &operation_state) | |
223 | .await | |
224 | .map_err(|e| OperationError::Internal(e.into()))?; | |
225 | ||
226 | let (r1, r2) = parameters; | |
227 | (self.clone())(r1, r2, state, operation_state, a1, a2).await | |
228 | } | |
229 | } | |
230 | ||
231 | #[async_trait::async_trait(?Send)] | |
232 | impl<R1, R2, A1, A2, A3, S, OS, Success, Failure, H, Fut> | |
233 | IntoGiteratedHandler<(R1, R2), (A1, A2, A3), S, OS, Result<Success, OperationError<Failure>>> | |
234 | for H | |
235 | where | |
236 | H: FnMut(R1, R2, S, OS, A1, A2, A3) -> Fut + Clone, | |
237 | Fut: Future<Output = Result<Success, OperationError<Failure>>> + 'static, | |
238 | Success: 'static, | |
239 | Failure: 'static, | |
240 | R1: 'static, | |
241 | R2: 'static, | |
242 | S: 'static, | |
243 | OS: 'static, | |
244 | A1: HandlerResolvable<(R1, R2), OS>, | |
245 | A1::Error: Into<anyhow::Error>, | |
246 | A2: HandlerResolvable<(R1, R2), OS>, | |
247 | A2::Error: Into<anyhow::Error>, | |
248 | A3: HandlerResolvable<(R1, R2), OS>, | |
249 | A3::Error: Into<anyhow::Error>, | |
250 | { | |
251 | type Future = Fut; | |
252 | ||
253 | async fn handle( | |
254 | &self, | |
255 | parameters: (R1, R2), | |
256 | state: S, | |
257 | operation_state: OS, | |
258 | ) -> Result<Success, OperationError<Failure>> { | |
259 | let a1 = A1::from_handler_state(¶meters, &operation_state) | |
260 | .await | |
261 | .map_err(|e| OperationError::Internal(e.into()))?; | |
262 | let a2 = A2::from_handler_state(¶meters, &operation_state) | |
263 | .await | |
264 | .map_err(|e| OperationError::Internal(e.into()))?; | |
265 | let a3 = A3::from_handler_state(¶meters, &operation_state) | |
266 | .await | |
267 | .map_err(|e| OperationError::Internal(e.into()))?; | |
268 | ||
269 | let (r1, r2) = parameters; | |
270 | (self.clone())(r1, r2, state, operation_state, a1, a2, a3).await | |
271 | } | |
272 | } |
giterated-stack/src/handler/mod.rs
@@ -0,0 +1,239 @@ | ||
1 | use std::{any::Any, sync::Arc}; | |
2 | pub mod handler_impl; | |
3 | use futures_util::{future::LocalBoxFuture, Future, FutureExt}; | |
4 | use giterated_models::error::OperationError; | |
5 | ||
6 | use crate::{ | |
7 | AuthenticatedInstance, AuthenticatedUser, GiteratedStack, MissingValue, StackOperationState, | |
8 | }; | |
9 | ||
10 | #[async_trait::async_trait(?Send)] | |
11 | pub trait IntoGiteratedHandler<Params, AdditionalParams, State, OState, Output> | |
12 | where | |
13 | // Output cannot have non-static references | |
14 | Output: 'static, | |
15 | { | |
16 | type Future: Future<Output = Output>; | |
17 | ||
18 | async fn handle(&self, parameters: Params, state: State, operation_state: OState) -> Output; | |
19 | } | |
20 | ||
21 | pub struct HandlerTree<Kind> { | |
22 | elements: Vec<Kind>, | |
23 | } | |
24 | ||
25 | impl<Kind> Default for HandlerTree<Kind> { | |
26 | fn default() -> Self { | |
27 | Self { | |
28 | elements: Default::default(), | |
29 | } | |
30 | } | |
31 | } | |
32 | ||
33 | impl<'fut: 'o + 'p, 'p, 'o, P, O, E> HandlerTree<HandlerWrapper<P, O, E>> | |
34 | where | |
35 | P: Clone, | |
36 | { | |
37 | pub fn push(&mut self, handler: HandlerWrapper<P, O, E>) { | |
38 | self.elements.push(handler); | |
39 | } | |
40 | pub async fn handle( | |
41 | &self, | |
42 | parameters: P, | |
43 | operation_state: StackOperationState, | |
44 | ) -> Result<O, OperationError<E>> { | |
45 | for handler in self.elements.iter() { | |
46 | match handler | |
47 | .handle(parameters.clone(), operation_state.clone()) | |
48 | .await | |
49 | { | |
50 | Ok(handled) => return Ok(handled), | |
51 | Err(err) => match err { | |
52 | OperationError::Internal(err) => return Err(OperationError::Internal(err)), | |
53 | OperationError::Operation(err) => return Err(OperationError::Operation(err)), | |
54 | OperationError::Unhandled => continue, | |
55 | }, | |
56 | } | |
57 | } | |
58 | ||
59 | Err(OperationError::Unhandled) | |
60 | } | |
61 | } | |
62 | ||
63 | pub struct HandlerWrapper<P, O, E> { | |
64 | func: Arc< | |
65 | dyn Fn( | |
66 | P, | |
67 | Arc<dyn Any + Send + Sync>, | |
68 | StackOperationState, | |
69 | ) -> LocalBoxFuture<'static, Result<O, OperationError<E>>> | |
70 | + Send | |
71 | + Sync, | |
72 | >, | |
73 | state: Arc<dyn Any + Send + Sync>, | |
74 | } | |
75 | ||
76 | impl<P, O, E> HandlerWrapper<P, O, E> { | |
77 | pub fn new<S, F, A>(state: S, handler: F) -> Self | |
78 | where | |
79 | F: IntoGiteratedHandler<P, A, S, StackOperationState, Result<O, OperationError<E>>> | |
80 | + Send | |
81 | + Sync, | |
82 | S: Send + Sync + Clone + 'static, | |
83 | E: 'static, | |
84 | P: 'static + Clone, | |
85 | F: 'static, | |
86 | O: 'static, | |
87 | { | |
88 | let state = Arc::new(state); | |
89 | ||
90 | let handler_func = Arc::new(handler); | |
91 | let state_two = state.clone(); | |
92 | HandlerWrapper { | |
93 | func: Arc::new( | |
94 | move |args: P, | |
95 | state: Arc<dyn Any + Send + Sync>, | |
96 | operation_state: StackOperationState| { | |
97 | let handler = handler_func.clone(); | |
98 | let operation_state = operation_state.clone(); | |
99 | let state = state.downcast_ref::<S>().unwrap(); | |
100 | let state = state.clone(); | |
101 | async move { | |
102 | let handler = handler.clone(); | |
103 | let operation_state = operation_state; | |
104 | handler.handle(args, state, operation_state).await | |
105 | } | |
106 | .boxed_local() | |
107 | }, | |
108 | ), | |
109 | state: state_two, | |
110 | } | |
111 | } | |
112 | ||
113 | pub async fn handle( | |
114 | &self, | |
115 | required: P, | |
116 | operation_state: StackOperationState, | |
117 | ) -> Result<O, OperationError<E>> { | |
118 | (self.func)(required, self.state.clone(), operation_state).await | |
119 | } | |
120 | ||
121 | pub fn map<F, N, R>(self, predicate: F) -> HandlerWrapper<N, O, R> | |
122 | where | |
123 | F: Fn(&N, &StackOperationState) -> Result<P, OperationError<R>> + Clone + Send + Sync, | |
124 | R: std::fmt::Debug + 'static, | |
125 | E: Into<OperationError<R>> + 'static, | |
126 | F: 'static, | |
127 | N: 'static, | |
128 | P: 'static, | |
129 | O: 'static, | |
130 | { | |
131 | let func = Arc::new(self.func); | |
132 | let predicate = Arc::new(predicate); | |
133 | HandlerWrapper { | |
134 | func: Arc::new( | |
135 | move |args: N, | |
136 | state: Arc<dyn Any + Send + Sync>, | |
137 | operation_state: StackOperationState| { | |
138 | let predicate_output = predicate(&args, &operation_state); | |
139 | let func = func.clone(); | |
140 | let operation_state: StackOperationState = operation_state.clone(); | |
141 | async move { | |
142 | let predicate_output = predicate_output?; | |
143 | let operation_state = operation_state; | |
144 | match (func)(predicate_output, state, operation_state).await { | |
145 | Ok(success) => Ok(success), | |
146 | Err(_) => todo!(), | |
147 | } | |
148 | } | |
149 | .boxed_local() | |
150 | }, | |
151 | ), | |
152 | state: self.state, | |
153 | } | |
154 | } | |
155 | ||
156 | pub fn map_return<F, NR, NE>(self, predicate: F) -> HandlerWrapper<P, NR, NE> | |
157 | where | |
158 | F: Fn(Result<O, OperationError<E>>, &StackOperationState) -> Result<NR, OperationError<NE>> | |
159 | + Clone | |
160 | + Send | |
161 | + Sync, | |
162 | O: 'static, | |
163 | F: 'static, | |
164 | E: 'static, | |
165 | P: 'static, | |
166 | { | |
167 | let predicate = Arc::new(predicate); | |
168 | let func = self.func; | |
169 | HandlerWrapper { | |
170 | func: Arc::new( | |
171 | move |args: P, | |
172 | state: Arc<dyn Any + Send + Sync>, | |
173 | operation_state: StackOperationState| { | |
174 | let clone = predicate.clone(); | |
175 | let func = func.clone(); | |
176 | let _statoperation_statee = operation_state.clone(); | |
177 | ||
178 | async move { | |
179 | let func = func.clone(); | |
180 | let clone = clone; | |
181 | let operation_state = operation_state; | |
182 | clone( | |
183 | (func)(args, state, operation_state.clone()).await, | |
184 | &operation_state, | |
185 | ) | |
186 | } | |
187 | .boxed_local() | |
188 | }, | |
189 | ), | |
190 | state: self.state, | |
191 | } | |
192 | } | |
193 | } | |
194 | ||
195 | #[async_trait::async_trait(?Send)] | |
196 | pub trait HandlerResolvable<RequiredParameters, OperationState>: Sized { | |
197 | type Error; | |
198 | ||
199 | async fn from_handler_state( | |
200 | required_parameters: &RequiredParameters, | |
201 | operation_state: &OperationState, | |
202 | ) -> Result<Self, Self::Error>; | |
203 | } | |
204 | ||
205 | #[async_trait::async_trait(?Send)] | |
206 | impl<R> HandlerResolvable<R, StackOperationState> for Arc<GiteratedStack> { | |
207 | type Error = MissingValue; | |
208 | ||
209 | async fn from_handler_state( | |
210 | _required_parameters: &R, | |
211 | operation_state: &StackOperationState, | |
212 | ) -> Result<Self, Self::Error> { | |
213 | Ok(operation_state.runtime.clone()) | |
214 | } | |
215 | } | |
216 | ||
217 | #[async_trait::async_trait(?Send)] | |
218 | impl<R> HandlerResolvable<R, StackOperationState> for AuthenticatedUser { | |
219 | type Error = MissingValue; | |
220 | ||
221 | async fn from_handler_state( | |
222 | _required_parameters: &R, | |
223 | operation_state: &StackOperationState, | |
224 | ) -> Result<Self, Self::Error> { | |
225 | operation_state.user.clone().ok_or_else(|| MissingValue) | |
226 | } | |
227 | } | |
228 | ||
229 | #[async_trait::async_trait(?Send)] | |
230 | impl<R> HandlerResolvable<R, StackOperationState> for AuthenticatedInstance { | |
231 | type Error = MissingValue; | |
232 | ||
233 | async fn from_handler_state( | |
234 | _required_parameters: &R, | |
235 | operation_state: &StackOperationState, | |
236 | ) -> Result<Self, Self::Error> { | |
237 | operation_state.instance.clone().ok_or_else(|| MissingValue) | |
238 | } | |
239 | } |
giterated-stack/src/lib.rs
@@ -1,18 +1,22 @@ | ||
1 | 1 | mod handler; |
2 | pub use handler::*; | |
2 | 3 | mod meta; |
3 | pub mod provider; | |
4 | pub use handler::{GiteratedStack, GiteratedStackState, *}; | |
5 | 4 | pub use meta::*; |
5 | pub mod provider; | |
6 | mod stack; | |
7 | pub use stack::*; | |
8 | mod substack; | |
6 | 9 | use serde::{de::DeserializeOwned, Deserialize, Serialize}; |
10 | pub use stack::*; | |
11 | pub use substack::*; | |
7 | 12 | pub mod state; |
8 | 13 | pub mod update; |
9 | 14 | |
10 | use std::{any::Any, convert::Infallible, future::Future, ops::Deref, pin::Pin, sync::Arc}; | |
15 | use std::{any::Any, convert::Infallible, ops::Deref, sync::Arc}; | |
11 | 16 | |
12 | 17 | use core::fmt::Debug; |
13 | use futures_util::FutureExt; | |
14 | 18 | use giterated_models::{ |
15 | error::{ExtractorError, IntoInternalError, OperationError, UnauthorizedError}, | |
19 | error::{ExtractorError, UnauthorizedError}, | |
16 | 20 | instance::{ |
17 | 21 | AuthenticationTokenRequest, Instance, RegisterAccountRequest, RepositoryCreateRequest, |
18 | 22 | }, |
@@ -26,335 +30,52 @@ use giterated_models::{ | ||
26 | 30 | }; |
27 | 31 | |
28 | 32 | #[derive(Clone, Debug, Hash, Eq, PartialEq)] |
29 | struct ObjectOperationPair { | |
30 | pub object_name: String, | |
31 | pub operation_name: String, | |
33 | pub struct ObjectOperationPair<'a> { | |
34 | pub object_name: &'a str, | |
35 | pub operation_name: &'a str, | |
32 | 36 | } |
33 | 37 | |
34 | impl ObjectOperationPair { | |
38 | impl ObjectOperationPair<'static> { | |
35 | 39 | #[allow(unused)] |
36 | 40 | pub fn from_types<O: GiteratedObject, D: GiteratedOperation<O>>() -> Self { |
37 | 41 | Self { |
38 | object_name: O::object_name().to_string(), | |
39 | operation_name: D::operation_name().to_string(), | |
42 | object_name: O::object_name(), | |
43 | operation_name: D::operation_name(), | |
40 | 44 | } |
41 | 45 | } |
42 | 46 | } |
43 | 47 | |
44 | 48 | #[derive(Clone, Debug, Hash, Eq, PartialEq)] |
45 | pub struct ObjectValuePair { | |
46 | pub object_kind: String, | |
47 | pub value_kind: String, | |
49 | pub struct ObjectValuePair<'a> { | |
50 | pub object_kind: &'a str, | |
51 | pub value_kind: &'a str, | |
48 | 52 | } |
49 | 53 | |
50 | impl ObjectValuePair { | |
51 | pub fn from_types<O: GiteratedObject, D: GiteratedObjectValue<Object = O>>() -> Self { | |
54 | impl ObjectValuePair<'static> { | |
55 | pub fn from_types<O: GiteratedObject, V: GiteratedObjectValue<Object = O>>() -> Self { | |
52 | 56 | Self { |
53 | object_kind: O::object_name().to_string(), | |
54 | value_kind: D::value_name().to_string(), | |
57 | object_kind: O::object_name(), | |
58 | value_kind: V::value_name(), | |
55 | 59 | } |
56 | 60 | } |
57 | 61 | } |
58 | 62 | |
59 | 63 | #[derive(Clone, Debug, Hash, Eq, PartialEq)] |
60 | pub struct ObjectSettingPair { | |
61 | pub object_kind: String, | |
62 | pub setting_name: String, | |
64 | pub struct ObjectSettingPair<'a> { | |
65 | pub object_kind: &'a str, | |
66 | pub setting_name: &'a str, | |
63 | 67 | } |
64 | 68 | |
65 | impl ObjectSettingPair { | |
69 | impl ObjectSettingPair<'static> { | |
66 | 70 | pub fn from_types<O: GiteratedObject, S: Setting>() -> Self { |
67 | 71 | Self { |
68 | object_kind: O::object_name().to_string(), | |
69 | setting_name: S::name().to_string(), | |
72 | object_kind: O::object_name(), | |
73 | setting_name: S::name(), | |
70 | 74 | } |
71 | 75 | } |
72 | 76 | } |
73 | 77 | |
74 | 78 | #[async_trait::async_trait(?Send)] |
75 | pub trait GiteratedOperationHandler< | |
76 | L, | |
77 | O: GiteratedObject, | |
78 | D: GiteratedOperation<O>, | |
79 | S: Send + Sync + Clone, | |
80 | > | |
81 | { | |
82 | fn operation_name(&self) -> &str; | |
83 | fn object_name(&self) -> &str; | |
84 | ||
85 | async fn handle( | |
86 | &self, | |
87 | object: &O, | |
88 | operation: D, | |
89 | state: S, | |
90 | operation_state: &StackOperationState, | |
91 | ) -> Result<D::Success, OperationError<D::Failure>>; | |
92 | } | |
93 | ||
94 | #[async_trait::async_trait(?Send)] | |
95 | impl<O, D, F, S> GiteratedOperationHandler<(), O, D, S> for F | |
96 | where | |
97 | F: FnMut( | |
98 | &O, | |
99 | D, | |
100 | S, | |
101 | ) | |
102 | -> Pin<Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>>>> | |
103 | + Send | |
104 | + Sync | |
105 | + Clone, | |
106 | O: GiteratedObject + Send + Sync, | |
107 | D: GiteratedOperation<O> + 'static, | |
108 | <D as GiteratedOperation<O>>::Failure: Send, | |
109 | S: Send + Sync + Clone + 'static, | |
110 | { | |
111 | fn operation_name(&self) -> &str { | |
112 | D::operation_name() | |
113 | } | |
114 | ||
115 | fn object_name(&self) -> &str { | |
116 | O::object_name() | |
117 | } | |
118 | ||
119 | async fn handle( | |
120 | &self, | |
121 | object: &O, | |
122 | operation: D, | |
123 | state: S, | |
124 | _operation_state: &StackOperationState, | |
125 | ) -> Result<D::Success, OperationError<D::Failure>> { | |
126 | self.clone()(object, operation, state).await | |
127 | } | |
128 | } | |
129 | ||
130 | #[async_trait::async_trait(?Send)] | |
131 | impl<O, O1, D, F, S> GiteratedOperationHandler<(O1,), O, D, S> for F | |
132 | where | |
133 | F: FnMut( | |
134 | &O, | |
135 | D, | |
136 | S, | |
137 | O1, | |
138 | ) | |
139 | -> Pin<Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>>>> | |
140 | + Send | |
141 | + Sync | |
142 | + Clone, | |
143 | O: GiteratedObject + Send + Sync, | |
144 | D: GiteratedOperation<O> + 'static + Send + Sync, | |
145 | <D as GiteratedOperation<O>>::Failure: Send, | |
146 | S: Send + Sync + Clone + 'static, | |
147 | O1: FromOperationState<O, D>, | |
148 | ExtractorError<<O1 as FromOperationState<O, D>>::Error>: Into<anyhow::Error>, | |
149 | { | |
150 | fn operation_name(&self) -> &str { | |
151 | D::operation_name() | |
152 | } | |
153 | ||
154 | fn object_name(&self) -> &str { | |
155 | O::object_name() | |
156 | } | |
157 | ||
158 | async fn handle( | |
159 | &self, | |
160 | object: &O, | |
161 | operation: D, | |
162 | state: S, | |
163 | operation_state: &StackOperationState, | |
164 | ) -> Result<D::Success, OperationError<D::Failure>> { | |
165 | let o1 = O1::from_state(object, &operation, operation_state) | |
166 | .await | |
167 | .as_internal_error()?; | |
168 | self.clone()(object, operation, state, o1).await | |
169 | } | |
170 | } | |
171 | ||
172 | #[async_trait::async_trait(?Send)] | |
173 | impl<O, O1, O2, D, F, S> GiteratedOperationHandler<(O1, O2), O, D, S> for F | |
174 | where | |
175 | F: FnMut( | |
176 | &O, | |
177 | D, | |
178 | S, | |
179 | O1, | |
180 | O2, | |
181 | ) | |
182 | -> Pin<Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>>>> | |
183 | + Send | |
184 | + Sync | |
185 | + Clone, | |
186 | O: GiteratedObject + Send + Sync, | |
187 | D: GiteratedOperation<O> + 'static + Send + Sync, | |
188 | <D as GiteratedOperation<O>>::Failure: Send, | |
189 | S: Send + Sync + Clone + 'static, | |
190 | O1: FromOperationState<O, D>, | |
191 | ExtractorError<<O1 as FromOperationState<O, D>>::Error>: Into<anyhow::Error>, | |
192 | O2: FromOperationState<O, D>, | |
193 | ExtractorError<<O2 as FromOperationState<O, D>>::Error>: Into<anyhow::Error>, | |
194 | { | |
195 | fn operation_name(&self) -> &str { | |
196 | D::operation_name() | |
197 | } | |
198 | ||
199 | fn object_name(&self) -> &str { | |
200 | O::object_name() | |
201 | } | |
202 | ||
203 | async fn handle( | |
204 | &self, | |
205 | object: &O, | |
206 | operation: D, | |
207 | state: S, | |
208 | operation_state: &StackOperationState, | |
209 | ) -> Result<D::Success, OperationError<D::Failure>> { | |
210 | let o1 = O1::from_state(object, &operation, operation_state) | |
211 | .await | |
212 | .as_internal_error()?; | |
213 | let o2 = O2::from_state(object, &operation, operation_state) | |
214 | .await | |
215 | .as_internal_error()?; | |
216 | self.clone()(object, operation, state, o1, o2).await | |
217 | } | |
218 | } | |
219 | ||
220 | #[async_trait::async_trait(?Send)] | |
221 | impl<O, O1, O2, O3, D, F, S> GiteratedOperationHandler<(O1, O2, O3), O, D, S> for F | |
222 | where | |
223 | F: FnMut( | |
224 | &O, | |
225 | D, | |
226 | S, | |
227 | O1, | |
228 | O2, | |
229 | O3, | |
230 | ) | |
231 | -> Pin<Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>>>> | |
232 | + Send | |
233 | + Sync | |
234 | + Clone, | |
235 | O: GiteratedObject + Send + Sync, | |
236 | D: GiteratedOperation<O> + 'static + Send + Sync, | |
237 | <D as GiteratedOperation<O>>::Failure: Send, | |
238 | S: Send + Sync + Clone + 'static, | |
239 | O1: FromOperationState<O, D>, | |
240 | ExtractorError<<O1 as FromOperationState<O, D>>::Error>: Into<anyhow::Error>, | |
241 | O2: FromOperationState<O, D>, | |
242 | ExtractorError<<O2 as FromOperationState<O, D>>::Error>: Into<anyhow::Error>, | |
243 | O3: FromOperationState<O, D>, | |
244 | ExtractorError<<O3 as FromOperationState<O, D>>::Error>: Into<anyhow::Error>, | |
245 | { | |
246 | fn operation_name(&self) -> &str { | |
247 | D::operation_name() | |
248 | } | |
249 | ||
250 | fn object_name(&self) -> &str { | |
251 | O::object_name() | |
252 | } | |
253 | ||
254 | async fn handle( | |
255 | &self, | |
256 | object: &O, | |
257 | operation: D, | |
258 | state: S, | |
259 | operation_state: &StackOperationState, | |
260 | ) -> Result<D::Success, OperationError<D::Failure>> { | |
261 | let o1 = O1::from_state(object, &operation, operation_state) | |
262 | .await | |
263 | .as_internal_error()?; | |
264 | let o2 = O2::from_state(object, &operation, operation_state) | |
265 | .await | |
266 | .as_internal_error()?; | |
267 | let o3 = O3::from_state(object, &operation, operation_state) | |
268 | .await | |
269 | .as_internal_error()?; | |
270 | self.clone()(object, operation, state, o1, o2, o3).await | |
271 | } | |
272 | } | |
273 | ||
274 | pub struct OperationWrapper { | |
275 | func: Box< | |
276 | dyn Fn( | |
277 | &(dyn Any + Send + Sync), | |
278 | &(dyn Any + Send + Sync), | |
279 | &(dyn Any + Send + Sync), | |
280 | StackOperationState, | |
281 | ) -> Pin< | |
282 | Box< | |
283 | dyn Future< | |
284 | Output = Result< | |
285 | Box<dyn Any + Send + Sync>, | |
286 | OperationError<Box<dyn Any + Send + Sync>>, | |
287 | >, | |
288 | >, | |
289 | >, | |
290 | > + Send | |
291 | + Sync, | |
292 | >, | |
293 | state: Box<dyn Any + Send + Sync>, | |
294 | } | |
295 | ||
296 | impl OperationWrapper { | |
297 | pub fn new< | |
298 | A, | |
299 | O: GiteratedObject + Send + Sync + 'static, | |
300 | D: GiteratedOperation<O> + 'static + Clone, | |
301 | F: GiteratedOperationHandler<A, O, D, S> + 'static + Send + Sync + Clone, | |
302 | S: GiteratedStackState + 'static, | |
303 | >( | |
304 | handler: F, | |
305 | state: S, | |
306 | ) -> Self | |
307 | where | |
308 | D::Failure: Send + Sync, | |
309 | D::Success: Send + Sync, | |
310 | { | |
311 | Self { | |
312 | func: Box::new(move |object, operation, state, operation_state| { | |
313 | let handler = handler.clone(); | |
314 | let state = state.downcast_ref::<S>().unwrap().clone(); | |
315 | let object: &O = object.downcast_ref().unwrap(); | |
316 | let operation: &D = operation.downcast_ref().unwrap(); | |
317 | let object = object.clone(); | |
318 | let operation = operation.clone(); | |
319 | async move { | |
320 | let result = handler | |
321 | .handle(&object, operation, state, &operation_state) | |
322 | .await; | |
323 | result | |
324 | .map(|success| Box::new(success) as _) | |
325 | .map_err(|err| match err { | |
326 | OperationError::Operation(err) => { | |
327 | OperationError::Operation(Box::new(err) as _) | |
328 | } | |
329 | OperationError::Internal(internal) => { | |
330 | OperationError::Internal(internal) | |
331 | } | |
332 | OperationError::Unhandled => OperationError::Unhandled, | |
333 | }) | |
334 | } | |
335 | .boxed_local() | |
336 | }), | |
337 | state: Box::new(state), | |
338 | } | |
339 | } | |
340 | ||
341 | async fn handle( | |
342 | &self, | |
343 | object: &Box<dyn Any + Send + Sync>, | |
344 | operation: &Box<dyn Any + Send + Sync>, | |
345 | operation_state: &StackOperationState, | |
346 | ) -> Result<Box<dyn Any + Send + Sync>, OperationError<Box<dyn Any + Send + Sync>>> { | |
347 | (self.func)( | |
348 | (*object).as_ref(), | |
349 | (*operation).as_ref(), | |
350 | self.state.as_ref(), | |
351 | operation_state.clone(), | |
352 | ) | |
353 | .await | |
354 | } | |
355 | } | |
356 | ||
357 | #[async_trait::async_trait(?Send)] | |
358 | 79 | pub trait FromOperationState<O: GiteratedObject, D: GiteratedOperation<O>>: Sized + Clone { |
359 | 80 | type Error: Into<anyhow::Error>; |
360 | 81 | |
@@ -367,21 +88,6 @@ pub trait FromOperationState<O: GiteratedObject, D: GiteratedOperation<O>>: Size | ||
367 | 88 | |
368 | 89 | #[async_trait::async_trait(?Send)] |
369 | 90 | impl<O: GiteratedObject, D: GiteratedOperation<O>> FromOperationState<O, D> |
370 | for Arc<GiteratedStack> | |
371 | { | |
372 | type Error = Infallible; | |
373 | ||
374 | async fn from_state( | |
375 | _object: &O, | |
376 | _operation: &D, | |
377 | state: &StackOperationState, | |
378 | ) -> Result<Self, ExtractorError<Infallible>> { | |
379 | Ok(state.runtime.clone()) | |
380 | } | |
381 | } | |
382 | ||
383 | #[async_trait::async_trait(?Send)] | |
384 | impl<O: GiteratedObject, D: GiteratedOperation<O>> FromOperationState<O, D> | |
385 | 91 | for StackOperationState |
386 | 92 | { |
387 | 93 | type Error = Infallible; |
@@ -688,15 +394,6 @@ impl<A: AuthorizedOperation<Instance> + Send + Sync> FromOperationState<Instance | ||
688 | 394 | } |
689 | 395 | } |
690 | 396 | |
691 | // #[async_trait::async_trait> FromOperationState for Option<T> { | |
692 | // type Error = (); | |
693 | ||
694 | // async fn from_state(state: &StackOperationState) -> Result<Option<T>, OperationError<()>> { | |
695 | // Ok(T::from_state(] | |
696 | // impl<T: FromOperationStatestate).await.ok()) | |
697 | // } | |
698 | // } | |
699 | ||
700 | 397 | #[derive(Clone)] |
701 | 398 | pub struct StackOperationState { |
702 | 399 | pub our_instance: Instance, |
@@ -753,3 +450,21 @@ where | ||
753 | 450 | |
754 | 451 | type Failure = (); |
755 | 452 | } |
453 | ||
454 | #[derive(Clone)] | |
455 | pub struct AnyObject(pub Arc<dyn Any + Send + Sync>); | |
456 | ||
457 | #[derive(Clone)] | |
458 | pub struct AnyOperation(pub Arc<dyn Any + Send>); | |
459 | ||
460 | #[derive(Clone)] | |
461 | pub struct AnySuccess(pub Arc<dyn Any + Send>); | |
462 | ||
463 | #[derive(Clone)] | |
464 | pub struct AnyFailure(pub Arc<dyn Any + Send>); | |
465 | ||
466 | #[derive(Clone)] | |
467 | pub struct AnyValue(pub Arc<dyn Any + Send>); | |
468 | ||
469 | #[derive(Clone)] | |
470 | pub struct AnySetting(pub Arc<dyn Any + Send + Sync>); |
giterated-stack/src/meta/mod.rs
@@ -1,4 +1,4 @@ | ||
1 | use std::{any::Any, str::FromStr, sync::Arc}; | |
1 | use std::{any::Any, collections::HashMap, str::FromStr, sync::Arc}; | |
2 | 2 | |
3 | 3 | use futures_util::{future::LocalBoxFuture, FutureExt}; |
4 | 4 | use giterated_models::{ |
@@ -8,23 +8,134 @@ use giterated_models::{ | ||
8 | 8 | value::{GetValueTyped, GiteratedObjectValue}, |
9 | 9 | }; |
10 | 10 | use serde_json::Value; |
11 | use tracing::trace; | |
11 | 12 | |
12 | use crate::{GiteratedStack, StackOperationState}; | |
13 | use crate::{ | |
14 | AnyFailure, AnyObject, AnyOperation, AnySetting, AnySuccess, AnyValue, GiteratedStack, | |
15 | ObjectOperationPair, ObjectSettingPair, ObjectValuePair, StackOperationState, | |
16 | }; | |
17 | ||
18 | /// Stores runtime metadata for all in-use Giterated protocol types. | |
19 | #[derive(Default)] | |
20 | pub struct RuntimeMetadata { | |
21 | pub objects: HashMap<String, ObjectMeta>, | |
22 | pub operations: HashMap<ObjectOperationPair<'static>, OperationMeta>, | |
23 | pub values: HashMap<ObjectValuePair<'static>, ValueMeta>, | |
24 | pub settings: HashMap<ObjectSettingPair<'static>, SettingMeta>, | |
25 | } | |
26 | ||
27 | impl RuntimeMetadata { | |
28 | pub fn register_object<O: GiteratedObject + 'static>(&mut self) { | |
29 | let object_name = O::object_name().to_string(); | |
30 | ||
31 | let object_meta = ObjectMeta::new::<O>(); | |
32 | ||
33 | if self.objects.insert(object_name, object_meta).is_some() { | |
34 | trace!( | |
35 | "Registration of object {} overwrote previous registration.", | |
36 | O::object_name() | |
37 | ); | |
38 | } else { | |
39 | trace!("Registration of object {}.", O::object_name()) | |
40 | } | |
41 | } | |
42 | ||
43 | pub fn register_operation<O: GiteratedObject + 'static, D: GiteratedOperation<O> + 'static>( | |
44 | &mut self, | |
45 | ) { | |
46 | let _object_name = O::object_name().to_string(); | |
47 | let _operation_name = D::operation_name().to_string(); | |
48 | ||
49 | if self | |
50 | .operations | |
51 | .insert( | |
52 | ObjectOperationPair::from_types::<O, D>(), | |
53 | OperationMeta::new::<O, D>(), | |
54 | ) | |
55 | .is_some() | |
56 | { | |
57 | trace!( | |
58 | "Registration of object operation {}<{}> overwrote previous registration.", | |
59 | D::operation_name(), | |
60 | O::object_name() | |
61 | ); | |
62 | } else { | |
63 | trace!( | |
64 | "Registration of object operation {}<{}>.", | |
65 | D::operation_name(), | |
66 | O::object_name() | |
67 | ) | |
68 | } | |
69 | } | |
70 | ||
71 | pub fn register_value< | |
72 | O: GiteratedObject + 'static, | |
73 | V: GiteratedObjectValue<Object = O> + 'static, | |
74 | >( | |
75 | &mut self, | |
76 | ) { | |
77 | let _object_name = O::object_name().to_string(); | |
78 | let _value_name = V::value_name().to_string(); | |
79 | ||
80 | if self | |
81 | .values | |
82 | .insert(ObjectValuePair::from_types::<O, V>(), ValueMeta::new::<V>()) | |
83 | .is_some() | |
84 | { | |
85 | trace!( | |
86 | "Registration of value <{}>::{} overwrote previous registration.", | |
87 | O::object_name(), | |
88 | V::value_name() | |
89 | ); | |
90 | } else { | |
91 | trace!( | |
92 | "Registration of value <{}>::{}.", | |
93 | O::object_name(), | |
94 | V::value_name() | |
95 | ); | |
96 | } | |
97 | } | |
98 | ||
99 | pub fn register_setting<O: GiteratedObject + 'static, S: Setting + 'static + Clone>(&mut self) { | |
100 | if self | |
101 | .settings | |
102 | .insert( | |
103 | ObjectSettingPair::from_types::<O, S>(), | |
104 | SettingMeta::new::<O, S>(), | |
105 | ) | |
106 | .is_some() | |
107 | { | |
108 | trace!( | |
109 | "Registration of setting {} overwrote previous registration.", | |
110 | S::name() | |
111 | ); | |
112 | } else { | |
113 | trace!("Registration of setting {}.", S::name()); | |
114 | } | |
115 | } | |
116 | ||
117 | pub fn append(&mut self, other: Self) { | |
118 | self.objects.extend(other.objects); | |
119 | self.operations.extend(other.operations); | |
120 | self.values.extend(other.values); | |
121 | self.settings.extend(other.settings); | |
122 | } | |
123 | } | |
13 | 124 | |
14 | 125 | pub struct ValueMeta { |
15 | 126 | pub name: String, |
16 | pub deserialize: fn(&[u8]) -> Result<Box<dyn Any>, serde_json::Error>, | |
17 | pub serialize: fn(Box<dyn Any + Send + Sync>) -> Result<Vec<u8>, serde_json::Error>, | |
127 | pub deserialize: fn(&[u8]) -> Result<AnyValue, serde_json::Error>, | |
128 | pub serialize: fn(AnyValue) -> Result<Vec<u8>, serde_json::Error>, | |
18 | 129 | pub typed_get: fn() -> Box<dyn Any + Send + Sync>, |
19 | pub is_get_value_typed: fn(&Box<dyn Any + Send + Sync>) -> bool, | |
130 | pub is_get_value_typed: fn(AnyOperation) -> bool, | |
20 | 131 | } |
21 | 132 | |
22 | 133 | pub trait IntoValueMeta { |
23 | 134 | fn name() -> String; |
24 | fn deserialize(buffer: &[u8]) -> Result<Box<dyn Any>, serde_json::Error>; | |
25 | fn serialize(value: Box<dyn Any + Send + Sync>) -> Result<Vec<u8>, serde_json::Error>; | |
135 | fn deserialize(buffer: &[u8]) -> Result<AnyValue, serde_json::Error>; | |
136 | fn serialize(value: AnyValue) -> Result<Vec<u8>, serde_json::Error>; | |
26 | 137 | fn typed_get() -> Box<dyn Any + Send + Sync>; |
27 | fn is_get_value_typed(typed_get_value: &Box<dyn Any + Send + Sync>) -> bool; | |
138 | fn is_get_value_typed(typed_get_value: AnyOperation) -> bool; | |
28 | 139 | } |
29 | 140 | |
30 | 141 | impl<O: GiteratedObject, V: GiteratedObjectValue<Object = O> + 'static> IntoValueMeta for V { |
@@ -32,25 +143,24 @@ impl<O: GiteratedObject, V: GiteratedObjectValue<Object = O> + 'static> IntoValu | ||
32 | 143 | V::value_name().to_string() |
33 | 144 | } |
34 | 145 | |
35 | fn deserialize(buffer: &[u8]) -> Result<Box<dyn Any>, serde_json::Error> { | |
36 | Ok(Box::new(serde_json::from_slice(buffer)?)) | |
146 | fn deserialize(buffer: &[u8]) -> Result<AnyValue, serde_json::Error> { | |
147 | Ok(AnyValue(Arc::new(serde_json::from_slice(buffer)?))) | |
37 | 148 | } |
38 | 149 | |
39 | fn serialize(value: Box<dyn Any + Send + Sync>) -> Result<Vec<u8>, serde_json::Error> { | |
40 | let value = value.downcast::<V>().unwrap(); | |
150 | fn serialize(value: AnyValue) -> Result<Vec<u8>, serde_json::Error> { | |
151 | let value = value.0.downcast_ref::<V>().unwrap(); | |
41 | 152 | |
42 | 153 | serde_json::to_vec(&*value) |
43 | 154 | } |
44 | 155 | |
45 | 156 | fn typed_get() -> Box<dyn Any + Send + Sync> { |
46 | 157 | Box::new(GetValueTyped::<V> { |
47 | value_name: V::value_name().to_string(), | |
48 | 158 | ty: Default::default(), |
49 | 159 | }) |
50 | 160 | } |
51 | 161 | |
52 | fn is_get_value_typed(typed_get_value: &Box<dyn Any + Send + Sync>) -> bool { | |
53 | typed_get_value.is::<GetValueTyped<V>>() | |
162 | fn is_get_value_typed(typed_get_value: AnyOperation) -> bool { | |
163 | typed_get_value.0.is::<GetValueTyped<V>>() | |
54 | 164 | } |
55 | 165 | } |
56 | 166 | |
@@ -69,17 +179,17 @@ impl ValueMeta { | ||
69 | 179 | pub struct OperationMeta { |
70 | 180 | pub name: String, |
71 | 181 | pub object_kind: String, |
72 | pub deserialize: fn(&[u8]) -> Result<Box<dyn Any + Send + Sync>, serde_json::Error>, | |
182 | pub deserialize: fn(&[u8]) -> Result<AnyOperation, serde_json::Error>, | |
73 | 183 | pub any_is_same: fn(&dyn Any) -> bool, |
74 | pub serialize_success: fn(Box<dyn Any>) -> Result<Vec<u8>, serde_json::Error>, | |
75 | pub serialize_error: fn(Box<dyn Any>) -> Result<Vec<u8>, serde_json::Error>, | |
184 | pub serialize_success: fn(AnySuccess) -> Result<Vec<u8>, serde_json::Error>, | |
185 | pub serialize_error: fn(AnyFailure) -> Result<Vec<u8>, serde_json::Error>, | |
76 | 186 | } |
77 | 187 | |
78 | 188 | pub trait IntoOperationMeta<O> { |
79 | 189 | fn name() -> String; |
80 | fn deserialize(buffer: &[u8]) -> Result<Box<dyn Any + Send + Sync>, serde_json::Error>; | |
81 | fn serialize_success(success: Box<dyn Any>) -> Result<Vec<u8>, serde_json::Error>; | |
82 | fn serialize_failure(failure: Box<dyn Any>) -> Result<Vec<u8>, serde_json::Error>; | |
190 | fn deserialize(buffer: &[u8]) -> Result<AnyOperation, serde_json::Error>; | |
191 | fn serialize_success(success: AnySuccess) -> Result<Vec<u8>, serde_json::Error>; | |
192 | fn serialize_failure(failure: AnyFailure) -> Result<Vec<u8>, serde_json::Error>; | |
83 | 193 | fn any_is_same(other: &dyn Any) -> bool; |
84 | 194 | } |
85 | 195 | |
@@ -94,17 +204,19 @@ where | ||
94 | 204 | D::operation_name().to_string() |
95 | 205 | } |
96 | 206 | |
97 | fn deserialize(buffer: &[u8]) -> Result<Box<dyn Any + Send + Sync>, serde_json::Error> { | |
98 | Ok(Box::new(serde_json::from_slice::<D>(buffer)?) as Box<dyn Any + Send + Sync>) | |
207 | fn deserialize(buffer: &[u8]) -> Result<AnyOperation, serde_json::Error> { | |
208 | Ok(AnyOperation( | |
209 | Arc::new(serde_json::from_slice::<D>(buffer)?) as Arc<dyn Any + Send + Sync> | |
210 | )) | |
99 | 211 | } |
100 | 212 | |
101 | fn serialize_success(success: Box<dyn Any>) -> Result<Vec<u8>, serde_json::Error> { | |
102 | let to_serialize = success.downcast::<D::Success>().unwrap(); | |
213 | fn serialize_success(success: AnySuccess) -> Result<Vec<u8>, serde_json::Error> { | |
214 | let to_serialize = success.0.downcast_ref::<D::Success>().unwrap(); | |
103 | 215 | serde_json::to_vec(&to_serialize) |
104 | 216 | } |
105 | 217 | |
106 | fn serialize_failure(failure: Box<dyn Any>) -> Result<Vec<u8>, serde_json::Error> { | |
107 | let to_serialize = failure.downcast::<D::Failure>().unwrap(); | |
218 | fn serialize_failure(failure: AnyFailure) -> Result<Vec<u8>, serde_json::Error> { | |
219 | let to_serialize = failure.0.downcast_ref::<D::Failure>().unwrap(); | |
108 | 220 | serde_json::to_vec(&to_serialize) |
109 | 221 | } |
110 | 222 | |
@@ -128,7 +240,7 @@ impl OperationMeta { | ||
128 | 240 | |
129 | 241 | pub struct ObjectMeta { |
130 | 242 | pub name: String, |
131 | pub from_str: Box<dyn Fn(&str) -> Result<Box<dyn Any + Send + Sync>, ()> + Send + Sync>, | |
243 | pub from_str: Box<dyn Fn(&str) -> Result<AnyObject, ()> + Send + Sync>, | |
132 | 244 | pub any_is_same: fn(&dyn Any) -> bool, |
133 | 245 | } |
134 | 246 | |
@@ -154,7 +266,7 @@ impl ObjectMeta { | ||
154 | 266 | from_str: Box::new(|source| { |
155 | 267 | let object = I::from_str(source).map_err(|_| ())?; |
156 | 268 | |
157 | Ok(Box::new(object) as Box<dyn Any + Send + Sync>) | |
269 | Ok(AnyObject(Arc::new(object) as Arc<dyn Any + Send + Sync>)) | |
158 | 270 | }), |
159 | 271 | any_is_same: I::any_is_same, |
160 | 272 | } |
@@ -163,11 +275,11 @@ impl ObjectMeta { | ||
163 | 275 | |
164 | 276 | pub struct SettingMeta { |
165 | 277 | pub name: String, |
166 | pub deserialize: fn(Value) -> Result<Box<dyn Any + Send + Sync>, serde_json::Error>, | |
167 | pub serialize: fn(&(dyn Any + Send + Sync)) -> Result<Value, serde_json::Error>, | |
278 | pub deserialize: fn(Value) -> Result<AnySetting, serde_json::Error>, | |
279 | pub serialize: fn(AnySetting) -> Result<Value, serde_json::Error>, | |
168 | 280 | pub setting_updated: for<'fut> fn( |
169 | Box<dyn Any + Send + Sync>, | |
170 | Box<dyn Any + Send + Sync>, | |
281 | AnyObject, | |
282 | AnySetting, | |
171 | 283 | Arc<GiteratedStack>, |
172 | 284 | &StackOperationState, |
173 | 285 | ) -> LocalBoxFuture<'_, ()>, |
@@ -175,40 +287,40 @@ pub struct SettingMeta { | ||
175 | 287 | |
176 | 288 | pub trait IntoSettingMeta<O> { |
177 | 289 | fn name() -> String; |
178 | fn deserialize(value: Value) -> Result<Box<dyn Any + Send + Sync>, serde_json::Error>; | |
179 | fn serialize(setting: &(dyn Any + Send + Sync)) -> Result<Value, serde_json::Error>; | |
290 | fn deserialize(value: Value) -> Result<AnySetting, serde_json::Error>; | |
291 | fn serialize(setting: AnySetting) -> Result<Value, serde_json::Error>; | |
180 | 292 | fn setting_updated( |
181 | object: Box<dyn Any + Send + Sync>, | |
182 | setting: Box<dyn Any + Send + Sync>, | |
293 | object: AnyObject, | |
294 | setting: AnySetting, | |
183 | 295 | stack: Arc<GiteratedStack>, |
184 | 296 | operation_state: &StackOperationState, |
185 | 297 | ) -> LocalBoxFuture<'_, ()>; |
186 | 298 | } |
187 | 299 | |
188 | impl<O: GiteratedObject + 'static, S: Setting + 'static> IntoSettingMeta<O> for S { | |
300 | impl<O: GiteratedObject + 'static, S: Setting + 'static + Clone> IntoSettingMeta<O> for S { | |
189 | 301 | fn name() -> String { |
190 | 302 | S::name().to_string() |
191 | 303 | } |
192 | 304 | |
193 | fn deserialize(value: Value) -> Result<Box<dyn Any + Send + Sync>, serde_json::Error> { | |
194 | Ok(Box::new(serde_json::from_value::<S>(value)?)) | |
305 | fn deserialize(value: Value) -> Result<AnySetting, serde_json::Error> { | |
306 | Ok(AnySetting(Arc::new(serde_json::from_value::<S>(value)?))) | |
195 | 307 | } |
196 | 308 | |
197 | fn serialize(setting: &(dyn Any + Send + Sync)) -> Result<Value, serde_json::Error> { | |
198 | serde_json::to_value(setting.downcast_ref::<S>().unwrap()) | |
309 | fn serialize(setting: AnySetting) -> Result<Value, serde_json::Error> { | |
310 | serde_json::to_value(setting.0.downcast_ref::<S>().unwrap()) | |
199 | 311 | } |
200 | 312 | |
201 | 313 | fn setting_updated( |
202 | object: Box<dyn Any + Send + Sync>, | |
203 | setting: Box<dyn Any + Send + Sync>, | |
314 | object: AnyObject, | |
315 | setting: AnySetting, | |
204 | 316 | stack: Arc<GiteratedStack>, |
205 | 317 | operation_state: &StackOperationState, |
206 | 318 | ) -> LocalBoxFuture<'_, ()> { |
207 | 319 | async move { |
208 | 320 | stack |
209 | 321 | .setting_update( |
210 | *object.downcast::<O>().unwrap(), | |
211 | *setting.downcast::<S>().unwrap(), | |
322 | object.0.downcast_ref::<O>().unwrap().clone(), | |
323 | setting.0.downcast_ref::<S>().unwrap().clone(), | |
212 | 324 | operation_state, |
213 | 325 | ) |
214 | 326 | .await |
giterated-stack/src/provider/metadata.rs
@@ -4,21 +4,21 @@ use anyhow::Error; | ||
4 | 4 | |
5 | 5 | use serde_json::Value; |
6 | 6 | |
7 | use crate::{ObjectMeta, SettingMeta}; | |
7 | use crate::{AnyObject, AnySetting, ObjectMeta, SettingMeta}; | |
8 | 8 | |
9 | 9 | #[async_trait::async_trait] |
10 | 10 | pub trait MetadataProvider: Send + Sync + 'static { |
11 | 11 | fn provides_for(&self, object: &dyn Any) -> bool; |
12 | 12 | async fn write( |
13 | 13 | &self, |
14 | object: &(dyn Any + Send + Sync), | |
14 | object: AnyObject, | |
15 | 15 | object_meta: &ObjectMeta, |
16 | setting: &(dyn Any + Send + Sync), | |
16 | setting: AnySetting, | |
17 | 17 | setting_meta: &SettingMeta, |
18 | 18 | ) -> Result<(), Error>; |
19 | 19 | async fn read( |
20 | 20 | &self, |
21 | object: &(dyn Any + Send + Sync), | |
21 | object: AnyObject, | |
22 | 22 | object_meta: &ObjectMeta, |
23 | 23 | setting_meta: &SettingMeta, |
24 | 24 | ) -> Result<Value, Error>; |
giterated-stack/src/stack.rs
@@ -0,0 +1,865 @@ | ||
1 | use std::any::Any; | |
2 | ||
3 | use std::fmt::Debug; | |
4 | use std::{collections::HashMap, sync::Arc}; | |
5 | ||
6 | use giterated_models::authenticated::AuthenticatedPayload; | |
7 | use giterated_models::error::{GetValueError, IntoInternalError}; | |
8 | use giterated_models::message::GiteratedMessage; | |
9 | use giterated_models::object::NetworkAnyObject; | |
10 | use giterated_models::operation::NetworkAnyOperation; | |
11 | use giterated_models::settings::{GetSettingError, Setting}; | |
12 | use giterated_models::value::{GetValue, GiteratedObjectValue}; | |
13 | use giterated_models::{ | |
14 | error::OperationError, | |
15 | object::{GiteratedObject, Object, ObjectRequest, ObjectRequestError}, | |
16 | object_backend::ObjectBackend, | |
17 | operation::GiteratedOperation, | |
18 | settings::{GetSetting, SetSetting}, | |
19 | }; | |
20 | use tracing::trace; | |
21 | ||
22 | use crate::handler::HandlerTree; | |
23 | use crate::provider::MetadataProvider; | |
24 | use crate::{ | |
25 | AnyFailure, AnyObject, AnyOperation, AnySetting, AnySuccess, AnyValue, HandlerResolvable, | |
26 | HandlerWrapper, MissingValue, ObjectOperationPair, ObjectSettingPair, ObjectValuePair, | |
27 | RuntimeMetadata, StackOperationState, SubstackBuilder, | |
28 | }; | |
29 | ||
30 | pub type OperationHandler = HandlerWrapper<(AnyObject, AnyOperation), AnySuccess, AnyFailure>; | |
31 | ||
32 | pub type ValueGetter = HandlerWrapper<(AnyObject,), AnyValue, AnyFailure>; | |
33 | ||
34 | pub type SettingGetter = HandlerWrapper<(AnyObject,), AnySetting, AnyFailure>; | |
35 | ||
36 | pub type ValueChange = HandlerWrapper<(AnyObject, AnyValue), (), anyhow::Error>; | |
37 | ||
38 | pub type SettingChange = HandlerWrapper<(AnyObject, AnySetting), (), anyhow::Error>; | |
39 | ||
40 | #[derive(Default)] | |
41 | pub struct GiteratedStack { | |
42 | operation_handlers: HashMap<ObjectOperationPair<'static>, HandlerTree<OperationHandler>>, | |
43 | value_getters: HashMap<ObjectValuePair<'static>, ValueGetter>, | |
44 | setting_getters: HashMap<&'static str, SettingGetter>, | |
45 | value_change: HashMap<ObjectValuePair<'static>, ValueChange>, | |
46 | setting_change: HashMap<ObjectSettingPair<'static>, SettingChange>, | |
47 | metadata_providers: Vec<Box<dyn MetadataProvider>>, | |
48 | pub metadata: RuntimeMetadata, | |
49 | } | |
50 | ||
51 | impl Debug for GiteratedStack { | |
52 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
53 | f.debug_struct("GiteratedStack").finish() | |
54 | } | |
55 | } | |
56 | ||
57 | impl GiteratedStack { | |
58 | pub fn merge_builder<S: GiteratedStackState>( | |
59 | &mut self, | |
60 | mut builder: SubstackBuilder<S>, | |
61 | ) -> &mut Self { | |
62 | for (target, handler) in builder.operation_handlers { | |
63 | let tree = self.get_or_create_tree(&target); | |
64 | ||
65 | tree.push(handler); | |
66 | } | |
67 | ||
68 | for (target, handler) in builder.value_getters { | |
69 | assert!(self.value_getters.insert(target, handler).is_none()); | |
70 | } | |
71 | ||
72 | for (target, handler) in builder.setting_getters { | |
73 | assert!(self.setting_getters.insert(target, handler).is_none()); | |
74 | } | |
75 | ||
76 | for (target, handler) in builder.value_change { | |
77 | self.value_change.insert(target, handler); | |
78 | } | |
79 | ||
80 | for (target, handler) in builder.setting_change { | |
81 | self.setting_change.insert(target, handler); | |
82 | } | |
83 | ||
84 | self.metadata_providers | |
85 | .append(&mut builder.metadata_providers); | |
86 | ||
87 | self.metadata.append(builder.metadata); | |
88 | ||
89 | self | |
90 | } | |
91 | ||
92 | pub async fn value_update<O, V>( | |
93 | &self, | |
94 | object: O, | |
95 | new_value: V, | |
96 | operation_state: &StackOperationState, | |
97 | ) where | |
98 | O: GiteratedObject + 'static, | |
99 | V: GiteratedObjectValue<Object = O> + 'static, | |
100 | { | |
101 | trace!("value updated {}::{}", O::object_name(), V::value_name()); | |
102 | let target = ObjectValuePair::from_types::<O, V>(); | |
103 | ||
104 | if let Some(handler) = self.value_change.get(&target) { | |
105 | // TODO | |
106 | let _ = handler | |
107 | .handle( | |
108 | (AnyObject(Arc::new(object)), AnyValue(Arc::new(new_value))), | |
109 | operation_state.clone(), | |
110 | ) | |
111 | .await; | |
112 | } | |
113 | } | |
114 | ||
115 | pub async fn setting_update<O, S>( | |
116 | &self, | |
117 | object: O, | |
118 | new_setting: S, | |
119 | operation_state: &StackOperationState, | |
120 | ) where | |
121 | O: GiteratedObject + 'static, | |
122 | S: Setting + 'static, | |
123 | { | |
124 | trace!("setting updated {}::{}", O::object_name(), S::name()); | |
125 | let target = ObjectSettingPair::from_types::<O, S>(); | |
126 | ||
127 | if let Some(handler) = self.setting_change.get(&target) { | |
128 | let _ = handler | |
129 | .handle( | |
130 | ( | |
131 | AnyObject(Arc::new(object)), | |
132 | AnySetting(Arc::new(new_setting)), | |
133 | ), | |
134 | operation_state.clone(), | |
135 | ) | |
136 | .await; | |
137 | } | |
138 | } | |
139 | ||
140 | pub async fn new_object<O>(&self, _new_object: &O, _operation_state: &StackOperationState) | |
141 | where | |
142 | O: GiteratedObject, | |
143 | { | |
144 | // TODO | |
145 | } | |
146 | ||
147 | /// Writes a setting for the specified object. | |
148 | pub async fn write_setting<O, S>( | |
149 | &self, | |
150 | object: &O, | |
151 | setting: S, | |
152 | ) -> Result<(), OperationError<()>> | |
153 | where | |
154 | O: GiteratedObject + 'static + Clone, | |
155 | S: Setting + 'static + Clone, | |
156 | { | |
157 | for provider in self.metadata_providers.iter() { | |
158 | if provider.provides_for(object as &dyn Any) { | |
159 | let setting_meta = self | |
160 | .metadata | |
161 | .settings | |
162 | .get(&ObjectSettingPair::from_types::<O, S>()) | |
163 | .ok_or_else(|| OperationError::Unhandled)?; | |
164 | ||
165 | let object_meta = self | |
166 | .metadata | |
167 | .objects | |
168 | .get(O::object_name()) | |
169 | .ok_or_else(|| OperationError::Unhandled)?; | |
170 | ||
171 | let result = provider | |
172 | .write( | |
173 | AnyObject(Arc::new(object.clone())), | |
174 | object_meta, | |
175 | AnySetting(Arc::new(setting)), | |
176 | setting_meta, | |
177 | ) | |
178 | .await | |
179 | .as_internal_error_with_context(format!("writing setting {}", S::name())); | |
180 | ||
181 | return result; | |
182 | } | |
183 | } | |
184 | ||
185 | Err(OperationError::Unhandled) | |
186 | } | |
187 | ||
188 | /// Gets a setting for the specified object. | |
189 | pub async fn new_get_setting<O, S>(&self, object: &O) -> Result<S, OperationError<MissingValue>> | |
190 | where | |
191 | O: GiteratedObject + 'static + Clone, | |
192 | S: Setting + 'static, | |
193 | { | |
194 | for provider in self.metadata_providers.iter() { | |
195 | if provider.provides_for(object as &dyn Any) { | |
196 | trace!( | |
197 | "Resolving setting {} for object {} from provider.", | |
198 | S::name(), | |
199 | O::object_name() | |
200 | ); | |
201 | ||
202 | let setting_meta = self | |
203 | .metadata | |
204 | .settings | |
205 | .get(&ObjectSettingPair::from_types::<O, S>()) | |
206 | .ok_or_else(|| OperationError::Unhandled)?; | |
207 | ||
208 | let object_meta = self | |
209 | .metadata | |
210 | .objects | |
211 | .get(O::object_name()) | |
212 | .ok_or_else(|| OperationError::Unhandled)?; | |
213 | ||
214 | let value = provider | |
215 | .read( | |
216 | AnyObject(Arc::new(object.clone())), | |
217 | object_meta, | |
218 | setting_meta, | |
219 | ) | |
220 | .await | |
221 | .as_internal_error_with_context(format!("getting setting {}", S::name()))?; | |
222 | ||
223 | return serde_json::from_value(value) | |
224 | .as_internal_error_with_context("deserializing setting"); | |
225 | } | |
226 | } | |
227 | trace!( | |
228 | "No provider registered for setting {} and object {}", | |
229 | S::name(), | |
230 | O::object_name() | |
231 | ); | |
232 | ||
233 | Err(OperationError::Unhandled) | |
234 | } | |
235 | ||
236 | fn get_or_create_tree( | |
237 | &mut self, | |
238 | target: &ObjectOperationPair<'static>, | |
239 | ) -> &mut HandlerTree<OperationHandler> { | |
240 | if self.operation_handlers.contains_key(target) { | |
241 | self.operation_handlers.get_mut(target).unwrap() | |
242 | } else { | |
243 | self.operation_handlers | |
244 | .insert(target.clone(), HandlerTree::default()); | |
245 | ||
246 | self.operation_handlers.get_mut(target).unwrap() | |
247 | } | |
248 | } | |
249 | } | |
250 | ||
251 | impl GiteratedStack { | |
252 | /// Handles a giterated network message, returning either a raw success | |
253 | /// payload or a serialized error payload. | |
254 | pub async fn handle_network_message( | |
255 | &self, | |
256 | message: AuthenticatedPayload, | |
257 | operation_state: &StackOperationState, | |
258 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { | |
259 | let message: GiteratedMessage<NetworkAnyObject, NetworkAnyOperation> = | |
260 | message.into_message(); | |
261 | ||
262 | // Deserialize the object, also getting the object type's name | |
263 | let (object_type, object) = { | |
264 | let mut result = None; | |
265 | ||
266 | for (object_type, object_meta) in self.metadata.objects.iter() { | |
267 | if let Ok(object) = (object_meta.from_str)(&message.object.0) { | |
268 | result = Some((object_type.clone(), object)); | |
269 | break; | |
270 | } | |
271 | } | |
272 | ||
273 | result | |
274 | } | |
275 | .ok_or_else(|| OperationError::Unhandled)?; | |
276 | ||
277 | trace!( | |
278 | "Handling network message {}::<{}>", | |
279 | message.operation, | |
280 | object_type | |
281 | ); | |
282 | ||
283 | if message.operation == "get_value" { | |
284 | // Special case | |
285 | let operation: GetValue = serde_json::from_slice(&message.payload.0).unwrap(); | |
286 | ||
287 | let result = self | |
288 | .network_get_value( | |
289 | object, | |
290 | object_type.clone(), | |
291 | operation.clone(), | |
292 | operation_state, | |
293 | ) | |
294 | .await; | |
295 | ||
296 | // In the case of internal errors, attach context | |
297 | let result = result.map_err(|err| match err { | |
298 | OperationError::Operation(operation) => OperationError::Operation(operation), | |
299 | OperationError::Internal(internal) => { | |
300 | OperationError::Internal(internal.context(format!( | |
301 | "{}::get_value::<{}> outcome", | |
302 | object_type, operation.value_name | |
303 | ))) | |
304 | } | |
305 | OperationError::Unhandled => OperationError::Unhandled, | |
306 | }); | |
307 | ||
308 | return result; | |
309 | } else if message.operation == "get_setting" { | |
310 | let operation: GetSetting = serde_json::from_slice(&message.payload.0).unwrap(); | |
311 | let setting_meta = self | |
312 | .metadata | |
313 | .settings | |
314 | .get(&ObjectSettingPair { | |
315 | object_kind: &object_type, | |
316 | setting_name: &operation.setting_name, | |
317 | }) | |
318 | .ok_or_else(|| OperationError::Unhandled)?; | |
319 | let raw_result = self | |
320 | .get_setting( | |
321 | object, | |
322 | object_type.clone(), | |
323 | operation.clone(), | |
324 | operation_state, | |
325 | ) | |
326 | .await; | |
327 | return match raw_result { | |
328 | Ok(success) => { | |
329 | // Success is the setting type, serialize it | |
330 | let serialized = (setting_meta.serialize)(success).unwrap(); | |
331 | ||
332 | Ok(serde_json::to_vec(&serialized).unwrap()) | |
333 | } | |
334 | Err(err) => Err(match err { | |
335 | OperationError::Operation(failure) => { | |
336 | // We know how to resolve this type | |
337 | let failure: GetSettingError = *failure.downcast().unwrap(); | |
338 | ||
339 | OperationError::Operation(serde_json::to_vec(&failure).unwrap()) | |
340 | } | |
341 | OperationError::Internal(internal) => { | |
342 | OperationError::Internal(internal.context(format!( | |
343 | "{}::get_setting::<{}> handler outcome", | |
344 | object_type, setting_meta.name | |
345 | ))) | |
346 | } | |
347 | OperationError::Unhandled => OperationError::Unhandled, | |
348 | }), | |
349 | }; | |
350 | } else if message.operation == "set_setting" { | |
351 | let operation: SetSetting = serde_json::from_slice(&message.payload.0).unwrap(); | |
352 | ||
353 | trace!( | |
354 | "Handling network {}::set_setting for {}", | |
355 | object_type, | |
356 | operation.setting_name | |
357 | ); | |
358 | ||
359 | let setting_meta = self | |
360 | .metadata | |
361 | .settings | |
362 | .get(&ObjectSettingPair { | |
363 | object_kind: &object_type, | |
364 | setting_name: &operation.setting_name, | |
365 | }) | |
366 | .unwrap(); | |
367 | ||
368 | let setting = (setting_meta.deserialize)(operation.value) | |
369 | .as_internal_error_with_context(format!( | |
370 | "deserializing setting {} for object {}", | |
371 | operation.setting_name, object_type | |
372 | ))?; | |
373 | ||
374 | trace!( | |
375 | "Deserialized setting {} for object {}", | |
376 | operation.setting_name, | |
377 | object_type, | |
378 | ); | |
379 | ||
380 | for provider in self.metadata_providers.iter() { | |
381 | if provider.provides_for(object.0.as_ref()) { | |
382 | trace!( | |
383 | "Resolved setting provider for setting {} for object {}", | |
384 | operation.setting_name, | |
385 | object_type, | |
386 | ); | |
387 | ||
388 | let object_meta = self | |
389 | .metadata | |
390 | .objects | |
391 | .get(&object_type) | |
392 | .ok_or_else(|| OperationError::Unhandled)?; | |
393 | ||
394 | let raw_result = provider | |
395 | .write(object.clone(), object_meta, setting.clone(), setting_meta) | |
396 | .await; | |
397 | ||
398 | return match raw_result { | |
399 | Ok(_) => { | |
400 | (setting_meta.setting_updated)( | |
401 | object, | |
402 | setting, | |
403 | operation_state.runtime.clone(), | |
404 | operation_state, | |
405 | ) | |
406 | .await; | |
407 | ||
408 | Ok(serde_json::to_vec(&()).unwrap()) | |
409 | } | |
410 | Err(e) => Err(OperationError::Internal(e.context(format!( | |
411 | "writing object {} setting {}", | |
412 | object_type, operation.setting_name | |
413 | )))), | |
414 | }; | |
415 | } | |
416 | ||
417 | trace!( | |
418 | "Failed to resolve setting provider for setting {} for object {}", | |
419 | operation.setting_name, | |
420 | object_type, | |
421 | ); | |
422 | } | |
423 | } | |
424 | ||
425 | let target = ObjectOperationPair { | |
426 | object_name: &object_type, | |
427 | operation_name: &message.operation, | |
428 | }; | |
429 | ||
430 | // Resolve the target operations from the handlers table | |
431 | let handler = self | |
432 | .operation_handlers | |
433 | .get(&target) | |
434 | .ok_or_else(|| OperationError::Unhandled)?; | |
435 | ||
436 | trace!( | |
437 | "Resolved operation handler for network message {}::<{}>", | |
438 | message.operation, | |
439 | object_type | |
440 | ); | |
441 | ||
442 | // Deserialize the operation | |
443 | let meta = self | |
444 | .metadata | |
445 | .operations | |
446 | .get(&target) | |
447 | .ok_or_else(|| OperationError::Unhandled)?; | |
448 | ||
449 | let operation = | |
450 | (meta.deserialize)(&message.payload.0).as_internal_error_with_context(format!( | |
451 | "deserializing operation {}::{}", | |
452 | target.object_name, target.operation_name | |
453 | ))?; | |
454 | ||
455 | trace!( | |
456 | "Deserialized operation for network message {}::<{}>", | |
457 | message.operation, | |
458 | object_type | |
459 | ); | |
460 | ||
461 | trace!( | |
462 | "Calling handler for network message {}::<{}>", | |
463 | message.operation, | |
464 | object_type | |
465 | ); | |
466 | ||
467 | // Get the raw result of the operation, where the return values are boxed. | |
468 | let raw_result = handler | |
469 | .handle((object.clone(), operation.clone()), operation_state.clone()) | |
470 | .await; | |
471 | ||
472 | trace!( | |
473 | "Finished handling network message {}::<{}>", | |
474 | message.operation, | |
475 | object_type | |
476 | ); | |
477 | ||
478 | // Deserialize the raw result for the network | |
479 | match raw_result { | |
480 | Ok(success) => Ok((meta.serialize_success)(success).as_internal_error()?), | |
481 | Err(err) => Err(match err { | |
482 | OperationError::Operation(failure) => { | |
483 | OperationError::Operation((meta.serialize_error)(failure).as_internal_error()?) | |
484 | } | |
485 | OperationError::Internal(internal) => { | |
486 | OperationError::Internal(internal.context(format!( | |
487 | "operation {}::{} handler outcome", | |
488 | target.object_name, target.operation_name | |
489 | ))) | |
490 | } | |
491 | OperationError::Unhandled => OperationError::Unhandled, | |
492 | }), | |
493 | } | |
494 | } | |
495 | ||
496 | pub async fn network_get_value( | |
497 | &self, | |
498 | object: AnyObject, | |
499 | object_kind: String, | |
500 | operation: GetValue, | |
501 | operation_state: &StackOperationState, | |
502 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { | |
503 | trace!("Handling network get_value for {}", operation.value_name); | |
504 | ||
505 | let value_meta = self | |
506 | .metadata | |
507 | .values | |
508 | .get(&ObjectValuePair { | |
509 | object_kind: &object_kind, | |
510 | value_kind: &operation.value_name, | |
511 | }) | |
512 | .ok_or_else(|| OperationError::Unhandled)?; | |
513 | ||
514 | for (target, getter) in self.value_getters.iter() { | |
515 | if target.object_kind != object_kind { | |
516 | continue; | |
517 | } | |
518 | ||
519 | if target.value_kind != operation.value_name { | |
520 | continue; | |
521 | } | |
522 | ||
523 | return match getter | |
524 | .handle((object.clone(),), operation_state.clone()) | |
525 | .await | |
526 | { | |
527 | Ok(success) => { | |
528 | // Serialize success, which is the value type itself | |
529 | let serialized = (value_meta.serialize)(success).as_internal_error()?; | |
530 | ||
531 | Ok(serialized) | |
532 | } | |
533 | Err(err) => Err(match err { | |
534 | OperationError::Operation(failure) => { | |
535 | // Failure is sourced from GetValue operation, but this is hardcoded for now | |
536 | let failure: &GetValueError = failure.0.downcast_ref().unwrap(); | |
537 | ||
538 | OperationError::Operation(serde_json::to_vec(&failure).as_internal_error()?) | |
539 | } | |
540 | OperationError::Internal(internal) => OperationError::Internal(internal), | |
541 | OperationError::Unhandled => OperationError::Unhandled, | |
542 | }), | |
543 | }; | |
544 | } | |
545 | ||
546 | Err(OperationError::Unhandled) | |
547 | } | |
548 | ||
549 | pub async fn get_setting( | |
550 | &self, | |
551 | object: AnyObject, | |
552 | object_kind: String, | |
553 | operation: GetSetting, | |
554 | _operation_state: &StackOperationState, | |
555 | ) -> Result<AnySetting, OperationError<Box<dyn Any + Send + Sync>>> { | |
556 | trace!( | |
557 | "Handling network {}::get_setting for {}", | |
558 | object_kind, | |
559 | operation.setting_name | |
560 | ); | |
561 | ||
562 | for provider in self.metadata_providers.iter() { | |
563 | if provider.provides_for(object.0.as_ref()) { | |
564 | let setting_meta = self | |
565 | .metadata | |
566 | .settings | |
567 | .get(&ObjectSettingPair { | |
568 | object_kind: &object_kind, | |
569 | setting_name: &operation.setting_name, | |
570 | }) | |
571 | .ok_or_else(|| OperationError::Unhandled)?; | |
572 | ||
573 | let object_meta = self | |
574 | .metadata | |
575 | .objects | |
576 | .get(&object_kind) | |
577 | .ok_or_else(|| OperationError::Unhandled)?; | |
578 | ||
579 | let result = provider | |
580 | .read(object.clone(), object_meta, setting_meta) | |
581 | .await | |
582 | .as_internal_error_with_context(format!( | |
583 | "reading setting {}", | |
584 | operation.setting_name | |
585 | ))?; | |
586 | ||
587 | return (setting_meta.deserialize)(result).as_internal_error_with_context(format!( | |
588 | "deserializing setting {}", | |
589 | operation.setting_name | |
590 | )); | |
591 | } | |
592 | } | |
593 | ||
594 | trace!("setting {} doesn't exist", operation.setting_name); | |
595 | ||
596 | Err(OperationError::Unhandled) | |
597 | } | |
598 | ||
599 | pub async fn network_set_setting( | |
600 | &self, | |
601 | object: AnyObject, | |
602 | object_kind: String, | |
603 | operation: SetSetting, | |
604 | operation_state: &StackOperationState, | |
605 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { | |
606 | trace!( | |
607 | "Handling network {}::set_setting for {}", | |
608 | object_kind, | |
609 | operation.setting_name | |
610 | ); | |
611 | ||
612 | let target = ObjectSettingPair { | |
613 | object_kind: &object_kind, | |
614 | setting_name: &operation.setting_name, | |
615 | }; | |
616 | ||
617 | let handler = self.setting_change.get(&target).unwrap(); | |
618 | ||
619 | let setting_meta = self | |
620 | .metadata | |
621 | .settings | |
622 | .get(&ObjectSettingPair { | |
623 | object_kind: &object_kind, | |
624 | setting_name: &operation.setting_name, | |
625 | }) | |
626 | .ok_or_else(|| OperationError::Unhandled)?; | |
627 | ||
628 | let setting = | |
629 | (setting_meta.deserialize)(operation.value).as_internal_error_with_context(format!( | |
630 | "deserializing setting {} for object {}", | |
631 | operation.setting_name, object_kind | |
632 | ))?; | |
633 | ||
634 | let raw_result = handler | |
635 | .handle((object, setting.clone()), operation_state.clone()) | |
636 | .await; | |
637 | ||
638 | match raw_result { | |
639 | Ok(_) => { | |
640 | // Serialize success, which is the value type itself | |
641 | let serialized = serde_json::to_vec(&()).as_internal_error()?; | |
642 | ||
643 | Ok(serialized) | |
644 | } | |
645 | Err(err) => Err(match err { | |
646 | OperationError::Operation(operation) => OperationError::Internal(operation), | |
647 | OperationError::Internal(internal) => OperationError::Internal(internal), | |
648 | OperationError::Unhandled => OperationError::Unhandled, | |
649 | }), | |
650 | } | |
651 | } | |
652 | } | |
653 | ||
654 | #[async_trait::async_trait(?Send)] | |
655 | impl ObjectBackend<StackOperationState> for Arc<GiteratedStack> { | |
656 | async fn object_operation<O, D>( | |
657 | &self, | |
658 | in_object: O, | |
659 | operation_name: &str, | |
660 | payload: D, | |
661 | operation_state: &StackOperationState, | |
662 | ) -> Result<D::Success, OperationError<D::Failure>> | |
663 | where | |
664 | O: GiteratedObject + Debug + 'static, | |
665 | D: GiteratedOperation<O> + Debug + 'static, | |
666 | D::Success: Clone, | |
667 | D::Failure: Clone, | |
668 | { | |
669 | // Erase object and operation types. | |
670 | let object = AnyObject(Arc::new(in_object.clone()) as Arc<dyn Any + Send + Sync>); | |
671 | let operation = AnyOperation(Arc::new(payload) as Arc<dyn Any + Send + Sync>); | |
672 | ||
673 | // We need to hijack get_value, set_setting, and get_setting. | |
674 | if operation_name == "get_value" { | |
675 | let mut value_meta = None; | |
676 | for (_, meta) in self.metadata.values.iter() { | |
677 | if (meta.is_get_value_typed)(operation.clone()) { | |
678 | value_meta = Some(meta); | |
679 | break; | |
680 | } | |
681 | } | |
682 | ||
683 | let value_meta = value_meta.ok_or_else(|| OperationError::Unhandled)?; | |
684 | ||
685 | let value_name = value_meta.name.clone(); | |
686 | ||
687 | trace!( | |
688 | "Handling get_value for {}::{}", | |
689 | O::object_name(), | |
690 | value_name | |
691 | ); | |
692 | ||
693 | for (target, getter) in self.value_getters.iter() { | |
694 | if target.object_kind != O::object_name() { | |
695 | continue; | |
696 | } | |
697 | ||
698 | if target.value_kind != value_name { | |
699 | continue; | |
700 | } | |
701 | ||
702 | return match getter | |
703 | .handle((object.clone(),), operation_state.clone()) | |
704 | .await | |
705 | { | |
706 | Ok(success) => Ok(success.0.downcast_ref::<D::Success>().unwrap().clone()), | |
707 | Err(err) => Err(match err { | |
708 | OperationError::Operation(failure) => OperationError::Operation( | |
709 | failure.0.downcast_ref::<D::Failure>().unwrap().clone(), | |
710 | ), | |
711 | OperationError::Internal(internal) => { | |
712 | OperationError::Internal(internal.context(format!( | |
713 | "{}::get_value::<{}> handler outcome", | |
714 | O::object_name(), | |
715 | value_name | |
716 | ))) | |
717 | } | |
718 | OperationError::Unhandled => OperationError::Unhandled, | |
719 | }), | |
720 | }; | |
721 | } | |
722 | ||
723 | return Err(OperationError::Unhandled); | |
724 | } else if operation.0.is::<GetSetting>() { | |
725 | let get_setting: &GetSetting = operation.0.downcast_ref().unwrap(); | |
726 | let setting_name = get_setting.setting_name.clone(); | |
727 | ||
728 | let raw_result = self | |
729 | .get_setting( | |
730 | object, | |
731 | O::object_name().to_string(), | |
732 | get_setting.clone(), | |
733 | operation_state, | |
734 | ) | |
735 | .await; | |
736 | ||
737 | return match raw_result { | |
738 | Ok(success) => { | |
739 | // Success is the setting type, serialize it | |
740 | // let serialized = (setting_meta.serialize)(success).unwrap(); | |
741 | ||
742 | // Ok(serde_json::to_vec(&serialized).unwrap()) | |
743 | Ok(success.0.downcast_ref::<D::Success>().unwrap().clone()) | |
744 | } | |
745 | Err(err) => Err(match err { | |
746 | OperationError::Operation(failure) => { | |
747 | // We know this is the right type | |
748 | OperationError::Operation(*failure.downcast().unwrap()) | |
749 | } | |
750 | OperationError::Internal(internal) => { | |
751 | OperationError::Internal(internal.context(format!( | |
752 | "{}::get_setting::<{}> handler outcome", | |
753 | O::object_name(), | |
754 | setting_name | |
755 | ))) | |
756 | } | |
757 | OperationError::Unhandled => OperationError::Unhandled, | |
758 | }), | |
759 | }; | |
760 | } else if operation.0.is::<SetSetting>() { | |
761 | todo!() | |
762 | } else if operation.0.is::<ObjectRequest>() { | |
763 | todo!() | |
764 | } | |
765 | ||
766 | // Resolve the operation from the known operations table. | |
767 | let operation_type = { | |
768 | let mut operation_type = None; | |
769 | ||
770 | for (target, operation_meta) in self.metadata.operations.iter() { | |
771 | // Skip elements that we know will not match | |
772 | if target.object_name != O::object_name() { | |
773 | continue; | |
774 | } | |
775 | ||
776 | if target.operation_name != operation_name { | |
777 | continue; | |
778 | } | |
779 | ||
780 | if (operation_meta.any_is_same)(&operation) { | |
781 | operation_type = Some(target.clone()); | |
782 | break; | |
783 | } | |
784 | } | |
785 | ||
786 | operation_type | |
787 | } | |
788 | .ok_or_else(|| OperationError::Unhandled)?; | |
789 | ||
790 | // Resolve the handler from our handler tree | |
791 | let handler_tree = self | |
792 | .operation_handlers | |
793 | .get(&operation_type) | |
794 | .ok_or_else(|| OperationError::Unhandled)?; | |
795 | ||
796 | let raw_result = handler_tree | |
797 | .handle((object, operation), operation_state.clone()) | |
798 | .await; | |
799 | ||
800 | // Convert the dynamic result back into its concrete type | |
801 | match raw_result { | |
802 | Ok(result) => Ok(result.0.downcast_ref::<D::Success>().unwrap().clone()), | |
803 | Err(err) => Err(match err { | |
804 | OperationError::Internal(internal) => { | |
805 | OperationError::Internal(internal.context(format!( | |
806 | "operation {}::{} handler outcome", | |
807 | operation_type.object_name, operation_type.operation_name | |
808 | ))) | |
809 | } | |
810 | OperationError::Operation(boxed_error) => OperationError::Operation( | |
811 | boxed_error.0.downcast_ref::<D::Failure>().unwrap().clone(), | |
812 | ), | |
813 | OperationError::Unhandled => OperationError::Unhandled, | |
814 | }), | |
815 | } | |
816 | } | |
817 | ||
818 | async fn get_object<O>( | |
819 | &self, | |
820 | object_str: &str, | |
821 | _operation_state: &StackOperationState, | |
822 | ) -> Result<Object<StackOperationState, O, Self>, OperationError<ObjectRequestError>> | |
823 | where | |
824 | O: GiteratedObject + Debug + 'static, | |
825 | { | |
826 | // TODO: Authorization? | |
827 | for (_object_name, object_meta) in self.metadata.objects.iter() { | |
828 | if let Ok(object) = (object_meta.from_str)(object_str) { | |
829 | return Ok(unsafe { | |
830 | Object::new_unchecked( | |
831 | object.0.downcast_ref::<O>().unwrap().clone(), | |
832 | self.clone(), | |
833 | ) | |
834 | }); | |
835 | } | |
836 | } | |
837 | ||
838 | Err(OperationError::Unhandled) | |
839 | } | |
840 | } | |
841 | ||
842 | /// Defines a type that is a valid Giterated runtime state. | |
843 | /// | |
844 | /// This allows for extraction of state in handlers, based on a | |
845 | /// [`FromOperationState<S>`] impl on (what is in this case) [`Self`]. | |
846 | pub trait GiteratedStackState: Send + Sync + Clone {} | |
847 | ||
848 | impl<T: Send + Sync + Clone> GiteratedStackState for T {} | |
849 | ||
850 | #[async_trait::async_trait(?Send)] | |
851 | impl<R, S, T> HandlerResolvable<R, S> for Option<T> | |
852 | where | |
853 | T: HandlerResolvable<R, S>, | |
854 | { | |
855 | type Error = MissingValue; | |
856 | ||
857 | async fn from_handler_state( | |
858 | required_parameters: &R, | |
859 | operation_state: &S, | |
860 | ) -> Result<Option<T>, MissingValue> { | |
861 | Ok(T::from_handler_state(required_parameters, operation_state) | |
862 | .await | |
863 | .ok()) | |
864 | } | |
865 | } |
giterated-stack/src/substack.rs
@@ -0,0 +1,325 @@ | ||
1 | use std::{collections::HashMap, sync::Arc}; | |
2 | ||
3 | use futures_util::FutureExt; | |
4 | use giterated_models::{ | |
5 | error::OperationError, | |
6 | instance::Instance, | |
7 | object::{GiteratedObject, ObjectRequest, ObjectResponse}, | |
8 | operation::GiteratedOperation, | |
9 | settings::Setting, | |
10 | value::{GetValueTyped, GiteratedObjectValue}, | |
11 | }; | |
12 | use tracing::{info, trace}; | |
13 | ||
14 | use crate::{ | |
15 | handler::HandlerWrapper, provider::MetadataProvider, AnyFailure, AnyObject, AnyOperation, | |
16 | AnySetting, AnySuccess, AnyValue, GiteratedStack, GiteratedStackState, IntoGiteratedHandler, | |
17 | ObjectOperationPair, ObjectSettingPair, ObjectValuePair, OperationHandler, RuntimeMetadata, | |
18 | SettingChange, SettingGetter, StackOperationState, ValueChange, ValueGetter, | |
19 | }; | |
20 | ||
21 | pub struct SubstackBuilder<S: GiteratedStackState> { | |
22 | pub(crate) operation_handlers: HashMap<ObjectOperationPair<'static>, OperationHandler>, | |
23 | pub(crate) value_getters: HashMap<ObjectValuePair<'static>, ValueGetter>, | |
24 | pub(crate) setting_getters: HashMap<&'static str, SettingGetter>, | |
25 | pub(crate) metadata: RuntimeMetadata, | |
26 | pub(crate) value_change: HashMap<ObjectValuePair<'static>, ValueChange>, | |
27 | pub(crate) metadata_providers: Vec<Box<dyn MetadataProvider>>, | |
28 | pub(crate) setting_change: HashMap<ObjectSettingPair<'static>, SettingChange>, | |
29 | ||
30 | pub(crate) state: S, | |
31 | } | |
32 | ||
33 | impl<S: GiteratedStackState + 'static> SubstackBuilder<S> { | |
34 | pub fn new(state: S) -> Self { | |
35 | Self { | |
36 | operation_handlers: Default::default(), | |
37 | value_getters: Default::default(), | |
38 | setting_getters: Default::default(), | |
39 | metadata: Default::default(), | |
40 | value_change: Default::default(), | |
41 | metadata_providers: Default::default(), | |
42 | setting_change: Default::default(), | |
43 | state, | |
44 | } | |
45 | } | |
46 | } | |
47 | ||
48 | impl<S: Send + Sync + Clone + 'static> SubstackBuilder<S> { | |
49 | /// Insert an operation handler into the runtime builder. | |
50 | /// | |
51 | /// # Type Registration | |
52 | /// Inserting the handler will automatically, if required, register the operation type of the | |
53 | /// handler. It will **not** register the object type automatically. | |
54 | pub fn operation<O, D, A, H>(&mut self, handler: H) -> &mut Self | |
55 | where | |
56 | O: GiteratedObject + Clone, | |
57 | D: GiteratedOperation<O> + Clone, | |
58 | H: IntoGiteratedHandler< | |
59 | (O, D), | |
60 | A, | |
61 | S, | |
62 | StackOperationState, | |
63 | Result<D::Success, OperationError<D::Failure>>, | |
64 | > + Send | |
65 | + Sync | |
66 | + 'static, | |
67 | O: 'static, | |
68 | D: 'static, | |
69 | D::Failure: std::fmt::Debug + 'static, | |
70 | D::Success: 'static, | |
71 | { | |
72 | let wrapped = HandlerWrapper::new(self.state.clone(), handler); | |
73 | ||
74 | let wrapped = wrapped.map( | |
75 | |(any_object, any_operation): &(AnyObject, AnyOperation), | |
76 | _state: &StackOperationState| { | |
77 | Ok(( | |
78 | any_object.0.downcast_ref::<O>().unwrap().clone(), | |
79 | any_operation.0.downcast_ref::<D>().unwrap().clone(), | |
80 | )) | |
81 | }, | |
82 | ); | |
83 | ||
84 | let wrapped = wrapped.map_return(|ret_val, _state| match ret_val { | |
85 | Ok(success) => Ok(AnySuccess(Arc::new(success))), | |
86 | Err(err) => Err(match err { | |
87 | OperationError::Operation(failure) => { | |
88 | OperationError::Operation(AnyFailure(Arc::new(failure))) | |
89 | } | |
90 | OperationError::Internal(err) => OperationError::Internal(err), | |
91 | OperationError::Unhandled => OperationError::Unhandled, | |
92 | }), | |
93 | }); | |
94 | ||
95 | let pair = ObjectOperationPair::from_types::<O, D>(); | |
96 | ||
97 | self.operation_handlers.insert(pair, wrapped); | |
98 | ||
99 | self.metadata.register_operation::<O, D>(); | |
100 | ||
101 | self | |
102 | } | |
103 | ||
104 | /// Register a [`GiteratedObject`] type with the runtime. | |
105 | /// | |
106 | /// # Type Registration | |
107 | /// This will register the provided object type. | |
108 | pub fn object<O: GiteratedObject + 'static>(&mut self) -> &mut Self { | |
109 | self.metadata.register_object::<O>(); | |
110 | ||
111 | // Insert handler so ObjectRequest is handled properly | |
112 | ||
113 | self.operation( | |
114 | move |_object: Instance, | |
115 | operation: ObjectRequest, | |
116 | _state: S, | |
117 | _operation_state: StackOperationState, | |
118 | stack: Arc<GiteratedStack>| { | |
119 | let operation = operation.clone(); | |
120 | async move { | |
121 | for (_object_name, object_meta) in stack.metadata.objects.iter() { | |
122 | if (object_meta.from_str)(&operation.0).is_ok() { | |
123 | return Ok(ObjectResponse(operation.0.clone())); | |
124 | } | |
125 | } | |
126 | ||
127 | Err(OperationError::Unhandled) | |
128 | } | |
129 | .boxed_local() | |
130 | }, | |
131 | ); | |
132 | ||
133 | self | |
134 | } | |
135 | ||
136 | /// Register a [`Setting`] type with the runtime. | |
137 | /// | |
138 | /// # Type Registration | |
139 | /// This will register the provided setting type. | |
140 | pub fn setting<O: GiteratedObject + 'static, T: Setting + 'static + Clone>( | |
141 | &mut self, | |
142 | ) -> &mut Self { | |
143 | self.metadata.register_setting::<O, T>(); | |
144 | ||
145 | self | |
146 | } | |
147 | ||
148 | /// Register a [`GiteratedObjectValue`] that is also a [`Setting`], which | |
149 | /// allows for automatic value updates. | |
150 | pub fn value_setting< | |
151 | O: GiteratedObject + 'static + Clone, | |
152 | T: GiteratedObjectValue<Object = O> + Setting + 'static + Clone, | |
153 | >( | |
154 | &mut self, | |
155 | ) -> &mut Self { | |
156 | self.metadata.register_setting::<O, T>(); | |
157 | self.metadata.register_value::<O, T>(); | |
158 | ||
159 | self.setting_change.insert( | |
160 | ObjectSettingPair::from_types::<O, T>(), | |
161 | HandlerWrapper::new( | |
162 | (), | |
163 | move |object: AnyObject, | |
164 | setting: AnySetting, | |
165 | _state: (), | |
166 | operation_state: StackOperationState, | |
167 | stack: Arc<GiteratedStack>| { | |
168 | trace!( | |
169 | "value setting updated {}::{}", | |
170 | O::object_name(), | |
171 | T::value_name() | |
172 | ); | |
173 | let object = object.clone(); | |
174 | async move { | |
175 | let object = object.0.downcast_ref::<O>().unwrap(); | |
176 | let setting = setting.0.downcast_ref::<T>().unwrap(); | |
177 | stack | |
178 | .value_update(object.clone(), setting.clone(), &operation_state) | |
179 | .await; | |
180 | Ok(()) | |
181 | } | |
182 | .boxed_local() | |
183 | }, | |
184 | ), | |
185 | ); | |
186 | ||
187 | let wrapped = HandlerWrapper::new( | |
188 | self.state.clone(), | |
189 | |object: AnyObject, | |
190 | _state: _, | |
191 | _operation_state: StackOperationState, | |
192 | stack: Arc<GiteratedStack>| { | |
193 | info!("a setting handler called"); | |
194 | let object = object.clone(); | |
195 | async move { | |
196 | match stack | |
197 | .new_get_setting::<O, T>(object.0.downcast_ref().unwrap()) | |
198 | .await | |
199 | { | |
200 | Ok(setting) => Ok(AnyValue(Arc::new(setting))), | |
201 | Err(err) => { | |
202 | panic!("Error: {:?}", err); | |
203 | } | |
204 | } | |
205 | } | |
206 | .boxed_local() | |
207 | }, | |
208 | ); | |
209 | ||
210 | self.value_getters | |
211 | .insert(ObjectValuePair::from_types::<O, T>(), wrapped); | |
212 | ||
213 | self | |
214 | } | |
215 | ||
216 | /// Register a [`GiteratedObjectValue<O>`] type with the runtime, providing | |
217 | /// its associated handler for [`GetValue`]. | |
218 | /// | |
219 | /// # Type Registration | |
220 | /// This will register the provided [`GiteratedObjectValue`] type for its matching / specified | |
221 | /// object type. It will **not** register the object type automatically. | |
222 | pub fn value<O, V, A, F, E, Fut>(&mut self, handler: F) -> &mut Self | |
223 | where | |
224 | O: GiteratedObject + 'static, | |
225 | V: GiteratedObjectValue<Object = O> + 'static + Clone, | |
226 | F: IntoGiteratedHandler< | |
227 | (O, GetValueTyped<V>), | |
228 | A, | |
229 | S, | |
230 | StackOperationState, | |
231 | Result<V, OperationError<E>>, | |
232 | > + Send | |
233 | + Sync, | |
234 | E: Into<anyhow::Error> + 'static + std::fmt::Debug + Clone, | |
235 | F: 'static, | |
236 | { | |
237 | let wrapped = HandlerWrapper::new(self.state.clone(), handler); | |
238 | ||
239 | let wrapped = wrapped.map( | |
240 | |(any_object,): &(AnyObject,), _state: &StackOperationState| { | |
241 | Ok(( | |
242 | any_object | |
243 | .0 | |
244 | .downcast_ref::<O>() | |
245 | .ok_or_else(|| OperationError::Internal(DowncastError.into()))? | |
246 | .clone(), | |
247 | GetValueTyped { | |
248 | ty: std::marker::PhantomData, | |
249 | }, | |
250 | )) | |
251 | }, | |
252 | ); | |
253 | ||
254 | let wrapped = wrapped.map_return(|ret_val, _state| match ret_val { | |
255 | Ok(success) => Ok(AnyValue(Arc::new(success))), | |
256 | Err(err) => Err(match err { | |
257 | OperationError::Operation(failure) => OperationError::Internal(failure.into()), | |
258 | OperationError::Internal(err) => OperationError::Internal(err), | |
259 | OperationError::Unhandled => OperationError::Unhandled, | |
260 | }), | |
261 | }); | |
262 | ||
263 | assert!(self | |
264 | .value_getters | |
265 | .insert(ObjectValuePair::from_types::<O, V>(), wrapped) | |
266 | .is_none()); | |
267 | ||
268 | self.metadata.register_value::<O, V>(); | |
269 | ||
270 | self | |
271 | } | |
272 | ||
273 | pub fn value_change<O, A, F, V>(&mut self, handler: F) -> &mut Self | |
274 | where | |
275 | O: GiteratedObject + 'static, | |
276 | F: IntoGiteratedHandler< | |
277 | (O, V), | |
278 | A, | |
279 | S, | |
280 | StackOperationState, | |
281 | Result<(), OperationError<anyhow::Error>>, | |
282 | > + Send | |
283 | + Sync, | |
284 | V: GiteratedObjectValue<Object = O> + Clone + 'static, | |
285 | O: 'static, | |
286 | V: 'static, | |
287 | F: 'static, | |
288 | { | |
289 | let wrapped = HandlerWrapper::new(self.state.clone(), handler); | |
290 | ||
291 | let wrapped = wrapped.map( | |
292 | |(any_object, any_value): &(AnyObject, AnyValue), _state: &StackOperationState| { | |
293 | Ok(( | |
294 | any_object | |
295 | .0 | |
296 | .downcast_ref::<O>() | |
297 | .ok_or_else(|| OperationError::Internal(DowncastError.into()))? | |
298 | .clone(), | |
299 | any_value | |
300 | .0 | |
301 | .downcast_ref::<V>() | |
302 | .ok_or_else(|| OperationError::Internal(DowncastError.into()))? | |
303 | .clone(), | |
304 | )) | |
305 | }, | |
306 | ); | |
307 | ||
308 | assert!(self | |
309 | .value_change | |
310 | .insert(ObjectValuePair::from_types::<O, V>(), wrapped) | |
311 | .is_none()); | |
312 | ||
313 | self | |
314 | } | |
315 | ||
316 | pub fn object_metadata_provider(&mut self, provider: Box<dyn MetadataProvider>) -> &mut Self { | |
317 | self.metadata_providers.push(provider); | |
318 | ||
319 | self | |
320 | } | |
321 | } | |
322 | ||
323 | #[derive(Debug, Clone, thiserror::Error)] | |
324 | #[error("downcast error")] | |
325 | pub struct DowncastError; |
giterated-stack/src/update.rs
@@ -116,20 +116,19 @@ impl HandleSettingUpdatedFunction { | ||
116 | 116 | setting_name: setting_name.to_string(), |
117 | 117 | }, |
118 | 118 | |
119 | function: Box::new(move |object, setting_name, value, state| { | |
119 | function: Box::new(move |object, _setting_name, _value, _state| { | |
120 | 120 | async move { |
121 | let mut handler = handler; | |
121 | let _handler = handler; | |
122 | 122 | |
123 | let object = match O::from_str(&object) { | |
123 | let _object = match O::from_str(&object) { | |
124 | 124 | Ok(object) => object, |
125 | 125 | Err(_) => return Err(()), |
126 | 126 | }; |
127 | 127 | |
128 | let setting: S = serde_json::from_value(value.0).unwrap(); | |
129 | ||
130 | let _ = handler | |
131 | .handle_setting_update(object, setting_name, setting, &state) | |
132 | .await; | |
128 | // let setting: S = serde_json::from_value( | |
129 | // let _ = handler | |
130 | // .handle_setting_update(object, setting_name, setting, &state) | |
131 | // .await;value.0).unwrap(); | |
133 | 132 | |
134 | 133 | Ok(()) |
135 | 134 | } |
@@ -168,20 +167,20 @@ impl HandleValueUpdatedFunction { | ||
168 | 167 | value_name: value_name.to_string(), |
169 | 168 | }, |
170 | 169 | |
171 | function: Box::new(move |object, setting_name, value, state| { | |
170 | function: Box::new(move |object, _setting_name, _value, _state| { | |
172 | 171 | async move { |
173 | let mut handler = handler; | |
172 | let _handler = handler; | |
174 | 173 | |
175 | let object = match O::from_str(&object) { | |
174 | let _object = match O::from_str(&object) { | |
176 | 175 | Ok(object) => object, |
177 | 176 | Err(_) => return Err(()), |
178 | 177 | }; |
179 | 178 | |
180 | let setting: V = serde_json::from_value(value.0).unwrap(); | |
179 | // let setting: V = serde_json::from_value(value.0).unwrap(); | |
181 | 180 | |
182 | let _ = handler | |
183 | .handle_value_update(object, setting_name, setting, &state) | |
184 | .await; | |
181 | // let _ = handler | |
182 | // .handle_value_update(object, setting_name, setting, &state) | |
183 | // .await; | |
185 | 184 | |
186 | 185 | Ok(()) |
187 | 186 | } |