c# - Handling service bus Message.Complete() exceptions -


consider scenario, azure service bus message deduplication enabled, single topic, single subscription , application subscribed queue.

how can ensure application receives messages queue once , once ?

here code i'm using in application receive messages :

public abstract class servicebuslistener<t> : iservicebuslistener {     private subscriptionclient subscriptionclient;     // ..... snip      private void receivemessages()     {         message = this.subscriptionclient.receive(timespan.fromseconds(5));          if (message != null)         {             t payload = message.getbody<t>(message);                                                  try             {                 dowork(payload);                  message.complete();             }             catch (exception exception)             {                 // message.complete failed             }         }     } } 

the problem forsee if message.complete() fails whatever reason, message has been processed remain on subscription's queue in azure. when receivemessages() called again pick same message queue , application same work again.

whilst best solution have idempotent domain logic (dowork(payload)), difficult write in instance.

the method can see ensure once , once delivery application building queue act intermediary between azure service bus , application. believe called 'durable client-side queue'.

however can see potential issue lot of applications use azure service bus, durable client-side queue solution ?

i have similar challenges in large scale azure platform responsible for. use logical combination of concepts embodied compensating transaction pattern (https://msdn.microsoft.com/en-us/library/dn589804.aspx), , event sourcing pattern (https://msdn.microsoft.com/en-us/library/dn589792.aspx). how incorporate these concepts vary, ultimately, may need plan on own "rollback" logic, or detecting previous process completed 100% minus removal of message. if there check upfront, know message not removed, complete , move on. how expensive "check" may make bad idea. can "create" artificial final step, adding row db, runs when dowork reaches end. can check row before processing other messages.

imo, best approach make sure of steps in dowork() check existence of work having been performed (if possible). example, if it's creating db table, run "if not exists(select table_name information_schema...". in scenario, in unlikely event happens, it's safe process message again.

other approaches use store messageid's (the sequential bigint on each message) of previous x messages (i.e. 10,000), , check existence (not in) before proceed processing message. not expensive might think , safe. if found, complete() message , move on. in other situations, update message "starting" type status (inline in queue types, persisted elsewhere in others), proceed. if read message , set "started", know either failed or did not clear appropriately.

sorry not clear cut answer, there lot of considerations.

kindest regards...


Comments

Popular posts from this blog

powershell Start-Process exit code -1073741502 when used with Credential from a windows service environment -

twig - Using Twigbridge in a Laravel 5.1 Package -

c# - LINQ join Entities from HashSet's, Join vs Dictionary vs HashSet performance -