@@ -57,6 +57,16 @@ public async Task<HttpResponseMessage> Message([HttpTrigger(AuthorizationLevel.A
5757
5858 if ( await WhatsApp . Message . DeserializeAsync ( json ) is { } message )
5959 {
60+ // Ensure idempotent processing
61+ var table = tableClient . GetTableClient ( "whatsapp" ) ;
62+ await table . CreateIfNotExistsAsync ( ) ;
63+ if ( await table . GetEntityIfExistsAsync < TableEntity > ( message . From . Number , message . Id ) is { HasValue : true } existing )
64+ {
65+ logger . LogInformation ( "Skipping already handled message {Id}" , message . Id ) ;
66+ return new HttpResponseMessage ( System . Net . HttpStatusCode . OK ) ;
67+ }
68+
69+ // Otherwise, queue the new message
6070 var queue = queueClient . GetQueueClient ( "whatsapp" ) ;
6171 await queue . CreateIfNotExistsAsync ( ) ;
6272 await queue . SendMessageAsync ( json ) ;
@@ -78,7 +88,9 @@ public async Task Process([QueueTrigger("whatsapp", Connection = "AzureWebJobsSt
7888
7989 if ( await WhatsApp . Message . DeserializeAsync ( json ) is { } message )
8090 {
81- // Ensure idempotent processing
91+ // Ensure idempotent processing at dequeue time, since we might have been called
92+ // multiple times for the same message by WhatsApp (Message method) while processing was still
93+ // happening (and therefore we didn't save the entity yet).
8294 var table = tableClient . GetTableClient ( "whatsapp" ) ;
8395 await table . CreateIfNotExistsAsync ( ) ;
8496 if ( await table . GetEntityIfExistsAsync < TableEntity > ( message . From . Number , message . Id ) is { HasValue : true } existing )
0 commit comments