Compare commits

...

6 commits

20 changed files with 655 additions and 121 deletions

1
.gitignore vendored
View file

@ -9,3 +9,4 @@ devenv.local.nix
# pre-commit # pre-commit
.pre-commit-config.yaml .pre-commit-config.yaml
rustc-ice-*.txt

View file

@ -1,37 +0,0 @@
thread 'rustc' panicked at compiler/rustc_middle/src/query/on_disk_cache.rs:736:21:
Failed to convert DefPathHash DefPathHash(Fingerprint(9597590199268592635, 17791879502897349522))
stack backtrace:
0: 0x7fbfbb48d025 - std::backtrace::Backtrace::create::hbc256ff4bc983c0b
1: 0x7fbfb9c8c865 - std::backtrace::Backtrace::force_capture::h1ebb6042c5b424a8
2: 0x7fbfb8db2217 - std[11ac8361619e45fd]::panicking::update_hook::<alloc[1ed43557cf619c2]::boxed::Box<rustc_driver_impl[8c32a9dec5e4d0f0]::install_ice_hook::{closure#0}>>::{closure#0}
3: 0x7fbfb9ca3ee8 - std::panicking::rust_panic_with_hook::ha6cfc51100acb1ab
4: 0x7fbfb9ca3cb7 - std::panicking::begin_panic_handler::{{closure}}::he56e1efe5ba67ce1
5: 0x7fbfb9ca1699 - std::sys::backtrace::__rust_end_short_backtrace::hcc7bf1345a5f7ae3
6: 0x7fbfb9ca3984 - rust_begin_unwind
7: 0x7fbfb6ad55c3 - core::panicking::panic_fmt::h146c2ef4416c8c7b
8: 0x7fbfba61abc5 - <rustc_middle[62c17eb200ed25ef]::query::on_disk_cache::CacheDecoder as rustc_span[e2902ef3f031f316]::SpanDecoder>::decode_span
9: 0x7fbfba94bc1c - rustc_query_system[4b3461eb5f3eee8]::query::plumbing::try_execute_query::<rustc_query_impl[2b1ee272ecafb82c]::DynamicConfig<rustc_query_system[4b3461eb5f3eee8]::query::caches::DefIdCache<rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 8usize]>>, false, false, false>, rustc_query_impl[2b1ee272ecafb82c]::plumbing::QueryCtxt, true>
10: 0x7fbfba94929a - rustc_query_impl[2b1ee272ecafb82c]::query_impl::def_span::get_query_incr::__rust_end_short_backtrace
11: 0x7fbfbaa190c0 - rustc_middle[62c17eb200ed25ef]::query::plumbing::query_get_at::<rustc_query_system[4b3461eb5f3eee8]::query::caches::DefIdCache<rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 8usize]>>>
12: 0x7fbfbacaaf7d - <rustc_hir_analysis[198913e0276c9380]::coherence::inherent_impls_overlap::InherentOverlapChecker>::check_for_duplicate_items_in_impl
13: 0x7fbfbb39e280 - rustc_hir_analysis[198913e0276c9380]::coherence::inherent_impls_overlap::crate_inherent_impls_overlap_check
14: 0x7fbfbb39dc6d - rustc_query_impl[2b1ee272ecafb82c]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[2b1ee272ecafb82c]::query_impl::crate_inherent_impls_overlap_check::dynamic_query::{closure#2}::{closure#0}, rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 1usize]>>
15: 0x7fbfbb39d1fd - rustc_query_system[4b3461eb5f3eee8]::query::plumbing::try_execute_query::<rustc_query_impl[2b1ee272ecafb82c]::DynamicConfig<rustc_query_system[4b3461eb5f3eee8]::query::caches::SingleCache<rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 1usize]>>, false, false, false>, rustc_query_impl[2b1ee272ecafb82c]::plumbing::QueryCtxt, true>
16: 0x7fbfbb39c867 - rustc_query_impl[2b1ee272ecafb82c]::query_impl::crate_inherent_impls_overlap_check::get_query_incr::__rust_end_short_backtrace
17: 0x7fbfba5bb6f3 - rustc_hir_analysis[198913e0276c9380]::check_crate
18: 0x7fbfba5b1351 - rustc_interface[d7e86b952eb641e5]::passes::run_required_analyses
19: 0x7fbfbb1bac1e - rustc_interface[d7e86b952eb641e5]::passes::analysis
20: 0x7fbfbb1babf1 - rustc_query_impl[2b1ee272ecafb82c]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[2b1ee272ecafb82c]::query_impl::analysis::dynamic_query::{closure#2}::{closure#0}, rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 1usize]>>
21: 0x7fbfbb39cecd - rustc_query_system[4b3461eb5f3eee8]::query::plumbing::try_execute_query::<rustc_query_impl[2b1ee272ecafb82c]::DynamicConfig<rustc_query_system[4b3461eb5f3eee8]::query::caches::SingleCache<rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 1usize]>>, false, false, false>, rustc_query_impl[2b1ee272ecafb82c]::plumbing::QueryCtxt, true>
22: 0x7fbfbb39cb7a - rustc_query_impl[2b1ee272ecafb82c]::query_impl::analysis::get_query_incr::__rust_end_short_backtrace
23: 0x7fbfbb1b30bc - rustc_interface[d7e86b952eb641e5]::interface::run_compiler::<core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>, rustc_driver_impl[8c32a9dec5e4d0f0]::run_compiler::{closure#0}>::{closure#1}
24: 0x7fbfbb2c0504 - std[11ac8361619e45fd]::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface[d7e86b952eb641e5]::util::run_in_thread_with_globals<rustc_interface[d7e86b952eb641e5]::util::run_in_thread_pool_with_globals<rustc_interface[d7e86b952eb641e5]::interface::run_compiler<core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>, rustc_driver_impl[8c32a9dec5e4d0f0]::run_compiler::{closure#0}>::{closure#1}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#0}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>
25: 0x7fbfbb2c0b70 - <<std[11ac8361619e45fd]::thread::Builder>::spawn_unchecked_<rustc_interface[d7e86b952eb641e5]::util::run_in_thread_with_globals<rustc_interface[d7e86b952eb641e5]::util::run_in_thread_pool_with_globals<rustc_interface[d7e86b952eb641e5]::interface::run_compiler<core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>, rustc_driver_impl[8c32a9dec5e4d0f0]::run_compiler::{closure#0}>::{closure#1}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#0}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#1} as core[dcc560a250502550]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
26: 0x7fbfbb2c0f6b - std::sys::pal::unix::thread::Thread::new::thread_start::h1921d0f3a7850262
27: 0x7fbfbcbf8272 - start_thread
28: 0x7fbfbcc73dcc - clone3
29: 0x0 - <unknown>
rustc version: 1.83.0-nightly (0ee7cb5e3 2024-09-10)
platform: x86_64-unknown-linux-gnu

View file

@ -1,37 +0,0 @@
thread 'rustc' panicked at compiler/rustc_middle/src/query/on_disk_cache.rs:736:21:
Failed to convert DefPathHash DefPathHash(Fingerprint(9597590199268592635, 17791879502897349522))
stack backtrace:
0: 0x77c2cca8d025 - std::backtrace::Backtrace::create::hbc256ff4bc983c0b
1: 0x77c2cb28c865 - std::backtrace::Backtrace::force_capture::h1ebb6042c5b424a8
2: 0x77c2ca3b2217 - std[11ac8361619e45fd]::panicking::update_hook::<alloc[1ed43557cf619c2]::boxed::Box<rustc_driver_impl[8c32a9dec5e4d0f0]::install_ice_hook::{closure#0}>>::{closure#0}
3: 0x77c2cb2a3ee8 - std::panicking::rust_panic_with_hook::ha6cfc51100acb1ab
4: 0x77c2cb2a3cb7 - std::panicking::begin_panic_handler::{{closure}}::he56e1efe5ba67ce1
5: 0x77c2cb2a1699 - std::sys::backtrace::__rust_end_short_backtrace::hcc7bf1345a5f7ae3
6: 0x77c2cb2a3984 - rust_begin_unwind
7: 0x77c2c80d55c3 - core::panicking::panic_fmt::h146c2ef4416c8c7b
8: 0x77c2cbc1abc5 - <rustc_middle[62c17eb200ed25ef]::query::on_disk_cache::CacheDecoder as rustc_span[e2902ef3f031f316]::SpanDecoder>::decode_span
9: 0x77c2cbf4bc1c - rustc_query_system[4b3461eb5f3eee8]::query::plumbing::try_execute_query::<rustc_query_impl[2b1ee272ecafb82c]::DynamicConfig<rustc_query_system[4b3461eb5f3eee8]::query::caches::DefIdCache<rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 8usize]>>, false, false, false>, rustc_query_impl[2b1ee272ecafb82c]::plumbing::QueryCtxt, true>
10: 0x77c2cbf4929a - rustc_query_impl[2b1ee272ecafb82c]::query_impl::def_span::get_query_incr::__rust_end_short_backtrace
11: 0x77c2cc0190c0 - rustc_middle[62c17eb200ed25ef]::query::plumbing::query_get_at::<rustc_query_system[4b3461eb5f3eee8]::query::caches::DefIdCache<rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 8usize]>>>
12: 0x77c2cc2aaf7d - <rustc_hir_analysis[198913e0276c9380]::coherence::inherent_impls_overlap::InherentOverlapChecker>::check_for_duplicate_items_in_impl
13: 0x77c2cc99e280 - rustc_hir_analysis[198913e0276c9380]::coherence::inherent_impls_overlap::crate_inherent_impls_overlap_check
14: 0x77c2cc99dc6d - rustc_query_impl[2b1ee272ecafb82c]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[2b1ee272ecafb82c]::query_impl::crate_inherent_impls_overlap_check::dynamic_query::{closure#2}::{closure#0}, rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 1usize]>>
15: 0x77c2cc99d1fd - rustc_query_system[4b3461eb5f3eee8]::query::plumbing::try_execute_query::<rustc_query_impl[2b1ee272ecafb82c]::DynamicConfig<rustc_query_system[4b3461eb5f3eee8]::query::caches::SingleCache<rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 1usize]>>, false, false, false>, rustc_query_impl[2b1ee272ecafb82c]::plumbing::QueryCtxt, true>
16: 0x77c2cc99c867 - rustc_query_impl[2b1ee272ecafb82c]::query_impl::crate_inherent_impls_overlap_check::get_query_incr::__rust_end_short_backtrace
17: 0x77c2cbbbb6f3 - rustc_hir_analysis[198913e0276c9380]::check_crate
18: 0x77c2cbbb1351 - rustc_interface[d7e86b952eb641e5]::passes::run_required_analyses
19: 0x77c2cc7bac1e - rustc_interface[d7e86b952eb641e5]::passes::analysis
20: 0x77c2cc7babf1 - rustc_query_impl[2b1ee272ecafb82c]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[2b1ee272ecafb82c]::query_impl::analysis::dynamic_query::{closure#2}::{closure#0}, rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 1usize]>>
21: 0x77c2cc99cecd - rustc_query_system[4b3461eb5f3eee8]::query::plumbing::try_execute_query::<rustc_query_impl[2b1ee272ecafb82c]::DynamicConfig<rustc_query_system[4b3461eb5f3eee8]::query::caches::SingleCache<rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 1usize]>>, false, false, false>, rustc_query_impl[2b1ee272ecafb82c]::plumbing::QueryCtxt, true>
22: 0x77c2cc99cb7a - rustc_query_impl[2b1ee272ecafb82c]::query_impl::analysis::get_query_incr::__rust_end_short_backtrace
23: 0x77c2cc7b30bc - rustc_interface[d7e86b952eb641e5]::interface::run_compiler::<core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>, rustc_driver_impl[8c32a9dec5e4d0f0]::run_compiler::{closure#0}>::{closure#1}
24: 0x77c2cc8c0504 - std[11ac8361619e45fd]::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface[d7e86b952eb641e5]::util::run_in_thread_with_globals<rustc_interface[d7e86b952eb641e5]::util::run_in_thread_pool_with_globals<rustc_interface[d7e86b952eb641e5]::interface::run_compiler<core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>, rustc_driver_impl[8c32a9dec5e4d0f0]::run_compiler::{closure#0}>::{closure#1}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#0}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>
25: 0x77c2cc8c0b70 - <<std[11ac8361619e45fd]::thread::Builder>::spawn_unchecked_<rustc_interface[d7e86b952eb641e5]::util::run_in_thread_with_globals<rustc_interface[d7e86b952eb641e5]::util::run_in_thread_pool_with_globals<rustc_interface[d7e86b952eb641e5]::interface::run_compiler<core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>, rustc_driver_impl[8c32a9dec5e4d0f0]::run_compiler::{closure#0}>::{closure#1}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#0}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#1} as core[dcc560a250502550]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
26: 0x77c2cc8c0f6b - std::sys::pal::unix::thread::Thread::new::thread_start::h1921d0f3a7850262
27: 0x77c2ce089272 - start_thread
28: 0x77c2ce104dcc - clone3
29: 0x0 - <unknown>
rustc version: 1.83.0-nightly (0ee7cb5e3 2024-09-10)
platform: x86_64-unknown-linux-gnu

View file

@ -1,37 +0,0 @@
thread 'rustc' panicked at compiler/rustc_middle/src/query/on_disk_cache.rs:736:21:
Failed to convert DefPathHash DefPathHash(Fingerprint(9597590199268592635, 17791879502897349522))
stack backtrace:
0: 0x704a8948d025 - std::backtrace::Backtrace::create::hbc256ff4bc983c0b
1: 0x704a87c8c865 - std::backtrace::Backtrace::force_capture::h1ebb6042c5b424a8
2: 0x704a86db2217 - std[11ac8361619e45fd]::panicking::update_hook::<alloc[1ed43557cf619c2]::boxed::Box<rustc_driver_impl[8c32a9dec5e4d0f0]::install_ice_hook::{closure#0}>>::{closure#0}
3: 0x704a87ca3ee8 - std::panicking::rust_panic_with_hook::ha6cfc51100acb1ab
4: 0x704a87ca3cb7 - std::panicking::begin_panic_handler::{{closure}}::he56e1efe5ba67ce1
5: 0x704a87ca1699 - std::sys::backtrace::__rust_end_short_backtrace::hcc7bf1345a5f7ae3
6: 0x704a87ca3984 - rust_begin_unwind
7: 0x704a84ad55c3 - core::panicking::panic_fmt::h146c2ef4416c8c7b
8: 0x704a8861abc5 - <rustc_middle[62c17eb200ed25ef]::query::on_disk_cache::CacheDecoder as rustc_span[e2902ef3f031f316]::SpanDecoder>::decode_span
9: 0x704a8894bc1c - rustc_query_system[4b3461eb5f3eee8]::query::plumbing::try_execute_query::<rustc_query_impl[2b1ee272ecafb82c]::DynamicConfig<rustc_query_system[4b3461eb5f3eee8]::query::caches::DefIdCache<rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 8usize]>>, false, false, false>, rustc_query_impl[2b1ee272ecafb82c]::plumbing::QueryCtxt, true>
10: 0x704a8894929a - rustc_query_impl[2b1ee272ecafb82c]::query_impl::def_span::get_query_incr::__rust_end_short_backtrace
11: 0x704a88a190c0 - rustc_middle[62c17eb200ed25ef]::query::plumbing::query_get_at::<rustc_query_system[4b3461eb5f3eee8]::query::caches::DefIdCache<rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 8usize]>>>
12: 0x704a88caaf7d - <rustc_hir_analysis[198913e0276c9380]::coherence::inherent_impls_overlap::InherentOverlapChecker>::check_for_duplicate_items_in_impl
13: 0x704a8939e280 - rustc_hir_analysis[198913e0276c9380]::coherence::inherent_impls_overlap::crate_inherent_impls_overlap_check
14: 0x704a8939dc6d - rustc_query_impl[2b1ee272ecafb82c]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[2b1ee272ecafb82c]::query_impl::crate_inherent_impls_overlap_check::dynamic_query::{closure#2}::{closure#0}, rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 1usize]>>
15: 0x704a8939d1fd - rustc_query_system[4b3461eb5f3eee8]::query::plumbing::try_execute_query::<rustc_query_impl[2b1ee272ecafb82c]::DynamicConfig<rustc_query_system[4b3461eb5f3eee8]::query::caches::SingleCache<rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 1usize]>>, false, false, false>, rustc_query_impl[2b1ee272ecafb82c]::plumbing::QueryCtxt, true>
16: 0x704a8939c867 - rustc_query_impl[2b1ee272ecafb82c]::query_impl::crate_inherent_impls_overlap_check::get_query_incr::__rust_end_short_backtrace
17: 0x704a885bb6f3 - rustc_hir_analysis[198913e0276c9380]::check_crate
18: 0x704a885b1351 - rustc_interface[d7e86b952eb641e5]::passes::run_required_analyses
19: 0x704a891bac1e - rustc_interface[d7e86b952eb641e5]::passes::analysis
20: 0x704a891babf1 - rustc_query_impl[2b1ee272ecafb82c]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[2b1ee272ecafb82c]::query_impl::analysis::dynamic_query::{closure#2}::{closure#0}, rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 1usize]>>
21: 0x704a8939cecd - rustc_query_system[4b3461eb5f3eee8]::query::plumbing::try_execute_query::<rustc_query_impl[2b1ee272ecafb82c]::DynamicConfig<rustc_query_system[4b3461eb5f3eee8]::query::caches::SingleCache<rustc_middle[62c17eb200ed25ef]::query::erase::Erased<[u8; 1usize]>>, false, false, false>, rustc_query_impl[2b1ee272ecafb82c]::plumbing::QueryCtxt, true>
22: 0x704a8939cb7a - rustc_query_impl[2b1ee272ecafb82c]::query_impl::analysis::get_query_incr::__rust_end_short_backtrace
23: 0x704a891b30bc - rustc_interface[d7e86b952eb641e5]::interface::run_compiler::<core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>, rustc_driver_impl[8c32a9dec5e4d0f0]::run_compiler::{closure#0}>::{closure#1}
24: 0x704a892c0504 - std[11ac8361619e45fd]::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface[d7e86b952eb641e5]::util::run_in_thread_with_globals<rustc_interface[d7e86b952eb641e5]::util::run_in_thread_pool_with_globals<rustc_interface[d7e86b952eb641e5]::interface::run_compiler<core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>, rustc_driver_impl[8c32a9dec5e4d0f0]::run_compiler::{closure#0}>::{closure#1}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#0}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>
25: 0x704a892c0b70 - <<std[11ac8361619e45fd]::thread::Builder>::spawn_unchecked_<rustc_interface[d7e86b952eb641e5]::util::run_in_thread_with_globals<rustc_interface[d7e86b952eb641e5]::util::run_in_thread_pool_with_globals<rustc_interface[d7e86b952eb641e5]::interface::run_compiler<core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>, rustc_driver_impl[8c32a9dec5e4d0f0]::run_compiler::{closure#0}>::{closure#1}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#0}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[dcc560a250502550]::result::Result<(), rustc_span[e2902ef3f031f316]::ErrorGuaranteed>>::{closure#1} as core[dcc560a250502550]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
26: 0x704a892c0f6b - std::sys::pal::unix::thread::Thread::new::thread_start::h1921d0f3a7850262
27: 0x704a8ac0b272 - start_thread
28: 0x704a8ac86dcc - clone3
29: 0x0 - <unknown>
rustc version: 1.83.0-nightly (0ee7cb5e3 2024-09-10)
platform: x86_64-unknown-linux-gnu

View file

@ -1,3 +1,4 @@
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net> // SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
pub mod web;

View file

@ -0,0 +1,168 @@
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
use actix_identity::Identity;
use actix_web::{get, http::header::ContentType, post, web, HttpRequest, HttpResponse, Responder};
use serde::{Deserialize, Serialize};
use url::Url;
use uuid::Uuid;
use super::errors::*;
use super::types;
use crate::billing::domain::add_store_command::AddStoreCommandBuilder;
use crate::billing::domain::{add_bill_command::*, bill_updated_event, commands::BillingCommand};
use crate::utils::uuid::WebGetUUIDInterfaceObj;
pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(add_bill_submit_handler);
cfg.service(add_bill_page_handler);
cfg.service(add_store_page_handler);
cfg.service(add_store_submit_handler);
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
struct WebAddBillPayload {
store_id: Uuid,
}
#[allow(clippy::too_many_arguments)]
#[get("/billing/store/add")]
#[tracing::instrument(name = "add store page handler", skip())]
//async fn add_bill_page_handler(_: Identity) -> WebJsonRepsonse<impl Responder> {
async fn add_store_page_handler() -> WebJsonRepsonse<impl Responder> {
let page = r#"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="/billing/store/add" method="post">
<button type="submit">
Create Store
</button>
</form>
</body>
</html>
"#;
Ok(HttpResponse::Ok()
.insert_header(ContentType::html())
.body(page))
}
const UUID: Uuid = uuid::uuid!("67e55044-10b1-426f-9247-bb680e5fe0c8");
#[allow(clippy::too_many_arguments)]
#[post("/billing/store/add")]
#[tracing::instrument(
name = "add store handler",
skip(billing_store_cqrs_exec, billing_store_cqrs_view, uuid_generator)
)]
async fn add_store_submit_handler(
billing_store_cqrs_exec: types::WebBillingStoreCqrsExec,
billing_store_cqrs_view: types::WebBillingStoreCqrsView,
uuid_generator: WebGetUUIDInterfaceObj,
req: HttpRequest,
// id: Identity,
) -> WebJsonRepsonse<impl Responder> {
// let user_id = Uuid::parse_str(&id.id().unwrap()).unwrap();
let user_id = UUID;
let store_uuid = UUID;
let store_uuid_str = store_uuid.to_string();
let cmd = AddStoreCommandBuilder::default()
.name("foo".into())
.owner(user_id)
.store_id(UUID)
.address(None)
.build()
.unwrap();
billing_store_cqrs_exec
.execute(&store_uuid_str, BillingCommand::AddStore(cmd))
.await
.unwrap();
let store = billing_store_cqrs_view
.load(&store_uuid_str)
.await
.unwrap()
.unwrap();
Ok(HttpResponse::Ok().json(store))
}
#[allow(clippy::too_many_arguments)]
#[get("/billing/bill/add")]
#[tracing::instrument(name = "add bill page handler", skip())]
//async fn add_bill_page_handler(_: Identity) -> WebJsonRepsonse<impl Responder> {
async fn add_bill_page_handler() -> WebJsonRepsonse<impl Responder> {
let page = r#"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
Token Refreshed
<form action="/billing/bill/add" method="post">
<label> Store ID <input type="text" name="store_id" id="store_id" /></label>
<button type="submit">
Refresh Token
</button>
</form>
</body>
</html>
"#;
Ok(HttpResponse::Ok()
.insert_header(ContentType::html())
.body(page))
}
#[allow(clippy::too_many_arguments)]
#[post("/billing/bill/add")]
#[tracing::instrument(
name = "add bill handler",
skip(billing_bill_cqrs_exec, billing_bill_cqrs_view,)
)]
async fn add_bill_submit_handler(
billing_bill_cqrs_exec: types::WebBillingBillCqrsExec,
billing_bill_cqrs_view: types::WebBillingBillCqrsView,
req: HttpRequest,
// id: Identity,
payload: web::Form<WebAddBillPayload>,
) -> WebJsonRepsonse<impl Responder> {
// let user_id = Uuid::parse_str(&id.id().unwrap()).unwrap();
let user_id = Uuid::new_v4();
let bill_uuid = Uuid::new_v4();
let bill_uuid_str = bill_uuid.to_string();
let cmd = AddBillCommandBuilder::default()
.adding_by(user_id)
.bill_id(bill_uuid)
.store_id(payload.store_id)
.build()
.unwrap();
billing_bill_cqrs_exec
.execute(&bill_uuid_str, BillingCommand::AddBill(cmd))
.await
.unwrap();
let bill = billing_bill_cqrs_view
.load(&bill_uuid_str)
.await
.unwrap()
.unwrap();
Ok(HttpResponse::Ok().json(bill))
}

View file

@ -0,0 +1,75 @@
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
use actix_web::http::StatusCode;
use actix_web::{HttpResponse, ResponseError};
use derive_more::Display;
use serde::{Deserialize, Serialize};
use crate::billing::application::services::errors::*;
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
struct ErrorResponse {
error: String,
}
impl From<WebError> for ErrorResponse {
fn from(value: WebError) -> Self {
ErrorResponse {
error: serde_json::to_string(&value).unwrap_or_else(|_| {
log::error!("Unable to serialize error");
"Unable to serialize error".into()
}),
}
}
}
#[derive(Debug, Display, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
pub enum WebError {
InternalError,
BillNotFound,
StoreNotFound,
LineItemNotFound,
BadRequest,
}
impl From<BillingError> for WebError {
fn from(v: BillingError) -> Self {
match v {
BillingError::BillIDNotFound => Self::BillNotFound,
BillingError::InternalError => Self::InternalError,
BillingError::DuplicateStoreName => Self::InternalError,
BillingError::DuplicateBillID => Self::InternalError,
BillingError::DuplicateLineItemID => Self::InternalError,
BillingError::DuplicateStoreID => Self::InternalError,
BillingError::StoreIDNotFound => Self::StoreNotFound,
BillingError::LineItemIDNotFound => Self::LineItemNotFound,
}
}
}
impl ResponseError for WebError {
fn status_code(&self) -> StatusCode {
match self {
Self::InternalError => StatusCode::INTERNAL_SERVER_ERROR,
Self::StoreNotFound => StatusCode::NOT_FOUND,
Self::LineItemNotFound => StatusCode::NOT_FOUND,
Self::BillNotFound => StatusCode::NOT_FOUND,
Self::BadRequest => StatusCode::BAD_REQUEST,
}
}
fn error_response(&self) -> actix_web::HttpResponse {
let e: ErrorResponse = self.clone().into();
match self {
Self::InternalError => HttpResponse::InternalServerError().json(e),
Self::StoreNotFound => HttpResponse::NotFound().json(e),
Self::LineItemNotFound => HttpResponse::NotFound().json(e),
Self::BillNotFound => HttpResponse::BadRequest().json(e),
Self::BadRequest => HttpResponse::BadRequest().json(e),
}
}
}
pub type WebJsonRepsonse<V> = Result<V, WebError>;

View file

@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
use std::sync::Arc;
use actix_web::web;
use crate::billing::adapters::types;
mod bill;
mod errors;
mod routes;
pub use errors::WebJsonRepsonse;
pub use routes::RoutesRepository;
pub fn load_ctx() -> impl FnOnce(&mut web::ServiceConfig) {
let routes = types::WebBillingRoutesRepository::new(Arc::new(RoutesRepository::default()));
let f = move |cfg: &mut web::ServiceConfig| {
cfg.app_data(routes);
cfg.configure(bill::services);
};
Box::new(f)
}

View file

@ -0,0 +1,67 @@
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
use url::Url;
use uuid::Uuid;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct RoutesRepository {
add_bill: String,
update_bill: String,
delete_bill: String,
compute_total_price_for_bill: String,
add_line_item: String,
update_line_item: String,
delete_line_item: String,
}
impl Default for RoutesRepository {
fn default() -> Self {
Self {
add_bill: "/billing/bill/add".into(),
update_bill: "/billing/bill/{bill_uuid}".into(),
delete_bill: "/billing/bill/{bill_uuid}".into(),
compute_total_price_for_bill: "/billing/bill/{bill_uuid}/compute-total".into(),
add_line_item: "/billing/bill/{bill_id}/line_item/add".into(),
update_line_item: "/billing/bill/{bill_id}/line_item/{line_item_uuid}".into(),
delete_line_item: "/billing/bill/{bill_id}/line_item/{line_item_uuid}".into(),
}
}
}
impl RoutesRepository {
pub fn update_bill(&self, bill_id: Uuid) -> String {
self.update_bill
.replace("{bill_uuid}", &bill_id.to_string())
}
pub fn delete_bill(&self, bill_id: Uuid) -> String {
self.delete_bill
.replace("{bill_uuid}", &bill_id.to_string())
}
pub fn compute_total_price_for_bill(&self, bill_id: Uuid) -> String {
self.compute_total_price_for_bill
.replace("{bill_uuid}", &bill_id.to_string())
}
pub fn add_line_item(&self, bill_id: Uuid) -> String {
self.add_line_item
.replace("{bill_uuid}", &bill_id.to_string())
}
pub fn update_line_item(&self, bill_id: Uuid, line_item_uuid: Uuid) -> String {
self.update_line_item
.replace("{bill_uuid}", &bill_id.to_string())
.replace("{line_item_uuid}", &line_item_uuid.to_string())
}
pub fn delete_line_item(&self, bill_id: Uuid, line_item_uuid: Uuid) -> String {
self.delete_line_item
.replace("{bill_uuid}", &bill_id.to_string())
.replace("{line_item_uuid}", &line_item_uuid.to_string())
}
}

View file

@ -1,6 +1,87 @@
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net> // SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
use std::sync::Arc;
use actix_web::web::{self, Data};
use cqrs_es::{persist::ViewRepository, EventEnvelope, Query, View};
use postgres_es::PostgresCqrs;
use sqlx::postgres::PgPool;
use crate::billing::{
application::{
port::output::db::{
bill_id_exists::BillIDExistsDBPortObj,
get_line_items_for_bill_id::GetLineItemsForBillIDDBPortObj,
line_item_id_exists::LineItemIDExistsDBPortObj, next_token_id::NextTokenIDDBPortObj,
store_id_exists::StoreIDExistsDBPortObj, store_name_exists::StoreNameExistsDBPortObj,
},
services::{BillingServices, BillingServicesObj},
},
domain::{bill_aggregate::Bill, line_item_aggregate::LineItem, store_aggregate::Store},
};
use crate::settings::Settings;
use output::db::postgres::{bill_view, line_item_view, store_view, BillingDBPostgresAdapter};
mod input; mod input;
mod output; mod output;
mod types;
pub fn load_adapters(pool: PgPool, settings: Settings) -> impl FnOnce(&mut web::ServiceConfig) {
// init DB
let db = BillingDBPostgresAdapter::new(pool.clone());
let db_bill_id_exists: BillIDExistsDBPortObj = Arc::new(db.clone());
let db_line_item_id_exists: LineItemIDExistsDBPortObj = Arc::new(db.clone());
let db_store_id_exists: StoreIDExistsDBPortObj = Arc::new(db.clone());
let db_store_name_exists: StoreNameExistsDBPortObj = Arc::new(db.clone());
let db_get_line_items_for_bill_id: GetLineItemsForBillIDDBPortObj = Arc::new(db.clone());
let db_next_token_id: NextTokenIDDBPortObj = Arc::new(db.clone());
// init services
let services: BillingServicesObj = Arc::new(BillingServices::new(
db_bill_id_exists.clone(),
db_line_item_id_exists.clone(),
db_store_id_exists.clone(),
db_store_name_exists.clone(),
db_get_line_items_for_bill_id.clone(),
db_next_token_id.clone(),
));
let (bill_cqrs_exec, bill_cqrs_query) = bill_view::init_cqrs(db.clone(), services.clone());
let (store_cqrs_exec, store_cqrs_query) = store_view::init_cqrs(db.clone(), services.clone());
let (line_item_cqrs_exec, line_item_cqrs_query) =
line_item_view::init_cqrs(db.clone(), services.clone());
let f = move |cfg: &mut web::ServiceConfig| {
cfg.configure(input::web::load_ctx());
cfg.app_data(Data::new(bill_cqrs_exec.clone()));
cfg.app_data(Data::new(bill_cqrs_query.clone()));
cfg.app_data(Data::new(store_cqrs_exec.clone()));
cfg.app_data(Data::new(store_cqrs_query.clone()));
cfg.app_data(Data::new(line_item_cqrs_exec.clone()));
cfg.app_data(Data::new(line_item_cqrs_query.clone()));
};
Box::new(f)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::db::migrate::*;
#[actix_rt::test]
async fn billing_load_adapters() {
let settings = crate::settings::tests::get_settings().await;
settings.create_db().await;
let db = crate::db::sqlx_postgres::Postgres::init(&settings.database.url).await;
db.migrate().await;
load_adapters(db.pool.clone(), settings.clone());
}
}

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net> // SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
mod postgres; pub(crate) mod postgres;

View file

@ -3,16 +3,20 @@
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use cqrs_es::persist::{PersistenceError, ViewContext, ViewRepository}; use cqrs_es::persist::{PersistenceError, ViewContext, ViewRepository};
use cqrs_es::{EventEnvelope, Query, View}; use cqrs_es::{EventEnvelope, Query, View};
use postgres_es::PostgresCqrs;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use time::OffsetDateTime; use time::OffsetDateTime;
use uuid::Uuid; use uuid::Uuid;
use super::errors::*; use super::errors::*;
use super::BillingDBPostgresAdapter; use super::BillingDBPostgresAdapter;
use crate::billing::adapters::types::{BillingBillCqrsExec, BillingBillCqrsView};
use crate::billing::application::services::BillingServicesObj;
use crate::billing::domain::bill_aggregate::{Bill, BillBuilder}; use crate::billing::domain::bill_aggregate::{Bill, BillBuilder};
use crate::billing::domain::events::BillingEvent; use crate::billing::domain::events::BillingEvent;
use crate::types::currency::{self, Currency, PriceBuilder}; use crate::types::currency::{self, Currency, PriceBuilder};
@ -311,12 +315,24 @@ impl Query<Bill> for BillingDBPostgresAdapter {
} }
} }
pub fn init_cqrs(
db: BillingDBPostgresAdapter,
services: BillingServicesObj,
) -> (BillingBillCqrsExec, BillingBillCqrsView) {
let queries: Vec<Box<dyn Query<Bill>>> = vec![Box::new(db.clone())];
let pool = db.pool.clone();
(
Arc::new(postgres_es::postgres_cqrs(pool.clone(), queries, services)),
Arc::new(db.clone()),
)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use postgres_es::PostgresCqrs;
use crate::{ use crate::{
billing::{ billing::{
application::services::{ application::services::{

View file

@ -1,8 +1,8 @@
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net> // SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use cqrs_es::persist::{PersistenceError, ViewContext, ViewRepository}; use cqrs_es::persist::{PersistenceError, ViewContext, ViewRepository};
@ -13,6 +13,8 @@ use uuid::Uuid;
use super::errors::*; use super::errors::*;
use super::BillingDBPostgresAdapter; use super::BillingDBPostgresAdapter;
use crate::billing::adapters::types::{BillingLineItemCqrsExec, BillingLineItemCqrsView};
use crate::billing::application::services::BillingServicesObj;
use crate::billing::domain::events::BillingEvent; use crate::billing::domain::events::BillingEvent;
use crate::billing::domain::line_item_aggregate::*; use crate::billing::domain::line_item_aggregate::*;
use crate::types::currency::*; use crate::types::currency::*;
@ -363,6 +365,20 @@ impl Query<LineItem> for BillingDBPostgresAdapter {
} }
} }
pub fn init_cqrs(
db: BillingDBPostgresAdapter,
services: BillingServicesObj,
) -> (BillingLineItemCqrsExec, BillingLineItemCqrsView) {
let queries: Vec<Box<dyn Query<LineItem>>> = vec![Box::new(db.clone())];
let pool = db.pool.clone();
(
Arc::new(postgres_es::postgres_cqrs(pool.clone(), queries, services)),
Arc::new(db.clone()),
)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View file

@ -8,19 +8,19 @@ use sqlx::postgres::PgPool;
use crate::db::{migrate::RunMigrations, sqlx_postgres::Postgres}; use crate::db::{migrate::RunMigrations, sqlx_postgres::Postgres};
mod bill_id_exists; mod bill_id_exists;
mod bill_view; pub(crate) mod bill_view;
mod errors; mod errors;
mod get_line_items_for_bill_id; mod get_line_items_for_bill_id;
mod line_item_id_exists; mod line_item_id_exists;
mod line_item_view; pub(crate) mod line_item_view;
mod next_token_id; mod next_token_id;
mod store_id_exists; mod store_id_exists;
mod store_name_exists; mod store_name_exists;
mod store_view; pub(crate) mod store_view;
#[derive(Clone)] #[derive(Clone)]
pub struct BillingDBPostgresAdapter { pub struct BillingDBPostgresAdapter {
pool: PgPool, pub(crate) pool: PgPool,
} }
impl BillingDBPostgresAdapter { impl BillingDBPostgresAdapter {

View file

@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net> // SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use cqrs_es::persist::{PersistenceError, ViewContext, ViewRepository}; use cqrs_es::persist::{PersistenceError, ViewContext, ViewRepository};
@ -10,6 +11,8 @@ use uuid::Uuid;
use super::errors::*; use super::errors::*;
use super::BillingDBPostgresAdapter; use super::BillingDBPostgresAdapter;
use crate::billing::adapters::types::{BillingStoreCqrsExec, BillingStoreCqrsView};
use crate::billing::application::services::BillingServicesObj;
use crate::billing::domain::events::BillingEvent; use crate::billing::domain::events::BillingEvent;
use crate::billing::domain::store_aggregate::*; use crate::billing::domain::store_aggregate::*;
use crate::utils::parse_aggregate_id::parse_aggregate_id; use crate::utils::parse_aggregate_id::parse_aggregate_id;
@ -216,6 +219,20 @@ impl Query<Store> for BillingDBPostgresAdapter {
} }
} }
pub fn init_cqrs(
db: BillingDBPostgresAdapter,
services: BillingServicesObj,
) -> (BillingStoreCqrsExec, BillingStoreCqrsView) {
let queries: Vec<Box<dyn Query<Store>>> = vec![Box::new(db.clone())];
let pool = db.pool.clone();
(
Arc::new(postgres_es::postgres_cqrs(pool.clone(), queries, services)),
Arc::new(db.clone()),
)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net> // SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
mod db; pub(crate) mod db;

View file

@ -0,0 +1,45 @@
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
#![allow(dead_code)]
use std::sync::Arc;
use actix_web::web::Data;
use cqrs_es::persist::ViewRepository;
use postgres_es::PostgresCqrs;
use crate::billing::{
adapters::{
input::web::RoutesRepository,
output::db::postgres::{
bill_view::BillView, line_item_view::LineItemView, store_view::StoreView,
BillingDBPostgresAdapter,
},
},
application::services::BillingServicesObj,
domain::{bill_aggregate::Bill, line_item_aggregate::LineItem, store_aggregate::Store},
};
pub type WebBillingRoutesRepository = Data<Arc<RoutesRepository>>;
pub type WebBillingServiceObj = Data<BillingServicesObj>;
pub type BillingBillCqrsExec = Arc<PostgresCqrs<Bill>>;
pub type WebBillingBillCqrsExec = Data<BillingBillCqrsExec>;
pub type BillingBillCqrsView = Arc<dyn ViewRepository<BillView, Bill>>;
pub type WebBillingBillCqrsView = Data<BillingBillCqrsView>;
pub type BillingLineItemCqrsExec = Arc<PostgresCqrs<LineItem>>;
pub type WebBillingLineItemCqrsExec = Data<BillingLineItemCqrsExec>;
pub type BillingLineItemCqrsView = Arc<dyn ViewRepository<LineItemView, LineItem>>;
pub type WebBillingLineItemCqrsView = Data<BillingLineItemCqrsView>;
pub type BillingStoreCqrsExec = Arc<PostgresCqrs<Store>>;
pub type WebBillingStoreCqrsExec = Data<BillingStoreCqrsExec>;
pub type BillingStoreCqrsView = Arc<dyn ViewRepository<StoreView, Store>>;
pub type WebBillingStoreCqrsView = Data<BillingStoreCqrsView>;

View file

@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net> // SPDX-FileCopyrightText: 2024 Aravinth Manivannan <realaravinth@batsense.net>
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
use std::sync::Arc;
use derive_builder::Builder; use derive_builder::Builder;
use mockall::predicate::*; use mockall::predicate::*;
@ -20,6 +21,23 @@ pub mod update_line_item_service;
pub mod update_store_service; pub mod update_store_service;
// TODO: 2. reset token number for store_id cronjob // TODO: 2. reset token number for store_id cronjob
use add_bill_service::AddBillServiceBuilder;
use add_line_item_service::AddLineItemServiceBuilder;
use add_store_service::AddStoreServiceBuilder;
use compute_bill_total_price_service::ComputeBillTotalPriceBillServiceBuilder;
use delete_bill_service::DeleteBillServiceBuilder;
use delete_line_item_service::DeleteLineItemServiceBuilder;
use update_bill_service::UpdateBillServiceBuilder;
use update_line_item_service::UpdateLineItemServiceBuilder;
use update_store_service::UpdateStoreServiceBuilder;
use crate::billing::application::port::output::db::{
bill_id_exists::BillIDExistsDBPortObj,
get_line_items_for_bill_id::GetLineItemsForBillIDDBPortObj,
line_item_id_exists::LineItemIDExistsDBPortObj, next_token_id::NextTokenIDDBPortObj,
store_id_exists::StoreIDExistsDBPortObj, store_name_exists::StoreNameExistsDBPortObj,
};
#[automock] #[automock]
pub trait BillingServicesInterface: Send + Sync { pub trait BillingServicesInterface: Send + Sync {
fn add_bill(&self) -> add_bill_service::AddBillServiceObj; fn add_bill(&self) -> add_bill_service::AddBillServiceObj;
@ -35,6 +53,8 @@ pub trait BillingServicesInterface: Send + Sync {
) -> compute_bill_total_price_service::ComputeBillTotalPriceBillServiceObj; ) -> compute_bill_total_price_service::ComputeBillTotalPriceBillServiceObj;
} }
pub type BillingServicesObj = std::sync::Arc<dyn BillingServicesInterface>;
#[derive(Clone, Builder)] #[derive(Clone, Builder)]
pub struct BillingServices { pub struct BillingServices {
add_bill: add_bill_service::AddBillServiceObj, add_bill: add_bill_service::AddBillServiceObj,
@ -81,3 +101,109 @@ impl BillingServicesInterface for BillingServices {
self.compute_total_price_for_bill.clone() self.compute_total_price_for_bill.clone()
} }
} }
impl BillingServices {
pub fn new(
db_bill_id_exists: BillIDExistsDBPortObj,
db_line_item_id_exists: LineItemIDExistsDBPortObj,
db_store_id_exists: StoreIDExistsDBPortObj,
db_store_name_exists: StoreNameExistsDBPortObj,
db_get_line_items_for_bill_id: GetLineItemsForBillIDDBPortObj,
db_next_token_id: NextTokenIDDBPortObj,
) -> Self {
let services = BillingServicesBuilder::default()
.add_bill(Arc::new(
AddBillServiceBuilder::default()
.db_next_token_id(db_next_token_id.clone())
.db_bill_id_exists(db_bill_id_exists.clone())
.build()
.unwrap(),
))
.add_store(Arc::new(
AddStoreServiceBuilder::default()
.db_store_id_exists(db_store_id_exists.clone())
.db_store_name_exists(db_store_name_exists.clone())
.build()
.unwrap(),
))
.update_store(Arc::new(
UpdateStoreServiceBuilder::default()
.db_store_id_exists(db_store_id_exists.clone())
.db_store_name_exists(db_store_name_exists.clone())
.build()
.unwrap(),
))
.add_line_item(Arc::new(
AddLineItemServiceBuilder::default()
.db_line_item_id_exists(db_line_item_id_exists.clone())
.db_bill_id_exists(db_bill_id_exists.clone())
.build()
.unwrap(),
))
.update_line_item(Arc::new(
UpdateLineItemServiceBuilder::default()
.db_line_item_id_exists(db_line_item_id_exists.clone())
.db_bill_id_exists(db_bill_id_exists.clone())
.build()
.unwrap(),
))
.delete_line_item(Arc::new(
DeleteLineItemServiceBuilder::default()
.db_line_item_id_exists(db_line_item_id_exists.clone())
.build()
.unwrap(),
))
.update_bill(Arc::new(
UpdateBillServiceBuilder::default()
.db_bill_id_exists(db_bill_id_exists.clone())
.build()
.unwrap(),
))
.delete_bill(Arc::new(
DeleteBillServiceBuilder::default()
.db_bill_id_exists(db_bill_id_exists.clone())
.build()
.unwrap(),
))
.compute_total_price_for_bill(Arc::new(
ComputeBillTotalPriceBillServiceBuilder::default()
.db_bill_id_exists(db_bill_id_exists.clone())
.db_get_line_items_for_bill_id(db_get_line_items_for_bill_id)
.build()
.unwrap(),
))
.build()
.unwrap();
services
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
billing::application::port::output::db::{
bill_id_exists::mock_bill_id_exists_db_port_true,
get_line_items_for_bill_id::mock_get_line_items_for_bill_id_db_port_no_line_items,
line_item_id_exists::mock_line_item_id_exists_db_port_true,
next_token_id::mock_next_token_id_db_port,
store_id_exists::mock_store_id_exists_db_port_true,
store_name_exists::mock_store_name_exists_db_port_true,
},
db::migrate::*,
tests::bdd::IS_NEVER_CALLED,
};
#[test]
fn billing_services_builder_works() {
BillingServices::new(
mock_bill_id_exists_db_port_true(IS_NEVER_CALLED),
mock_line_item_id_exists_db_port_true(IS_NEVER_CALLED),
mock_store_id_exists_db_port_true(IS_NEVER_CALLED),
mock_store_name_exists_db_port_true(IS_NEVER_CALLED),
mock_get_line_items_for_bill_id_db_port_no_line_items(IS_NEVER_CALLED),
mock_next_token_id_db_port(IS_NEVER_CALLED),
);
}
}

View file

@ -2,6 +2,6 @@
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
mod adapters; pub(crate) mod adapters;
mod application; mod application;
mod domain; mod domain;

View file

@ -58,6 +58,10 @@ async fn main() {
.wrap( .wrap(
middleware::DefaultHeaders::new().add(("Permissions-Policy", "interest-cohort=()")), middleware::DefaultHeaders::new().add(("Permissions-Policy", "interest-cohort=()")),
) )
.configure(billing::adapters::load_adapters(
db.pool.clone(),
settings.clone(),
))
// .configure(auth::adapter::load_adapters(db.pool.clone(), &settings)) // .configure(auth::adapter::load_adapters(db.pool.clone(), &settings))
.configure(utils::random_string::GenerateRandomString::inject()) .configure(utils::random_string::GenerateRandomString::inject())
.configure(utils::uuid::GenerateUUID::inject()) .configure(utils::uuid::GenerateUUID::inject())