/// <summary> /// Handler for records obtained through the subscription /// </summary> private void ApplyRecord(JournalRecord record) { TaskCompletionSource <object> completion = null; try { var command = record.Command; var isLocalCommand = _pendingLocalCommands.TryRemove(command.Id, out completion); if (isLocalCommand) { _pendingCommandsChanged.Set(); } _logger.LogDebug("ApplyRecord: {0}/{1}, isLocal: {2}", record.RecordNumber, command.GetType().Name, isLocalCommand); long expected = Interlocked.Increment(ref _lastRecordNumber); if (expected != record.RecordNumber) { _logger.LogError("ApplyRecord: RecordNumber out of order. Expected {0}, got {1}", expected, record.RecordNumber); } object result = _kernel.Execute(record.Command); completion?.SetResult(result); } catch (Exception ex) { _logger.LogError(default(EventId), ex, "ApplyRecord failed: {0}/{1}", record.RecordNumber, record.Command.GetType().Name); completion?.SetException(ex); } }
private void OnCommandExecuted(JournalRecord journalRecord, bool isLocal, IEnumerable <Event> events) { foreach (var @event in events) { if (_handlers.TryGetValue(@event.GetType(), out var eventSubscription)) { eventSubscription.Invoke(@event); } } }
public void Handle(JournalRecord record) { if (record.RecordNumber != _nextRecord) { throw new InvalidOperationException("expected version " + _nextRecord + ", got " + record.RecordNumber); } _nextRecord++; _callback.Invoke(record); }
/// <summary> /// Handler for records obtained through the subscription /// </summary> private void ApplyRecord(JournalRecord record) { TaskCompletionSource <object> completion = null; try { var command = record.Command; var isLocalCommand = _pendingLocalCommands.TryRemove(command.Id, out completion); if (isLocalCommand) { _metrics.PendingLocalCommands(_pendingLocalCommands.Count); _pendingCommandsChanged.Set(); } _logger.LogDebug("ApplyRecord: {0}/{1}, isLocal: {2}", record.RecordNumber, command.GetType().Name, isLocalCommand); var expected = Interlocked.Increment(ref _lastRecordNumber); if (expected != record.RecordNumber) { if (!_settings.AllowBrokenSequence) { _stopped = true; throw new Exception($"Broken sequence, expected {expected}, got {record.RecordNumber}"); } _logger.LogWarning( "ApplyRecord: RecordNumber out of order. Expected {0}, got {1}", expected, record.RecordNumber); } var events = new List <Event>(); var result = _kernel.Execute(record.Command, events.Add); NotifyCommandExecuted(record, isLocalCommand, events); completion?.SetResult(result); _metrics.CommandExecuted(); } catch (Exception ex) { _metrics.CommandFailed(); _logger.LogError(default(EventId), ex, "ApplyRecord failed: {0}/{1}", record.RecordNumber, record.Command.GetType().Name); completion?.SetException(ex); } }
/// <summary> /// /// </summary> /// <param name="journalRecord"></param> /// <param name="isLocal"></param> /// <param name="events"></param> private void NotifyCommandExecuted(JournalRecord journalRecord, bool isLocal, IEnumerable <Event> events) { try { CommandExecuted.Invoke(journalRecord, isLocal, events); } catch { // Don't let external code crash the engine } }
private void NotifyCommandExecuted(JournalRecord journalRecord, bool isLocal, IEnumerable <Event> events) { try { CommandExecuted.Invoke(journalRecord, isLocal, events); } catch (Exception exception) { _logger.LogError(exception, "Exception thrown in CommandExecuted handler."); } }
private string JournalRecordToString(JournalRecord record) { var selfSerializingCommand = (ISerializable)record.Command; selfSerializingCommand.Save(out var typeIdentifier, out string commandAsString); return(String.Join(" ", record.RecordNumber, record.Written.ToString("o"), record.Command.Id, typeIdentifier, commandAsString)); }
private void OnCommandBatch(IEnumerable <Command> commands) { lock (_journal) { foreach (var command in commands) { var record = new JournalRecord(_nextRecord++, DateTime.Now, command); _journal.Add(record); foreach (var sub in _subscriptions.Values) { sub.Handle(record); } } } }
/// <summary> /// Handler for records obtained through the subscription /// </summary> private void OnRecordReceived(JournalRecord record) { if (_stopped) { return; } TaskCompletionSource <object> completion = null; try { var command = record.Command; var isLocalCommand = _pendingLocalCommands.TryRemove(command.Id, out completion); if (isLocalCommand) { _metrics.PendingLocalCommands(_pendingLocalCommands.Count); _pendingCommandsChanged.Set(); } _logger.LogDebug("OnRecordReceived: {0}/{1}, isLocal: {2}", record.RecordNumber, command.GetType().Name, isLocalCommand); VerifyRecordSequence(record.RecordNumber); var ctx = ExecutionContext.Current; ctx.Reset(record.RecordNumber); var result = _kernel.Execute(record.Command); Interlocked.Exchange(ref _lastRecordNumber, record.RecordNumber); NotifyCommandExecuted(record, isLocalCommand, ctx.Events); completion?.SetResult(result); _metrics.CommandExecuted(); } catch (Exception ex) { _metrics.CommandFailed(); _logger.LogError(default(EventId), ex, "OnRecordReceived failed: {0}/{1}", record.RecordNumber, record.Command.GetType().Name); completion?.SetException(ex); } }
private void OnEngineOnCommandExecuted(JournalRecord record, bool local, IEnumerable <Event> events) { foreach (var item in events) { if (item == null) { continue; } if (_globalFilters.Count > 0 && !_globalFilters.All(filter => filter.Accept(item))) { continue; } if (_subscriptions.Count > 0) { if (!_subscriptions.TryGetValue(item.GetType(), out var handlers)) { continue; } foreach (var handler in handlers) { try { handler.Invoke(item); } catch { // TODO: Log the exception... } } } else { Raise(item); } } }