public async Task ExecuteEvent(GameEvent newEvent) { ProcessingEvents.TryAdd(newEvent.Id, newEvent); // the event has failed already if (newEvent.Failed) { goto skip; } try { await newEvent.Owner.ExecuteEvent(newEvent); // save the event info to the database await _changeHistoryService.Add(newEvent); } catch (TaskCanceledException) { _logger.LogDebug("Received quit signal for event id {eventId}, so we are aborting early", newEvent.Id); } catch (OperationCanceledException) { _logger.LogDebug("Received quit signal for event id {eventId}, so we are aborting early", newEvent.Id); } // this happens if a plugin requires login catch (AuthorizationException ex) { newEvent.FailReason = EventFailReason.Permission; newEvent.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMAND_NOTAUTHORIZED"]} - {ex.Message}"); } catch (NetworkException ex) { newEvent.FailReason = EventFailReason.Exception; using (LogContext.PushProperty("Server", newEvent.Owner?.ToString())) { _logger.LogError(ex, ex.Message); } } catch (ServerException ex) { newEvent.FailReason = EventFailReason.Exception; using (LogContext.PushProperty("Server", newEvent.Owner?.ToString())) { _logger.LogError(ex, ex.Message); } } catch (Exception ex) { newEvent.FailReason = EventFailReason.Exception; Console.WriteLine(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_EXCEPTION"].FormatExt(newEvent.Owner)); using (LogContext.PushProperty("Server", newEvent.Owner?.ToString())) { _logger.LogError(ex, "Unexpected exception"); } } skip: if (newEvent.Type == EventType.Command && newEvent.ImpersonationOrigin == null) { var correlatedEvents = ProcessingEvents.Values.Where(ev => ev.CorrelationId == newEvent.CorrelationId && ev.Id != newEvent.Id) .ToList(); await Task.WhenAll(correlatedEvents.Select(ev => ev.WaitAsync(Utilities.DefaultCommandTimeout, CancellationToken))); newEvent.Output.AddRange(correlatedEvents.SelectMany(ev => ev.Output)); foreach (var correlatedEvent in correlatedEvents) { ProcessingEvents.Remove(correlatedEvent.Id, out _); } } // we don't want to remove events that are correlated to command if (ProcessingEvents.Values.ToList()?.Count(gameEvent => gameEvent.CorrelationId == newEvent.CorrelationId) == 1) { ProcessingEvents.Remove(newEvent.Id, out _); } // tell anyone waiting for the output that we're done newEvent.Complete(); OnGameEventExecuted?.Invoke(this, newEvent); }
public async Task ExecuteEvent(GameEvent newEvent) { #if DEBUG == true Logger.WriteDebug($"Entering event process for {newEvent.Id}"); #endif // the event has failed already if (newEvent.Failed) { goto skip; } try { await newEvent.Owner.ExecuteEvent(newEvent); // save the event info to the database var changeHistorySvc = new ChangeHistoryService(); await changeHistorySvc.Add(newEvent); #if DEBUG Logger.WriteDebug($"Processed event with id {newEvent.Id}"); #endif } catch (TaskCanceledException) { Logger.WriteInfo($"Received quit signal for event id {newEvent.Id}, so we are aborting early"); } catch (OperationCanceledException) { Logger.WriteInfo($"Received quit signal for event id {newEvent.Id}, so we are aborting early"); } // this happens if a plugin requires login catch (AuthorizationException ex) { newEvent.FailReason = EventFailReason.Permission; newEvent.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMAND_NOTAUTHORIZED"]} - {ex.Message}"); } catch (NetworkException ex) { newEvent.FailReason = EventFailReason.Exception; Logger.WriteError(ex.Message); Logger.WriteDebug(ex.GetExceptionInfo()); } catch (ServerException ex) { newEvent.FailReason = EventFailReason.Exception; Logger.WriteWarning(ex.Message); } catch (Exception ex) { newEvent.FailReason = EventFailReason.Exception; Logger.WriteError(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_EXCEPTION"].FormatExt(newEvent.Owner)); Logger.WriteDebug(ex.GetExceptionInfo()); } skip: // tell anyone waiting for the output that we're done newEvent.Complete(); OnGameEventExecuted?.Invoke(this, newEvent); #if DEBUG == true Logger.WriteDebug($"Exiting event process for {newEvent.Id}"); #endif }