/// <summary> /// Creates a new subscription which will handle all the transactions after the given checkpoint. /// Waits asynchronously for the subscription to process all the transactions that are already in the event source. /// If the given <paramref name="lastProcessedCheckpoint"/> is ahead of the event source /// and that is ignored by the handler, /// waits asynchronously for a replacement subscription to be created /// and to process all the transactions that are already in the event source. /// The replacement subscription is not returned. /// The code that creates the replacement subscription is responsible for cancelling it. /// </summary> /// <param name="lastProcessedCheckpoint"> /// If has value, only the transactions with checkpoints greater than the given value will be processed. /// </param> /// <param name="subscriber">The <see cref="Subscriber"/> which will handle the transactions.</param> /// <param name="subscriptionId">An arbitrary string identifying the subscription.</param> /// <returns> /// A task that returns an object implementing the <see cref="IDisposable"/> interface. /// Disposing the object will cancel the subscription asynchronously. /// </returns> public async Task <IDisposable> SubscribeAsync(long?lastProcessedCheckpoint, Subscriber subscriber, string subscriptionId) { MemorySubscription subscription = SubscribeWithoutWaitingInternal(lastProcessedCheckpoint, subscriber, subscriptionId); try { await subscription.WaitForCheckingWhetherItIsAhead().ConfigureAwait(false); } catch (OperationCanceledException) { // Do nothing. } long checkpointAtStart; lock (syncRoot) { checkpointAtStart = lastHistoryCheckpoint; } try { await subscription.WaitUntilCheckpoint(checkpointAtStart).ConfigureAwait(false); } catch (OperationCanceledException) { // Do nothing. } return(subscription); }
/// <summary> /// Checks whether the event source has a non-cancelled subscription with the given identifier. /// </summary> /// <param name="subscriptionId"> /// The identifier of the subscription which was specified when the subscription was created. /// </param> public bool HasSubscriptionForId(string subscriptionId) { lock (syncRoot) { MemorySubscription subscription = subscriptions.SingleOrDefault(aSubscription => aSubscription.Id == subscriptionId); return((subscription != null) && !subscription.IsDisposed); } }
private MemorySubscription SubscribeWithoutWaitingInternal(long?lastProcessedCheckpoint, Subscriber subscriber, string subscriptionId) { var subscription = new MemorySubscription(lastProcessedCheckpoint ?? 0, batchSize, subscriber, subscriptionId, this); lock (syncRoot) { subscriptions.Add(subscription); } subscription.Start(); return(subscription); }