Nie mogłem znaleźć jednego, popularnego wzoru do robienia tego. Ale po odgadnięciu trochę w System.Messaging, byłem w stanie wykorzystać właściwości wiadomości i zachowanie MSMQ w tym, co uważam za odpowiedni sposób na wykonanie pracy przy minimalnych ruchomych częściach.
Oto, co zaimplementowałem.Okazało się to być dość prosty i lekki - nie dużo kodu i łatwe w utrzymaniu:
stworzyłem obiekt o nazwie RetryLevel który ma trzy właściwości:
int kolejności, int NumberOfRetries, TimeSpan Delay
Konfiguracja aplikacji odbiorcy zawiera teraz listę RetryLevel. Tak więc nowa funkcja zasadniczo obsługuje ponowna próba na poziomie n.
Następnie utworzyłem obiekt o nazwie RetryInfo. Ten obiekt posiada dwie właściwości:
int próbach ciąg SourceQueuePath
Instancja obiektu RetryInfo jest seryjny i przechowywane we właściwości Extension każdej wiadomości, że kończy się ich ponowiona. To pozwala mi śledzić bieżący stan ponawiania na samym komunikacie, eliminując w ten sposób konieczność utrzymywania oddzielnego magazynu metadanych ponawiania i całego obciążenia związanego z uzgadnianiem identyfikatorów wiadomości, utrzymywania synchronizacji danych itp.
Wreszcie dodałem ścieżka kolejki oczekiwania do konfiguracji odbiornika. Ta kolejka jest miejscem, w którym wiadomości zostaną usunięte, gdy są w "limicie czasu".
Tak więc teraz, gdy program obsługi wiadomości odrzuca komunikat, odbiornik deserializuje jego RetryInfo, jeśli taki istnieje, i sprawdza liczbę (poprzednich) prób ustalenia, które ze skonfigurowanych poziomów RetryLevel osiągnęło.
Odbiornik ustawia właściwość TimeToBeRecieved (TTBR) komunikatu na DateTime.Now oraz wartość opóźnienia odpowiedniej opcji RetryLevel. Następnie ustawia właściwość AdministrativeQueue na kolejkę utworzoną z właściwości SourceQueuePath obiektu RetryInfo i ustawia właściwość Message's AcknowledgeType na AcknowledgeTypes.NegativeReceive. W końcu umieszcza komunikat w kolejce oczekiwania.
Stąd MSMQ ogląda TTBR wiadomości. Po przekroczeniu limitu czasu usługa MSMQ umieszcza komunikat w kolejce w jego właściwości AdministrativeQueue, która jest kolejką, z której pochodzi pierwotnie wiadomość. Jeśli komunikat nadal będzie odrzucany przez procedury obsługi, to po prostu przesuwa się w górę do poziomu RetryLevels.
Jeżeli Próby wiadomość jest poza tym wszystkich NumberOfRetries od skonfigurowanego RetryLevels, nieruchomości TTBR depeszy jest ustawiony na TimeSpan.Zero właściwość UseDeadLetterQueue jest ustawiona na wartość true, a wiadomość jest umieszczany w kolejce oczekiwania tak jak każdy inne próby. Tym razem jednak upływa natychmiast i MSMQ wysyła je do kolejki martwych liter hosta kolejki oczekującej (DLQ), gdzie można ją obsługiwać ręcznie.
Dzięki Jens. Jestem świadomy NServiceBus i MassTransit, które są, podobnie jak WCF, aplikacjami zbudowanymi na MSMQ, które mają funkcję ponowienia. Ale moje pytanie brzmi: jaki jest dobry sposób tworzenia funkcji ponawiania, jeśli budujesz aplikację na MSMQ. Nie jest to dobry sposób na zastąpienie mojej aplikacji innym. –