@@ -20,11 +20,12 @@ use std::{pin::pin, time::Instant};
20
20
21
21
use chrono:: { DateTime , Utc } ;
22
22
use compact_str:: CompactString ;
23
- use futures_util:: StreamExt as _;
23
+ use futures_util:: { SinkExt , StreamExt as _, TryStreamExt as _ } ;
24
24
use mas_storage:: Clock ;
25
25
use rand:: { RngCore , SeedableRng } ;
26
26
use thiserror:: Error ;
27
27
use thiserror_ext:: ContextInto ;
28
+ use tokio_util:: sync:: PollSender ;
28
29
use tracing:: { info, Level , Span } ;
29
30
use tracing_indicatif:: span_ext:: IndicatifSpanExt ;
30
31
use ulid:: Ulid ;
@@ -61,6 +62,8 @@ pub enum Error {
61
62
source : ExtractLocalpartError ,
62
63
user : FullUserId ,
63
64
} ,
65
+ #[ error( "channel closed" ) ]
66
+ ChannelClosed ,
64
67
#[ error( "user {user} was not found for migration but a row in {table} was found for them" ) ]
65
68
MissingUserFromDependentTable { table : String , user : FullUserId } ,
66
69
#[ error( "missing a mapping for the auth provider with ID {synapse_id:?} (used by {user} and maybe other users)" ) ]
@@ -154,7 +157,7 @@ pub async fn migrate(
154
157
. await ?;
155
158
156
159
// `(MAS user_id, device_id)` mapped to `compat_session` ULID
157
- let mut devices_to_compat_sessions: HashMap < ( Uuid , CompactString ) , Uuid > =
160
+ let devices_to_compat_sessions: HashMap < ( Uuid , CompactString ) , Uuid > =
158
161
HashMap :: with_capacity_and_hasher (
159
162
usize:: try_from ( counts. devices )
160
163
. expect ( "More than usize::MAX devices — unable to handle this many!" )
@@ -166,9 +169,9 @@ pub async fn migrate(
166
169
167
170
span. pb_set_message ( "migrating access tokens" ) ;
168
171
span. pb_inc ( 1 ) ;
169
- migrate_unrefreshable_access_tokens (
172
+ let ( mas , devices_to_compat_sessions ) = migrate_unrefreshable_access_tokens (
170
173
& mut synapse,
171
- & mut mas,
174
+ mas,
172
175
counts
173
176
. access_tokens
174
177
. try_into ( )
@@ -177,7 +180,7 @@ pub async fn migrate(
177
180
clock,
178
181
rng,
179
182
& migrated_users. user_localparts_to_uuid ,
180
- & mut devices_to_compat_sessions,
183
+ devices_to_compat_sessions,
181
184
)
182
185
. await ?;
183
186
@@ -244,9 +247,6 @@ async fn migrate_users(
244
247
) -> Result < ( UsersMigrated , MasWriter ) , Error > {
245
248
let start = Instant :: now ( ) ;
246
249
247
- let mut users_stream = pin ! ( synapse
248
- . read_users( )
249
- . with_progress_bar( user_count_hint as u64 , 10_000 ) ) ;
250
250
let ( tx, mut rx) = tokio:: sync:: mpsc:: channel ( 1024 * 1024 ) ;
251
251
252
252
let mut rng = rand_chacha:: ChaCha8Rng :: from_rng ( rng) . expect ( "failed to seed rng" ) ;
@@ -299,10 +299,12 @@ async fn migrate_users(
299
299
Ok ( ( synapse_admins, user_localparts_to_uuid, mas) )
300
300
} ) ;
301
301
302
- while let Some ( user_res) = users_stream. next ( ) . await {
303
- let user = user_res. into_synapse ( "reading user" ) ?;
304
- tx. send ( user) . await . expect ( "failed to send in channel" ) ;
305
- }
302
+ synapse
303
+ . read_users ( )
304
+ . with_progress_bar ( user_count_hint as u64 , 10_000 )
305
+ . map_err ( |e| e. into_synapse ( "reading users" ) )
306
+ . forward ( PollSender :: new ( tx) . sink_map_err ( |_| Error :: ChannelClosed ) )
307
+ . await ?;
306
308
307
309
let ( synapse_admins, user_localparts_to_uuid, mas) = task. await . expect ( "task panicked" ) ?;
308
310
@@ -611,22 +613,22 @@ async fn migrate_devices(
611
613
#[ allow( clippy:: too_many_arguments) ]
612
614
async fn migrate_unrefreshable_access_tokens (
613
615
synapse : & mut SynapseReader < ' _ > ,
614
- mas : & mut MasWriter ,
616
+ mas : MasWriter ,
615
617
count_hint : u64 ,
616
618
server_name : & str ,
617
619
clock : & dyn Clock ,
618
620
rng : & mut impl RngCore ,
619
621
user_localparts_to_uuid : & HashMap < CompactString , Uuid > ,
620
- devices : & mut HashMap < ( Uuid , CompactString ) , Uuid > ,
621
- ) -> Result < ( ) , Error > {
622
+ devices : HashMap < ( Uuid , CompactString ) , Uuid > ,
623
+ ) -> Result < ( MasWriter , HashMap < ( Uuid , CompactString ) , Uuid > ) , Error > {
622
624
let start = Instant :: now ( ) ;
623
625
624
626
let mut token_stream = pin ! ( synapse
625
627
. read_unrefreshable_access_tokens( )
626
628
. with_progress_bar( count_hint, 10_000 ) ) ;
627
- let mut write_buffer = MasWriteBuffer :: new ( mas, MasWriter :: write_compat_access_tokens) ;
629
+ let mut write_buffer = MasWriteBuffer :: new ( & mas, MasWriter :: write_compat_access_tokens) ;
628
630
let mut deviceless_session_write_buffer =
629
- MasWriteBuffer :: new ( mas, MasWriter :: write_compat_sessions) ;
631
+ MasWriteBuffer :: new ( & mas, MasWriter :: write_compat_sessions) ;
630
632
631
633
while let Some ( token_res) = token_stream. next ( ) . await {
632
634
let SynapseAccessToken {
@@ -672,7 +674,7 @@ async fn migrate_unrefreshable_access_tokens(
672
674
673
675
deviceless_session_write_buffer
674
676
. write (
675
- mas,
677
+ & mut mas,
676
678
MasNewCompatSession {
677
679
session_id : deviceless_session_id,
678
680
user_id,
@@ -696,7 +698,7 @@ async fn migrate_unrefreshable_access_tokens(
696
698
// TODO skip access tokens for deactivated users
697
699
write_buffer
698
700
. write (
699
- mas,
701
+ & mut mas,
700
702
MasNewCompatAccessToken {
701
703
token_id,
702
704
session_id,
@@ -710,11 +712,11 @@ async fn migrate_unrefreshable_access_tokens(
710
712
}
711
713
712
714
write_buffer
713
- . finish ( mas)
715
+ . finish ( & mut mas)
714
716
. await
715
717
. into_mas ( "writing compat access tokens" ) ?;
716
718
deviceless_session_write_buffer
717
- . finish ( mas)
719
+ . finish ( & mut mas)
718
720
. await
719
721
. into_mas ( "writing deviceless compat sessions" ) ?;
720
722
@@ -723,7 +725,7 @@ async fn migrate_unrefreshable_access_tokens(
723
725
Instant :: now( ) . duration_since( start) . as_secs_f64( )
724
726
) ;
725
727
726
- Ok ( ( ) )
728
+ Ok ( ( mas , devices_to_compat_sessions ) )
727
729
}
728
730
729
731
/// Migrates (access token, refresh token) pairs.
0 commit comments