Решение, которое я в итоге придумал, состояло в том, чтобы назначить уникальный идентификатор каждому опубликованному сообщению и кэшировать опубликованное сообщение в сервисном адаптере (там же, где я хранил обратные вызовы для подписанных клиентов. Всякий раз, когда я опубликовав сообщение, подписчики получат сообщения и с соответствующим уникальным идентификатором. Затем подписчики могут использовать событие channel.Faults для повторного подключения и повторной подписки на услугу специальным методом, который принимает последний полученный идентификатор сообщения в качестве параметр.
Сервисный код:
/// <summary>
/// Operation used by the subscriber to subscribe to events published.
/// </summary>
public void Resubscribe(int lastReceivedMessageId)
{
// Get callback contract
IPubSubCallback callback = OperationContext.Current.GetCallbackChannel<IPubSubCallback>();
ThreadPool.QueueUserWorkItem(delegate(object state)
{
adapter.Resubscribe(lastReceivedMessageId, callback);
});
}
Код адаптера:
/// <summary>
/// Operation used by the subscriber to resubscribe to events published.
/// </summary>
public void Resubscribe(int lastReceivedMessageId, IPubSubCallback callback)
{
try
{
// Send the subscriber any missed messages
foreach (KeyValuePair<int, string> missedMessage in publishedMessages.Where(x => x.Key > lastReceivedMessageId))
{
callback.MessagePublished(missedMessage.Value, missedMessage.Key);
}
// Add the subscriber callback to the list of active subscribers
if (!callbacks.Contains(callback))
{
callbacks.Add(callback);
}
}
catch
{
// ignore subscription, callbacks failed again
}
}
Служба может затем определить, что пропустил клиент, и отправить эти сообщения в правильном порядке.
Мне кажется, это решение работает хорошо, но у меня есть ощущение, что должен быть лучший способ сделать это. Комментарии / дополнительные ответы очень приветствуются! :)