@@ -149,8 +149,19 @@ Func<ReadOnlyMemory<byte>, CancellationToken, Task> handler
149149 _handler = handler ;
150150 }
151151
152+ // SNS only fans a publish out to subscriptions that are already confirmed at publish time
153+ // (unlike a plain SQS queue, it does not buffer for endpoints that subscribe later), so the
154+ // subscribe/queue/policy/SNS-subscribe wiring below must complete before Start() returns.
155+ // This mirrors RabbitMqTopicProvider.Subscription.Start(), which blocks the same way.
152156 public void Start ( )
153- => _loop = Task . Run ( ( ) => RunAsync ( _cts . Token ) ) ;
157+ {
158+ var queueUrl = SetupAsync ( _cts . Token ) . GetAwaiter ( ) . GetResult ( ) ;
159+
160+ if ( queueUrl is not null )
161+ {
162+ _loop = Task . Run ( ( ) => ReceiveLoopAsync ( queueUrl , _cts . Token ) ) ;
163+ }
164+ }
154165
155166 private static string BuildPolicy ( string queueArn , string topicArn )
156167 => JsonSerializer . Serialize (
@@ -171,18 +182,21 @@ private static string BuildPolicy(string queueArn, string topicArn)
171182 }
172183 ) ;
173184
174- private async Task RunAsync ( CancellationToken cancellationToken )
185+ /// <summary>
186+ /// Creates the subscriber's dedicated queue, grants SNS permission to send to it and
187+ /// confirms the SNS subscription. Returns the queue URL once the subscription is fully
188+ /// wired and ready to receive fanned-out messages, or null on failure/cancellation.
189+ /// </summary>
190+ private async Task < string ? > SetupAsync ( CancellationToken cancellationToken )
175191 {
176- string queueUrl ;
177-
178192 try
179193 {
180194 var topicArn = await _provider . EnsureTopicAsync ( _topic , cancellationToken ) ;
181195 var queueName = SqsNames . Sanitize ( _topic ) + "-sub-" + _index ;
182- queueUrl = ( await _provider . _sqs ! . CreateQueueAsync (
183- new CreateQueueRequest { QueueName = queueName } ,
184- cancellationToken
185- ) ) . QueueUrl ;
196+ var queueUrl = ( await _provider . _sqs ! . CreateQueueAsync (
197+ new CreateQueueRequest { QueueName = queueName } ,
198+ cancellationToken
199+ ) ) . QueueUrl ;
186200 _queueUrl = queueUrl ;
187201
188202 var attributes = await _provider . _sqs . GetQueueAttributesAsync (
@@ -211,18 +225,23 @@ await _provider._sqs.SetQueueAttributesAsync(
211225 } ,
212226 cancellationToken
213227 ) ) . SubscriptionArn ;
228+
229+ return queueUrl ;
214230 }
215231 catch ( OperationCanceledException )
216232 {
217- return ;
233+ return null ;
218234 }
219235 catch ( Exception ex )
220236 {
221237 _provider . _logger . Warning ( ex , "SQS topic '{Topic}' subscribe setup failed" , _topic ) ;
222238
223- return ;
239+ return null ;
224240 }
241+ }
225242
243+ private async Task ReceiveLoopAsync ( string queueUrl , CancellationToken cancellationToken )
244+ {
226245 while ( ! cancellationToken . IsCancellationRequested )
227246 {
228247 ReceiveMessageResponse response ;
0 commit comments