@@ -37,24 +37,30 @@ internal sealed class AlarmPairingCoordinator(
3737 public async Task HandlePairedAsync ( AlarmPairedEvent evt , CancellationToken cancellationToken )
3838 {
3939 ArgumentNullException . ThrowIfNull ( evt ) ;
40- if ( await ExistsAsync ( evt . GuildId , evt . ServerId , evt . EntityId , cancellationToken ) . ConfigureAwait ( false ) )
41- {
42- return ;
43- }
4440
45- var channelId = await locator . GetChannelIdAsync ( evt . GuildId , evt . ServerId , cancellationToken )
46- . ConfigureAwait ( false ) ;
47- if ( channelId is not { } channel )
41+ var scope = scopeFactory . CreateAsyncScope ( ) ;
42+ await using ( scope . ConfigureAwait ( false ) )
4843 {
49- return ;
50- }
44+ var store = scope . ServiceProvider . GetRequiredService < IAlarmStore > ( ) ;
45+ if ( await store . ExistsAsync ( evt . GuildId , evt . ServerId , evt . EntityId , cancellationToken ) . ConfigureAwait ( false ) )
46+ {
47+ return ;
48+ }
5149
52- var culture = await GetCultureAsync ( evt . GuildId , cancellationToken ) . ConfigureAwait ( false ) ;
53- var defaultName = $ "Alarm { evt . EntityId } ";
54- var ( embed , components ) = renderer . RenderPrompt ( evt . ServerId , evt . EntityId , defaultName , culture ) ;
55- var messageId = await poster . EnsureAsync ( channel , null , embed , components , cancellationToken )
56- . ConfigureAwait ( false ) ;
57- _pending [ ( evt . GuildId , evt . ServerId , evt . EntityId ) ] = new Pending ( defaultName , messageId ) ;
50+ var channelId = await locator . GetChannelIdAsync ( evt . GuildId , evt . ServerId , cancellationToken )
51+ . ConfigureAwait ( false ) ;
52+ if ( channelId is not { } channel )
53+ {
54+ return ;
55+ }
56+
57+ var culture = await GetCultureAsync ( scope . ServiceProvider , evt . GuildId , cancellationToken ) . ConfigureAwait ( false ) ;
58+ var defaultName = $ "Alarm { evt . EntityId } ";
59+ var ( embed , components ) = renderer . RenderPrompt ( evt . ServerId , evt . EntityId , defaultName , culture ) ;
60+ var messageId = await poster . EnsureAsync ( channel , null , embed , components , cancellationToken )
61+ . ConfigureAwait ( false ) ;
62+ _pending [ ( evt . GuildId , evt . ServerId , evt . EntityId ) ] = new Pending ( defaultName , messageId ) ;
63+ }
5864 }
5965
6066 /// <summary>Accepts a pending pairing: persist + replace prompt with the alarm embed. Race-guarded.</summary>
@@ -71,26 +77,26 @@ public async Task<bool> TryAcceptAsync(
7177 ulong acceptingUserId ,
7278 CancellationToken cancellationToken )
7379 {
74- if ( await ExistsAsync ( guildId , serverId , entityId , cancellationToken ) . ConfigureAwait ( false ) )
75- {
76- _pending . TryRemove ( ( guildId , serverId , entityId ) , out _ ) ;
77- return false ;
78- }
79-
8080 _pending . TryGetValue ( ( guildId , serverId , entityId ) , out var pending ) ;
8181 var name = pending ? . DefaultName ?? $ "Alarm { entityId } ";
8282
8383 var scope = scopeFactory . CreateAsyncScope ( ) ;
8484 await using ( scope . ConfigureAwait ( false ) )
8585 {
8686 var store = scope . ServiceProvider . GetRequiredService < IAlarmStore > ( ) ;
87+ if ( await store . ExistsAsync ( guildId , serverId , entityId , cancellationToken ) . ConfigureAwait ( false ) )
88+ {
89+ _pending . TryRemove ( ( guildId , serverId , entityId ) , out _ ) ;
90+ return false ;
91+ }
92+
8793 var added = await store . AddAsync ( guildId , serverId , entityId , name , acceptingUserId , cancellationToken )
8894 . ConfigureAwait ( false ) ;
8995
9096 var channelId = await locator . GetChannelIdAsync ( guildId , serverId , cancellationToken ) . ConfigureAwait ( false ) ;
9197 if ( channelId is { } channel )
9298 {
93- var culture = await GetCultureAsync ( guildId , cancellationToken ) . ConfigureAwait ( false ) ;
99+ var culture = await GetCultureAsync ( scope . ServiceProvider , guildId , cancellationToken ) . ConfigureAwait ( false ) ;
94100
95101 // The alarm is freshly accepted; unreachable is false (it just paired).
96102 // The supervisor's prime path will re-render real state shortly.
@@ -118,24 +124,10 @@ await store.SetMessageIdAsync(guildId, serverId, entityId, mid, cancellationToke
118124 public bool TryDismiss ( ulong guildId , Guid serverId , ulong entityId ) =>
119125 _pending . TryRemove ( ( guildId , serverId , entityId ) , out _ ) ;
120126
121- private async Task < bool > ExistsAsync ( ulong guildId , Guid serverId , ulong entityId , CancellationToken ct )
122- {
123- var scope = scopeFactory . CreateAsyncScope ( ) ;
124- await using ( scope . ConfigureAwait ( false ) )
125- {
126- var store = scope . ServiceProvider . GetRequiredService < IAlarmStore > ( ) ;
127- return await store . ExistsAsync ( guildId , serverId , entityId , ct ) . ConfigureAwait ( false ) ;
128- }
129- }
130-
131- private async Task < string > GetCultureAsync ( ulong guildId , CancellationToken ct )
127+ private static async Task < string > GetCultureAsync ( IServiceProvider provider , ulong guildId , CancellationToken ct )
132128 {
133- var scope = scopeFactory . CreateAsyncScope ( ) ;
134- await using ( scope . ConfigureAwait ( false ) )
135- {
136- var store = scope . ServiceProvider . GetRequiredService < IWorkspaceStore > ( ) ;
137- return await store . GetCultureAsync ( guildId , ct ) . ConfigureAwait ( false ) ;
138- }
129+ var store = provider . GetRequiredService < IWorkspaceStore > ( ) ;
130+ return await store . GetCultureAsync ( guildId , ct ) . ConfigureAwait ( false ) ;
139131 }
140132
141133 private sealed record Pending ( string DefaultName , ulong ? MessageId ) ;
0 commit comments