// Not thread safe. public async Task ManageAsync(CancellationToken cancellationToken) { try { while (!cancellationToken.IsCancellationRequested) { ResolutionStreamEvent resolutionStreamEvent; while (!cancellationToken.IsCancellationRequested && _resolutionQueue.TryDequeue(out resolutionStreamEvent)) { var streamEvent = resolutionStreamEvent.StreamEvent; IBusinessEvent businessEvent = null; try { // If unable to resolve event type then subscriber event will still be created but it // will be unresolved. if (_resolver.CanResolve(streamEvent.EventType)) { businessEvent = _resolver.Resolve(streamEvent.EventType, streamEvent.Data); } } catch (Exception ex) { _logger.LogError(ex, "Exception while resolving business event. Subscription event will be created with null business event."); } // Stream events may (and will for subscription streams) have links to original events. // We want the original event as the core event and the subscription event info as secondary. // However, if the event is not a link then we take the event info as both subscription info and original event. var streamId = streamEvent.StreamId; var position = streamEvent.Position; var subscriptionStreamId = streamEvent.StreamId; var subscriptionPosition = streamEvent.Position; if (streamEvent.IsLink) { streamId = streamEvent.Link.StreamId; position = streamEvent.Link.Position; } var subscriberEvent = new SubscriberEvent(resolutionStreamEvent.RegionId, streamId, position, subscriptionStreamId, subscriptionPosition, streamEvent.EventType, businessEvent); // Send to the sorting manager. await _sortingManager.ReceiveSubscriberEventAsync(subscriberEvent, cancellationToken); } await Task.WhenAny(new Task[] { _resolutionQueue.AwaitEnqueueSignalAsync(), cancellationToken.WaitHandle.AsTask() }); } } catch (Exception ex) { _logger.LogError(ex, "Exception while managing resolution."); throw; } }
public async Task TryRunHandlerAsync(SubscriberEvent subscriberEvent, CancellationToken cancellationToken) { try { try { await _handler.HandleSubscriberEventAsync(subscriberEvent, cancellationToken); await _streamStateRepo.SaveStreamStateAsync(subscriberEvent.StreamId, subscriberEvent.Position, false); } catch (Exception ex) { _logger.LogError(ex, "Exception while handling event. Stream will be halted until stream state errors are cleared."); // Save errored stream state. await _streamStateRepo.SaveStreamStateAsync(subscriberEvent.StreamId, subscriberEvent.Position, true); } } finally { _awaiter.ReleaseThrottle(); // Make room for other handlers. _awaiter.SetHandlerCompletionSignal(); } }
public async Task ReceiveSubscriberEventAsync(SubscriberEvent subscriberEvent, CancellationToken cancellationToken) { // Enque when space opens up. await _sortingQueue.EnqueueWithWaitAsync(subscriberEvent, cancellationToken); }
public async Task ReceiveSubscriberEventAsync(string parallelKey, SubscriberEvent subscriberEvent, CancellationToken cancellationToken) { // Enqueue when space available. await _handlingQueue.EnqueueWithWaitAsync(parallelKey, subscriberEvent, cancellationToken); }