@@ -25,8 +25,7 @@ use serde_json::json;
2525use sha2:: Sha256 ;
2626
2727use crate :: state:: {
28- AppState , load_keyword_filter_cache, recompute_keyword_blocked,
29- recompute_stream_keyword_blocked,
28+ AppState , KwRecomputeKind , kw_recompute_single_flight, load_keyword_filter_cache,
3029} ;
3130
3231// ─── Auth helpers ─────────────────────────────────────────────────────────────
@@ -146,23 +145,18 @@ pub struct WhitelistRow {
146145async fn reload_cache ( state : & AppState ) {
147146 let mut new_cache = load_keyword_filter_cache ( & state. pool ) . await ;
148147 new_cache. nsfw_filter_enabled = state. config . poster_nsfw_enabled ;
149- let media_ver = new_cache. media_version_tag ( ) ;
150- let stream_ver = new_cache. version_tag ( ) ;
151- let keywords = new_cache. keywords . clone ( ) ;
152- let stream_kws = new_cache. stream_keywords . clone ( ) ;
153- let whitelist = new_cache. whitelist . clone ( ) ;
154- let whitelist2 = whitelist. clone ( ) ;
155148 if let Ok ( mut w) = state. keyword_filters . write ( ) {
156149 * w = new_cache;
157150 }
151+ // Converge the blocked flags via the deployment-wide single-flight lease —
152+ // an admin keyword edit must not launch unguarded full-table sweeps
153+ // alongside whatever other processes are doing.
158154 let pool = state. pool . clone ( ) ;
159155 let pool2 = pool. clone ( ) ;
160- tokio:: spawn ( async move {
161- recompute_keyword_blocked ( & pool, media_ver, & keywords, & whitelist) . await
162- } ) ;
163- tokio:: spawn ( async move {
164- recompute_stream_keyword_blocked ( & pool2, stream_ver, & stream_kws, & whitelist2) . await
165- } ) ;
156+ tokio:: spawn ( async move { kw_recompute_single_flight ( & pool, KwRecomputeKind :: Media ) . await } ) ;
157+ tokio:: spawn (
158+ async move { kw_recompute_single_flight ( & pool2, KwRecomputeKind :: Stream ) . await } ,
159+ ) ;
166160}
167161
168162// ─── Handlers ────────────────────────────────────────────────────────────────
0 commit comments