Repository: IgnisDa/ryot (language: rust)

Issue:
After reordering exercises, automatically scroll to the exercise whose position was changed



Discussion / hints:

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 4e8b05d2ab..fca5289bb6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -311,7 +311,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -331,9 +331,9 @@ dependencies = [
 
 [[package]]
 name = "async-graphql"
-version = "7.0.7"
+version = "7.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b76aba2f176af685c2229633881a3adeae51f87ae1811781e73910b7001c93e"
+checksum = "9d37c3e9ba322eb00e9e5e997d58f08e8b6de037325b9367ac59bca8e3cd46af"
 dependencies = [
  "async-graphql-derive",
  "async-graphql-parser",
@@ -345,10 +345,11 @@ dependencies = [
  "chrono",
  "fast_chemail",
  "fnv",
+ "futures-timer",
  "futures-util",
  "handlebars",
  "http 1.1.0",
- "indexmap 2.4.0",
+ "indexmap 2.5.0",
  "log",
  "mime",
  "multer",
@@ -369,9 +370,9 @@ dependencies = [
 
 [[package]]
 name = "async-graphql-axum"
-version = "7.0.7"
+version = "7.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "686e48ce7820a1cf404b5c8e9b90ae24d03c867a408d8d651183945c7a554982"
+checksum = "329afc4fc7359f112b7593bc930b788544cedbc97c4fbdf1db21e58704b4b5d0"
 dependencies = [
  "async-graphql",
  "async-trait",
@@ -387,9 +388,9 @@ dependencies = [
 
 [[package]]
 name = "async-graphql-derive"
-version = "7.0.7"
+version = "7.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72e2e26a6b44bc61df3ca8546402cf9204c28e30c06084cc8e75cd5e34d4f150"
+checksum = "f1141703c11c6ad4fa9b3b0e1e476dea01dbd18a44db00f949b804afaab2f344"
 dependencies = [
  "Inflector",
  "async-graphql-parser",
@@ -398,15 +399,15 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strum",
- "syn 2.0.75",
+ "syn 2.0.77",
  "thiserror",
 ]
 
 [[package]]
 name = "async-graphql-parser"
-version = "7.0.7"
+version = "7.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f801451484b4977d6fe67b29030f81353cabdcbb754e5a064f39493582dac0cf"
+checksum = "2f66edcce4c38c18f7eb181fdf561c3d3aa2d644ce7358fc7a928c00a4ffef17"
 dependencies = [
  "async-graphql-value",
  "pest",
@@ -416,12 +417,12 @@ dependencies = [
 
 [[package]]
 name = "async-graphql-value"
-version = "7.0.7"
+version = "7.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69117c43c01d81a69890a9f5dd6235f2f027ca8d1ec62d6d3c5e01ca0edb4f2b"
+checksum = "3b0206011cad065420c27988f17dd7fe201a0e056b20c262209b7bffcd6fa176"
 dependencies = [
  "bytes",
- "indexmap 2.4.0",
+ "indexmap 2.5.0",
  "serde",
  "serde_json",
 ]
@@ -454,7 +455,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -465,7 +466,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -825,7 +826,7 @@ dependencies = [
  "heck 0.4.1",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -1052,7 +1053,7 @@ dependencies = [
  "proc-macro-crate",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
  "syn_derive",
 ]
 
@@ -1137,7 +1138,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -1254,7 +1255,7 @@ dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -1567,7 +1568,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
 dependencies = [
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -1615,7 +1616,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -1639,7 +1640,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -1650,7 +1651,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
 dependencies = [
  "darling_core",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -1775,7 +1776,7 @@ checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -1795,7 +1796,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -1878,6 +1879,17 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "displaydoc"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.77",
+]
+
 [[package]]
 name = "dotenvy"
 version = "0.15.7"
@@ -1986,7 +1998,7 @@ dependencies = [
  "enum-ordinalize",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -1998,7 +2010,7 @@ dependencies = [
  "enum-ordinalize",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -2105,7 +2117,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -2489,7 +2501,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -2568,7 +2580,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "regex",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -2708,7 +2720,7 @@ dependencies = [
  "futures-sink",
  "futures-util",
  "http 0.2.12",
- "indexmap 2.4.0",
+ "indexmap 2.5.0",
  "slab",
  "tokio",
  "tokio-util",
@@ -2727,7 +2739,7 @@ dependencies = [
  "futures-core",
  "futures-sink",
  "http 1.1.0",
- "indexmap 2.4.0",
+ "indexmap 2.5.0",
  "slab",
  "tokio",
  "tokio-util",
@@ -2864,7 +2876,7 @@ dependencies = [
  "markup5ever",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -3103,6 +3115,124 @@ dependencies = [
  "cc",
 ]
 
+[[package]]
+name = "icu_collections"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_locid_transform_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
+
+[[package]]
+name = "icu_normalizer"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "utf16_iter",
+ "utf8_iter",
+ "write16",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
+
+[[package]]
+name = "icu_properties"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_locid_transform",
+ "icu_properties_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
+
+[[package]]
+name = "icu_provider"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_provider_macros",
+ "stable_deref_trait",
+ "tinystr",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_provider_macros"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.77",
+]
+
 [[package]]
 name = "ident_case"
 version = "1.0.1"
@@ -3119,6 +3249,18 @@ dependencies = [
  "unicode-normalization",
 ]
 
+[[package]]
+name = "idna"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd69211b9b519e98303c015e21a007e293db403b6c85b9b124e133d25e242cdd"
+dependencies = [
+ "icu_normalizer",
+ "icu_properties",
+ "smallvec",
+ "utf8_iter",
+]
+
 [[package]]
 name = "importer-models"
 version = "0.1.0"
@@ -3198,9 +3340,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.4.0"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c"
+checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
 dependencies = [
  "equivalent",
  "hashbrown 0.14.5",
@@ -3221,7 +3363,7 @@ checksum = "0122b7114117e64a63ac49f752a5ca4624d534c7b1c7de796ac196381cd2d947"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -3370,9 +3512,9 @@ dependencies = [
 
 [[package]]
 name = "lettre"
-version = "0.11.7"
+version = "0.11.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a62049a808f1c4e2356a2a380bd5f2aca3b011b0b482cf3b914ba1731426969"
+checksum = "1658ac89b01055e3ba23d66ecf6f8b97388ebe34ce125e49f8ef71234fb8aaba"
 dependencies = [
  "base64 0.22.1",
  "chumsky",
@@ -3382,7 +3524,7 @@ dependencies = [
  "futures-util",
  "hostname",
  "httpdate",
- "idna",
+ "idna 1.0.2",
  "mime",
  "native-tls",
  "nom",
@@ -3432,6 +3574,12 @@ version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
 
+[[package]]
+name = "litemap"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
+
 [[package]]
 name = "lock_api"
 version = "0.4.12"
@@ -3566,7 +3714,7 @@ checksum = "dcf09caffaac8068c346b6df2a7fc27a177fd20b39421a39ce0a211bde679a6c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -3915,7 +4063,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -3981,7 +4129,7 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -4169,7 +4317,7 @@ dependencies = [
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -4252,7 +4400,7 @@ dependencies = [
  "phf_shared 0.11.2",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -4290,7 +4438,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -4497,9 +4645,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.36"
+version = "1.0.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
 dependencies = [
  "proc-macro2",
 ]
@@ -4928,9 +5076,9 @@ dependencies = [
 
 [[package]]
 name = "rust_decimal"
-version = "1.35.0"
+version = "1.36.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a"
+checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555"
 dependencies = [
  "arrayvec",
  "borsh",
@@ -4944,9 +5092,9 @@ dependencies = [
 
 [[package]]
 name = "rust_decimal_macros"
-version = "1.35.0"
+version = "1.36.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a05bf7103af0797dbce0667c471946b29b9eaea34652eff67324f360fec027de"
+checksum = "da991f231869f34268415a49724c6578e740ad697ba0999199d6f22b3949332c"
 dependencies = [
  "quote",
  "rust_decimal",
@@ -5098,12 +5246,12 @@ dependencies = [
 
 [[package]]
 name = "schematic"
-version = "0.16.6"
+version = "0.17.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39662af6f427584874872ecc0e42888bccd0c42510d32d519c4ac9319f4c52f3"
+checksum = "414b8235f6cf6a13ed2a42df1a5f69006280ca860b2a0762afb4de8c4367db70"
 dependencies = [
  "garde",
- "indexmap 2.4.0",
+ "indexmap 2.5.0",
  "miette",
  "reqwest 0.12.7",
  "schematic_macros",
@@ -5120,26 +5268,29 @@ dependencies = [
 
 [[package]]
 name = "schematic_macros"
-version = "0.16.6"
+version = "0.17.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9747db30b2549f7a3d5c5c61e00a4da45d6fe7f4a413594ffc5e598f5ced1330"
+checksum = "641ca4c08e2735689cbc88901b755a806cbdb328a5dbddcd9176ec6de2ce59b0"
 dependencies = [
  "convert_case",
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
 name = "schematic_types"
-version = "0.8.4"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6196a0b23e5b4ee02e3894a937606fc49ccc9211e1650a9bef759062cfff3d58"
+checksum = "baae6c4555fd2a9cad6b1675fde90c8c3eff3772a1053b251d6ff0d547852e1f"
 dependencies = [
  "chrono",
- "indexmap 2.4.0",
+ "indexmap 2.5.0",
  "rust_decimal",
+ "serde_json",
+ "serde_yaml",
+ "toml",
 ]
 
 [[package]]
@@ -5184,7 +5335,7 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -5241,7 +5392,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "sea-bae",
- "syn 2.0.75",
+ "syn 2.0.77",
  "unicode-ident",
 ]
 
@@ -5301,7 +5452,7 @@ dependencies = [
  "heck 0.4.1",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
  "thiserror",
 ]
 
@@ -5325,7 +5476,7 @@ dependencies = [
  "heck 0.4.1",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -5412,9 +5563,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
 
 [[package]]
 name = "serde"
-version = "1.0.204"
+version = "1.0.209"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
+checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09"
 dependencies = [
  "serde_derive",
 ]
@@ -5443,23 +5594,24 @@ dependencies = [
 
 [[package]]
 name = "serde_derive"
-version = "1.0.204"
+version = "1.0.209"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
+checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.120"
+version = "1.0.127"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
+checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad"
 dependencies = [
- "indexmap 2.4.0",
+ "indexmap 2.5.0",
  "itoa",
+ "memchr",
  "ryu",
  "serde",
 ]
@@ -5530,7 +5682,7 @@ dependencies = [
  "chrono",
  "hex",
  "indexmap 1.9.3",
- "indexmap 2.4.0",
+ "indexmap 2.5.0",
  "serde",
  "serde_derive",
  "serde_json",
@@ -5547,7 +5699,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -5559,7 +5711,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -5568,7 +5720,7 @@ version = "0.9.34+deprecated"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
 dependencies = [
- "indexmap 2.4.0",
+ "indexmap 2.5.0",
  "itoa",
  "ryu",
  "serde",
@@ -5816,7 +5968,7 @@ dependencies = [
  "futures-util",
  "hashlink",
  "hex",
- "indexmap 2.4.0",
+ "indexmap 2.5.0",
  "log",
  "memchr",
  "native-tls",
@@ -6118,7 +6270,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustversion",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -6161,9 +6313,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.75"
+version = "2.0.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9"
+checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -6179,7 +6331,7 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -6197,6 +6349,17 @@ dependencies = [
  "futures-core",
 ]
 
+[[package]]
+name = "synstructure"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.77",
+]
+
 [[package]]
 name = "system-configuration"
 version = "0.5.1"
@@ -6297,7 +6460,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -6341,6 +6504,16 @@ dependencies = [
  "time-core",
 ]
 
+[[package]]
+name = "tinystr"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
 [[package]]
 name = "tinyvec"
 version = "1.8.0"
@@ -6382,7 +6555,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -6491,7 +6664,7 @@ version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
 dependencies = [
- "indexmap 2.4.0",
+ "indexmap 2.5.0",
  "toml_datetime",
  "winnow 0.5.40",
 ]
@@ -6502,7 +6675,7 @@ version = "0.22.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
 dependencies = [
- "indexmap 2.4.0",
+ "indexmap 2.5.0",
  "serde",
  "serde_spanned",
  "toml_datetime",
@@ -6576,7 +6749,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
 ]
 
 [[package]]
@@ -6783,7 +6956,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
 dependencies = [
  "form_urlencoded",
- "idna",
+ "idna 0.5.0",
  "percent-encoding",
  "serde",
 ]
@@ -6859,6 +7032,18 @@ version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
 
+[[package]]
+name = "utf16_iter"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
 [[package]]
 name = "utf8parse"
 version = "0.2.2"
@@ -6948,7 +7133,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
  "wasm-bindgen-shared",
 ]
 
@@ -6982,7 +7167,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -7289,6 +7474,18 @@ dependencies = [
  "windows-sys 0.48.0",
 ]
 
+[[package]]
+name = "write16"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
+
+[[package]]
+name = "writeable"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
+
 [[package]]
 name = "wyz"
 version = "0.5.1"
@@ -7310,6 +7507,30 @@ version = "0.13.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
 
+[[package]]
+name = "yoke"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.77",
+ "synstructure",
+]
+
 [[package]]
 name = "zerocopy"
 version = "0.7.35"
@@ -7328,7 +7549,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.75",
+ "syn 2.0.77",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.77",
+ "synstructure",
 ]
 
 [[package]]
@@ -7336,3 +7578,25 @@ name = "zeroize"
 version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+
+[[package]]
+name = "zerovec"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.77",
+]
diff --git a/Cargo.toml b/Cargo.toml
index f65aa6d008..dea52bbec0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -45,7 +45,7 @@ resolver = "2"
 anyhow = "=1.0.82"
 apalis = { version = "=0.5.3", features = ["cron", "limit"] }
 argon2 = "=0.6.0-pre.1"
-async-graphql = { version = "=7.0.7", features = [
+async-graphql = { version = "=7.0.9", features = [
     "chrono",
     "decimal",
     "log",
@@ -68,10 +68,11 @@ markdown = "=1.0.0-alpha.18"
 nanoid = "=0.4.0"
 openidconnect = "=3.5.0"
 regex = "=1.10.5"
-rust_decimal = "=1.35.0"
-rust_decimal_macros = "=1.35.0"
-schematic = { version = "=0.16.6", features = [
+rust_decimal = "=1.36.0"
+rust_decimal_macros = "=1.36.0"
+schematic = { version = "=0.17.4", features = [
     "config",
+    "env",
     "json",
     "schema",
     "toml",
@@ -80,6 +81,7 @@ schematic = { version = "=0.16.6", features = [
     "type_rust_decimal",
     "url",
     "renderer_template",
+    "validate",
     "yaml",
 ], default-features = false }
 sea-orm = { version = "=1.0.0", features = [
@@ -95,8 +97,8 @@ sea-orm = { version = "=1.0.0", features = [
 ], default-features = false }
 sea-orm-migration = "=1.0.0"
 sea-query = "=0.31.0"
-serde = { version = "=1.0.204", features = ["derive"] }
-serde_json = "=1.0.120"
+serde = { version = "=1.0.209", features = ["derive"] }
+serde_json = "=1.0.127"
 serde_with = { version = "=3.9.0", features = ["chrono_0_4"] }
 slug = "=0.1.5"
 strum = { version = "=0.26.2", features = ["derive"] }
diff --git a/apps/backend/Cargo.toml b/apps/backend/Cargo.toml
index cd42a5276e..f56217d0cd 100644
--- a/apps/backend/Cargo.toml
+++ b/apps/backend/Cargo.toml
@@ -10,7 +10,7 @@ anyhow = { workspace = true }
 apalis = { workspace = true }
 application-utils = { path = "../../crates/utils/application" }
 async-graphql = { workspace = true }
-async-graphql-axum = "=7.0.7"
+async-graphql-axum = "=7.0.9"
 axum = { workspace = true }
 aws-sdk-s3 = { workspace = true }
 background = { path = "../../crates/background" }
diff --git a/apps/frontend/app/routes/_dashboard.fitness.$action.tsx b/apps/frontend/app/routes/_dashboard.fitness.$action.tsx
index 65ebf58aaf..4bcc1b774a 100644
--- a/apps/frontend/app/routes/_dashboard.fitness.$action.tsx
+++ b/apps/frontend/app/routes/_dashboard.fitness.$action.tsx
@@ -690,6 +690,11 @@ type FuncStartTimer = (
 	triggeredBy: { exerciseIdentifier: string; setIdx: number },
 ) => void;
 
+const focusOnExercise = (idx: number) => {
+	const exercise = document.getElementById(idx.toString());
+	exercise?.scrollIntoView({ behavior: "smooth" });
+};
+
 const ExerciseDisplay = (props: {
 	exerciseIdx: number;
 	startTimer: FuncStartTimer;
@@ -1572,10 +1577,12 @@ const ReorderDrawer = (props: { opened: boolean; onClose: () => void }) => {
 		>
 			<DragDropContext
 				onDragEnd={({ destination, source }) => {
+					const reorderedExerciseDestinationIndex = destination?.index || 0;
 					exerciseElementsHandlers.reorder({
 						from: source.index,
-						to: destination?.index || 0,
+						to: reorderedExerciseDestinationIndex,
 					});
+					focusOnExercise(reorderedExerciseDestinationIndex);
 				}}
 			>
 				<Droppable droppableId="dnd-list">
diff --git a/crates/migrations/src/lib.rs b/crates/migrations/src/lib.rs
index 8cf39d9ad5..3f7bfd0b38 100644
--- a/crates/migrations/src/lib.rs
+++ b/crates/migrations/src/lib.rs
@@ -30,6 +30,7 @@ mod m20240828_add_last_login_on_column_to_user;
 mod m20240828_zz_add_columns_to_daily_user_activity;
 mod m20240829_change_structure_for_exercise_extra_information;
 mod m20240903_add_changes_for_user_to_collection_removal;
+mod m20240904_create_monitored_entity;
 
 pub use m20230410_create_metadata::Metadata as AliasedMetadata;
 pub use m20230413_create_person::Person as AliasedPerson;
@@ -80,6 +81,7 @@ impl MigratorTrait for Migrator {
             Box::new(m20240828_zz_add_columns_to_daily_user_activity::Migration),
             Box::new(m20240829_change_structure_for_exercise_extra_information::Migration),
             Box::new(m20240903_add_changes_for_user_to_collection_removal::Migration),
+            Box::new(m20240904_create_monitored_entity::Migration),
         ]
     }
 }
diff --git a/crates/migrations/src/m20240904_create_monitored_entity.rs b/crates/migrations/src/m20240904_create_monitored_entity.rs
new file mode 100644
index 0000000000..7b97a307ad
--- /dev/null
+++ b/crates/migrations/src/m20240904_create_monitored_entity.rs
@@ -0,0 +1,36 @@
+use indoc::indoc;
+use sea_orm_migration::prelude::*;
+
+#[derive(DeriveMigrationName)]
+pub struct Migration;
+
+pub static MONITORED_ENTITY_VIEW_CREATION_SQL: &str = indoc! { r#"
+    CREATE VIEW monitored_entity AS
+    SELECT
+        ute."user_id",
+        cte."entity_id",
+        cte."entity_lot",
+        cte."collection_id" AS "origin_collection_id"
+    FROM
+        "collection_to_entity" cte
+    JOIN
+        "collection" c ON cte."collection_id" = c."id"
+    JOIN
+        "user_to_entity" ute ON cte."collection_id" = ute."collection_id"
+    WHERE
+        c."name" = 'Monitoring'
+"# };
+
+#[async_trait::async_trait]
+impl MigrationTrait for Migration {
+    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
+        let db = manager.get_connection();
+        db.execute_unprepared(MONITORED_ENTITY_VIEW_CREATION_SQL)
+            .await?;
+        Ok(())
+    }
+
+    async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
+        Ok(())
+    }
+}
diff --git a/crates/models/database/src/lib.rs b/crates/models/database/src/lib.rs
index e2eabc7d07..707158a804 100644
--- a/crates/models/database/src/lib.rs
+++ b/crates/models/database/src/lib.rs
@@ -17,6 +17,7 @@ pub mod metadata_to_genre;
 pub mod metadata_to_metadata;
 pub mod metadata_to_metadata_group;
 pub mod metadata_to_person;
+pub mod monitored_entity;
 pub mod notification_platform;
 pub mod person;
 pub mod queued_notification;
diff --git a/crates/models/database/src/monitored_entity.rs b/crates/models/database/src/monitored_entity.rs
new file mode 100644
index 0000000000..d761d28aa1
--- /dev/null
+++ b/crates/models/database/src/monitored_entity.rs
@@ -0,0 +1,22 @@
+//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2
+
+use enums::EntityLot;
+use sea_orm::entity::prelude::*;
+use serde::{Deserialize, Serialize};
+
+#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
+#[sea_orm(table_name = "monitored_entity")]
+pub struct Model {
+    #[sea_orm(primary_key, auto_increment = false)]
+    pub user_id: String,
+    #[sea_orm(primary_key, auto_increment = false)]
+    pub entity_id: String,
+    #[sea_orm(primary_key, auto_increment = false)]
+    pub entity_lot: EntityLot,
+    pub origin_collection_id: String,
+}
+
+#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
+pub enum Relation {}
+
+impl ActiveModelBehavior for ActiveModel {}
diff --git a/crates/models/database/src/prelude.rs b/crates/models/database/src/prelude.rs
index bd4c56078d..e8f20aa054 100644
--- a/crates/models/database/src/prelude.rs
+++ b/crates/models/database/src/prelude.rs
@@ -14,6 +14,7 @@ pub use super::metadata_to_genre::Entity as MetadataToGenre;
 pub use super::metadata_to_metadata::Entity as MetadataToMetadata;
 pub use super::metadata_to_metadata_group::Entity as MetadataToMetadataGroup;
 pub use super::metadata_to_person::Entity as MetadataToPerson;
+pub use super::monitored_entity::Entity as MonitoredEntity;
 pub use super::notification_platform::Entity as NotificationPlatform;
 pub use super::person::Entity as Person;
 pub use super::queued_notification::Entity as QueuedNotification;
diff --git a/crates/services/miscellaneous/src/lib.rs b/crates/services/miscellaneous/src/lib.rs
index c76ec75f53..9c8ac28d34 100644
--- a/crates/services/miscellaneous/src/lib.rs
+++ b/crates/services/miscellaneous/src/lib.rs
@@ -24,13 +24,13 @@ use database_models::{
     calendar_event, collection, collection_to_entity,
     functions::{associate_user_with_entity, get_user_to_entity_association},
     genre, import_report, integration, metadata, metadata_group, metadata_to_genre,
-    metadata_to_metadata, metadata_to_metadata_group, metadata_to_person, notification_platform,
-    person,
+    metadata_to_metadata, metadata_to_metadata_group, metadata_to_person, monitored_entity,
+    notification_platform, person,
     prelude::{
         CalendarEvent, Collection, CollectionToEntity, Genre, ImportReport, Integration, Metadata,
         MetadataGroup, MetadataToGenre, MetadataToMetadata, MetadataToMetadataGroup,
-        MetadataToPerson, NotificationPlatform, Person, QueuedNotification, Review, Seen, User,
-        UserToEntity,
+        MetadataToPerson, MonitoredEntity, NotificationPlatform, Person, QueuedNotification,
+        Review, Seen, User, UserToEntity,
     },
     queued_notification, review, seen, user, user_to_entity,
 };
@@ -94,7 +94,7 @@ use rust_decimal::Decimal;
 use rust_decimal_macros::dec;
 use sea_orm::{
     prelude::DateTimeUtc, sea_query::NullOrdering, ActiveModelTrait, ActiveValue, ColumnTrait,
-    ConnectionTrait, DatabaseBackend, DatabaseConnection, DbBackend, EntityTrait, FromQueryResult,
+    ConnectionTrait, DatabaseBackend, DatabaseConnection, EntityTrait, FromQueryResult,
     ItemsAndPagesNumber, Iterable, JoinType, ModelTrait, Order, PaginatorTrait, QueryFilter,
     QueryOrder, QuerySelect, QueryTrait, RelationTrait, Statement, TransactionTrait,
 };
@@ -188,8 +188,6 @@ impl MiscellaneousService {
     }
 }
 
-type EntityBeingMonitoredByMap = HashMap<String, Vec<String>>;
-
 impl MiscellaneousService {
     pub async fn core_details(&self) -> CoreDetails {
         let mut files_enabled = self.config.file_storage.is_enabled();
@@ -2805,8 +2803,9 @@ impl MiscellaneousService {
             .await
             .unwrap();
         if !notifications.is_empty() {
-            let (meta_map, _, _) = self.get_entities_monitored_by().await.unwrap();
-            let users_to_notify = meta_map.get(metadata_id).cloned().unwrap_or_default();
+            let users_to_notify = self
+                .get_entities_monitored_by(metadata_id, EntityLot::Metadata)
+                .await?;
             for notification in notifications {
                 for user_id in users_to_notify.iter() {
                     self.queue_media_state_changed_notification_for_user(user_id, &notification)
@@ -3453,8 +3452,26 @@ impl MiscellaneousService {
         Ok(true)
     }
 
+    async fn get_monitored_entities(
+        &self,
+        entity_lot: EntityLot,
+    ) -> Result<HashMap<String, HashSet<String>>> {
+        let monitored_entities = MonitoredEntity::find()
+            .filter(monitored_entity::Column::EntityLot.eq(entity_lot))
+            .all(&self.db)
+            .await?;
+        let mut monitored_by = HashMap::new();
+        for entity in monitored_entities {
+            let user_ids = monitored_by
+                .entry(entity.entity_id)
+                .or_insert(HashSet::new());
+            user_ids.insert(entity.user_id);
+        }
+        Ok(monitored_by)
+    }
+
     async fn update_watchlist_metadata_and_queue_notifications(&self) -> Result<()> {
-        let (meta_map, _, _) = self.get_entities_monitored_by().await?;
+        let meta_map = self.get_monitored_entities(EntityLot::Metadata).await?;
         ryot_log!(
             debug,
             "Users to be notified for metadata state changes: {:?}",
@@ -3473,7 +3490,7 @@ impl MiscellaneousService {
     }
 
     async fn update_monitored_people_and_queue_notifications(&self) -> Result<()> {
-        let (_, _, person_map) = self.get_entities_monitored_by().await?;
+        let person_map = self.get_monitored_entities(EntityLot::Person).await?;
         ryot_log!(
             debug,
             "Users to be notified for people state changes: {:?}",
@@ -4127,9 +4144,10 @@ impl MiscellaneousService {
                 )
             })
             .collect_vec();
-        let (meta_map, _, _) = self.get_entities_monitored_by().await?;
         for (metadata_id, notification) in notifications.into_iter() {
-            let users_to_notify = meta_map.get(&metadata_id).cloned().unwrap_or_default();
+            let users_to_notify = self
+                .get_entities_monitored_by(&metadata_id, EntityLot::Metadata)
+                .await?;
             for user in users_to_notify {
                 self.queue_media_state_changed_notification_for_user(&user, &notification)
                     .await?;
@@ -4217,8 +4235,9 @@ impl MiscellaneousService {
             .await
             .unwrap_or_default();
         if !notifications.is_empty() {
-            let (_, _, person_map) = self.get_entities_monitored_by().await.unwrap();
-            let users_to_notify = person_map.get(&person_id).cloned().unwrap_or_default();
+            let users_to_notify = self
+                .get_entities_monitored_by(&person_id, EntityLot::Person)
+                .await?;
             for notification in notifications {
                 for user_id in users_to_notify.iter() {
                     self.queue_media_state_changed_notification_for_user(user_id, &notification)
@@ -4232,72 +4251,24 @@ impl MiscellaneousService {
 
     async fn get_entities_monitored_by(
         &self,
-    ) -> Result<(
-        EntityBeingMonitoredByMap,
-        EntityBeingMonitoredByMap,
-        EntityBeingMonitoredByMap,
-    )> {
-        #[derive(Debug, FromQueryResult, Clone, Default)]
-        struct UsersToBeNotified {
-            entity_id: String,
-            to_notify: Vec<String>,
-        }
-        let get_sql = |entity_type: &str| {
-            format!(
-                r#"
-SELECT
-    m.id as entity_id,
-    array_agg(DISTINCT u.id) as to_notify
-FROM {entity_type} m
-JOIN collection_to_entity cte ON m.id = cte.{entity_type}_id
-JOIN collection c ON cte.collection_id = c.id AND c.name = '{}'
-JOIN "user" u ON c.user_id = u.id
-GROUP BY m.id;
-        "#,
-                DefaultCollection::Monitoring
-            )
-        };
-        let meta_map: Vec<_> = UsersToBeNotified::find_by_statement(
-            Statement::from_sql_and_values(DbBackend::Postgres, get_sql("metadata"), []),
-        )
-        .all(&self.db)
-        .await?;
-        let meta_map = meta_map
-            .into_iter()
-            .map(|m| (m.entity_id, m.to_notify))
-            .collect::<EntityBeingMonitoredByMap>();
-        let meta_group_map: Vec<_> = UsersToBeNotified::find_by_statement(
-            Statement::from_sql_and_values(DbBackend::Postgres, get_sql("metadata_group"), []),
-        )
-        .all(&self.db)
-        .await?;
-        let meta_group_map = meta_group_map
-            .into_iter()
-            .map(|m| (m.entity_id, m.to_notify))
-            .collect::<EntityBeingMonitoredByMap>();
-        let person_map: Vec<_> = UsersToBeNotified::find_by_statement(
-            Statement::from_sql_and_values(DbBackend::Postgres, get_sql("person"), []),
-        )
-        .all(&self.db)
-        .await?;
-        let person_map = person_map
-            .into_iter()
-            .map(|m| (m.entity_id, m.to_notify))
-            .collect::<EntityBeingMonitoredByMap>();
-        Ok((meta_map, meta_group_map, person_map))
+        entity_id: &String,
+        entity_lot: EntityLot,
+    ) -> Result<Vec<String>> {
+        let all_entities = MonitoredEntity::find()
+            .select_only()
+            .column(monitored_entity::Column::UserId)
+            .filter(monitored_entity::Column::EntityId.eq(entity_id))
+            .filter(monitored_entity::Column::EntityLot.eq(entity_lot))
+            .into_tuple::<String>()
+            .all(&self.db)
+            .await?;
+        Ok(all_entities)
     }
 
     pub async fn handle_review_posted_event(&self, event: ReviewPostedEvent) -> Result<()> {
-        let (meta_map, meta_group_map, person_map) = self.get_entities_monitored_by().await?;
-        let monitored_by = match event.entity_lot {
-            EntityLot::Metadata => meta_map.get(&event.obj_id).cloned().unwrap_or_default(),
-            EntityLot::MetadataGroup => meta_group_map
-                .get(&event.obj_id)
-                .cloned()
-                .unwrap_or_default(),
-            EntityLot::Person => person_map.get(&event.obj_id).cloned().unwrap_or_default(),
-            _ => vec![],
-        };
+        let monitored_by = self
+            .get_entities_monitored_by(&event.obj_id, event.entity_lot)
+            .await?;
         let users = User::find()
             .select_only()
             .column(user::Column::Id)
diff --git a/crates/services/notification/Cargo.toml b/crates/services/notification/Cargo.toml
index d1fec18d0d..adb0ec6379 100644
--- a/crates/services/notification/Cargo.toml
+++ b/crates/services/notification/Cargo.toml
@@ -9,7 +9,7 @@ askama = "0.12.1"
 common-utils = { path = "../../utils/common" }
 config = { path = "../../config" }
 convert_case = { workspace = true }
-lettre = "=0.11.7"
+lettre = "=0.11.8"
 reqwest = { workspace = true }
 serde = { workspace = true }
 serde_json = { workspace = true }


Test patch: