/// <remarks> /// If the event store is deployed as a cluster, it may be possible to get transient read failures. /// If an event could not be found on the event stream, try again. ///</remarks> private async Task ProcessSingleMessageAsync(string stream, Type eventType, IEnumerable handlers, BasicEventInfo eventInfo, string subscriberId) { var maxAttempts = Math.Max(_eventNotFoundRetryCount, 1); object @event = null; for (var i = 0; i < maxAttempts; i++) { if (i > 0) { await Task.Delay(_eventNotFoundRetryDelay); } try { Log.Debug(_log, "{0}|{1}: Processing event {2}. Attempt: {3}", stream, subscriberId ?? "default", eventInfo.Id, i + 1); @event = await _connection.ReadEventBodyAsync(eventType, eventInfo.CanonicalEventLink); if (@event != null) { break; } } catch (EventNotFoundException ex) { if (i < maxAttempts - 1) { Log.Warning(_log, "{0}|{1}: Event could not be found. Attempting to process the event again. {2}: {3}", stream, subscriberId ?? "default", eventInfo.Id, ex.Message); } else { Log.Error(_log, "{0}|{1}: Event could not be found after {2} attempts. {3}: {4}", stream, subscriberId ?? "default", i + 1, eventInfo.Id, ex.Message); return; } } catch (Exception ex) { Log.Error(_log, "{0}|{1}: Error getting message {2}: {3}", stream, subscriberId ?? "default", eventInfo.Id, ex); return; } } try { await InvokeMessageHandlersForEventMessageAsync(stream, eventType, handlers, @event, eventInfo); } catch (Exception ex) { Log.Error(_log, "{0}|{1}: Error invoking message handlers for message {2}: {3}", stream, subscriberId ?? "default", eventInfo.Id, ex); } }
public async Task<IDictionary<Type, Exception>> InvokeMessageHandlersForEventMessageAsync(string stream, Type eventType, IEnumerable handlers, object @event, BasicEventInfo eventInfo) { var handlerCount = 0; var eventTitle = eventInfo.Title; var updated = eventInfo.Updated; var errors = new Dictionary<Type, Exception>(); foreach (var handler in handlers) { handlerCount++; var handlerType = handler.GetType(); var handleMethod = GetMethodFromHandler(handlerType, eventType, "Handle"); if (handleMethod == null) { Log.Warning(_log, "Could not find the handle method for: {0}", handlerType.FullName); continue; } try { try { var arguments = new[] {@event, eventInfo}.Take(handleMethod.GetParameters().Length); await (Task)handleMethod.Invoke(handler, arguments.ToArray()); } catch (Exception invokeException) { errors[handlerType] = invokeException.InnerException; var errorMessage = string.Format("{0} thrown processing event {1}", invokeException.GetType().FullName, eventTitle); Log.Error(_log, errorMessage, invokeException); var errorMethod = GetMethodFromHandler(handlerType, eventType, "OnError"); errorMethod.Invoke(handler, new[] { invokeException, @event }); } } catch (Exception errorHandlingException) { var errorMessage = string.Format("{0} thrown whilst handling error from event {1}", errorHandlingException.GetType().FullName, eventTitle); Log.Error(_log, errorMessage, errorHandlingException); } } _performanceMonitors.AsParallel().ForAll(x => x.Accept(stream, eventType.FullName, updated, handlerCount, errors)); return errors; }
public async Task InvokeMessageHandlersForStreamMessageAsync(string stream, Type eventType, IEnumerable handlers, BasicEventInfo eventInfo) { var @event = await _connection.ReadEventBodyAsync(eventType, eventInfo.CanonicalEventLink); await InvokeMessageHandlersForEventMessageAsync(stream, eventType, handlers, @event, eventInfo); }