tuwunel_service/migrations/
upgrade_legacy_mediaid_user.rs1use ruma::UserId;
2use tuwunel_core::{
3 Result, info,
4 utils::{ReadyExt, stream::TryIgnore},
5 warn,
6};
7use tuwunel_database::SEP;
8
9use crate::Services;
10
11pub(super) async fn upgrade_legacy_mediaid_user(services: &Services) -> Result {
12 let db = &services.db;
13 let cork = db.cork_and_sync();
14 let mediaid_user = db["mediaid_user"].clone();
15
16 warn!("Upgrading legacy mediaid_user keys to composite (mxc, user_id) layout");
17
18 let (checked, upgraded, removed_invalid) = mediaid_user
19 .raw_stream()
20 .ignore_err()
21 .ready_fold(
22 (0_usize, 0_usize, 0_usize),
23 |(mut checked, mut upgraded, mut removed_invalid), (raw_key, raw_val)| {
24 checked = checked.saturating_add(1);
25
26 let has_sep = raw_key.contains(&SEP);
27 let user_id = str::from_utf8(raw_val)
28 .ok()
29 .and_then(|s| <&UserId>::try_from(s).ok());
30
31 match (has_sep, user_id) {
32 | (true, _) => {},
33 | (false, None) => {
34 warn!(
35 ?raw_key,
36 ?raw_val,
37 "Legacy entry has unparsable user_id, removing"
38 );
39
40 mediaid_user.remove(raw_key);
41 removed_invalid = removed_invalid.saturating_add(1);
42 },
43 | (false, Some(user_id)) => {
44 let mut new_key = raw_key.to_vec();
45
46 new_key.push(SEP);
47 new_key.extend_from_slice(user_id.as_bytes());
48
49 mediaid_user.put_raw(new_key, user_id.as_str());
50 mediaid_user.remove(raw_key);
51
52 upgraded = upgraded.saturating_add(1);
53 },
54 }
55
56 (checked, upgraded, removed_invalid)
57 },
58 )
59 .await;
60
61 drop(cork);
62 info!(
63 %checked,
64 %upgraded,
65 %removed_invalid,
66 "Upgraded legacy mediaid_user keys"
67 );
68
69 db["global"].insert(b"upgrade_legacy_mediaid_user", []);
70 mediaid_user.sort()
71}