protected override async ValueTask OnTxRollback(string txId) { if (!string.IsNullOrEmpty(txId) && this.EventTypeContainer.TryGet(typeof(TxFinishedEvent), out var eventName)) { var rollbackEvent = new EventUnit <TPrimaryKey> { Event = new TxRollbackEvent { Id = this.TxSnapshot.TxId }, Meta = new EventMeta { Version = this.CurrentTxEventVersion + 1, Timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(), FlowId = txId }, ActorId = this.ActorId }; await this.TxEventStorage.Append(new EventDocument <TPrimaryKey> { FlowId = txId, ActorId = this.ActorId, Data = this.Serializer.Serialize(rollbackEvent.Event as TxFinishedEvent), Name = eventName, Timestamp = rollbackEvent.Meta.Timestamp, Version = rollbackEvent.Meta.Version }); this.TxEventApply(rollbackEvent); await this.ClearTxEvents(); } }
private void TxEventApply(EventUnit <TPrimaryKey> evt) { switch (evt.Event) { case TxCommitEvent value: { this.TxSnapshot.TxId = value.Id; this.TxSnapshot.TxStartVersion = value.StartVersion; this.TxSnapshot.TxStartTime = evt.Meta.Timestamp; this.TxSnapshot.Status = TransactionStatus.WaitingCommit; }; break; case TxCommitedEvent _: { this.TxSnapshot.Status = TransactionStatus.Commited; }; break; case TxFinishedEvent _: { this.TxSnapshot.Reset(); }; break; case TxRollbackEvent _: { this.TxSnapshot.Reset(); }; break; default: throw new NotSupportedException(evt.Event.GetType().FullName); } this.CurrentTxEventVersion = evt.Meta.Version; }
protected override async ValueTask OnTxCommited(string txId) { // If it is a transaction with Id, join the transaction event and wait for Complete if (!string.IsNullOrEmpty(txId) && this.EventTypeContainer.TryGet(typeof(TxCommitedEvent), out var eventName)) { var commitEvent = new EventUnit <TPrimaryKey> { Event = new TxCommitedEvent { Id = this.TxSnapshot.TxId }, Meta = new EventMeta { Version = this.CurrentTxEventVersion + 1, Timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(), FlowId = txId }, ActorId = this.ActorId }; await this.TxEventStorage.Append(new EventDocument <TPrimaryKey> { FlowId = txId, ActorId = this.ActorId, Data = this.Serializer.Serialize(commitEvent.Event as TxCommitedEvent), Name = eventName, Timestamp = commitEvent.Meta.Timestamp, Version = commitEvent.Meta.Version }); this.TxEventApply(commitEvent); await this.ClearTxEvents(); } }
private async ValueTask EventDelivered(EventUnit <TPrimaryKey> eventUnit) { try { RequestContext.Set(RuntimeConsts.EventFlowIdKey, eventUnit.Meta.FlowId); this.SnapshotHandler.Apply(this.Snapshot, eventUnit); await this.OnEventDelivered(eventUnit); } catch (Exception ex) { this.Logger.LogCritical(ex, "Delivered failed: {0}->{1}->{2}", this.ActorType.FullName, this.ActorId.ToString(), this.Serializer.Serialize(eventUnit, eventUnit.Event.GetType())); } }
public void SetEventUnit(EventUnit value, Context context) { if (value == null) { eventUnit = null; Enabled = false; } else if (value != eventUnit) { eventUnit = value; UpdateView(context); Enabled = true; } }
protected virtual async ValueTask OnRaiseStart(EventUnit <TPrimaryKey> @event) { if (this.Snapshot.Meta.Version == 0) { return; } if (this.Snapshot.Meta.IsLatest) { await this.SnapshotStorage.UpdateIsLatest(this.Snapshot.Meta.ActorId, false); this.Snapshot.Meta.IsLatest = false; } }
private void unitSelectorListBox_DrawItem(object sender, DrawItemEventArgs e) { // Find if units have overlapping positions _isPositionOccupied = new bool[evt.Units.Length]; for (int index = 0; index < evt.Units.Length; index++) { _isPositionOccupied[index] = false; } for (int index = 0; index < evt.Units.Length; index++) { EventUnit eventUnit = evt.Units[index]; for (int innerIndex = index + 1; innerIndex < evt.Units.Length; innerIndex++) { EventUnit innerEventUnit = evt.Units[innerIndex]; if ((eventUnit.X == innerEventUnit.X) && (eventUnit.Y == innerEventUnit.Y) && (eventUnit.UpperLevel == innerEventUnit.UpperLevel) && (!eventUnit.RandomlyPresent) && (!innerEventUnit.RandomlyPresent) && (eventUnit.SpriteSet.Value > 0) && (innerEventUnit.SpriteSet.Value > 0)) { _isPositionOccupied[index] = true; _isPositionOccupied[innerIndex] = true; } } } bool canCheckOccupied = (_isPositionOccupied != null); if (canCheckOccupied) { canCheckOccupied = (_isPositionOccupied.Length == unitSelectorListBox.Items.Count); } if ((e.Index > -1) && (e.Index < unitSelectorListBox.Items.Count)) { bool useOccupiedColor = canCheckOccupied ? _isPositionOccupied[e.Index] : false; EventUnit unit = unitSelectorListBox.Items[e.Index] as EventUnit; using (Brush textBrush = new SolidBrush(useOccupiedColor ? Color.Red : e.ForeColor)) using (Brush backBrush = new SolidBrush(e.BackColor)) { e.Graphics.FillRectangle(backBrush, e.Bounds); e.Graphics.DrawString((unit.HasChanged ? "*" : "") + unit.SpriteSet.Name, e.Font, textBrush, e.Bounds.X + 0, e.Bounds.Y + 0); e.Graphics.DrawString(unit.SpecialName.Name, e.Font, textBrush, e.Bounds.X + columnWidths[0], e.Bounds.Y + 0); e.Graphics.DrawString(unit.Job.Name, e.Font, textBrush, e.Bounds.X + columnWidths[0] + columnWidths[1], e.Bounds.Y + 0); if ((e.State & DrawItemState.Focus) == DrawItemState.Focus) { e.DrawFocusRectangle(); } } } }
protected async ValueTask Tell(EventUnit <TPrimaryKey> eventUnit) { if (eventUnit.Meta.Version == this.Snapshot.Meta.Version + 1) { await this.EventDelivered(eventUnit); this.Snapshot.Meta.ForceUpdateVersion(eventUnit.Meta, this.ActorType); // 更新处理完成的Version } else if (eventUnit.Meta.Version > this.Snapshot.Meta.Version) { var documentList = await this.Vertex.GetEventDocuments(this.Snapshot.Meta.Version + 1, eventUnit.Meta.Version - 1); var evtList = documentList.Select(document => { if (!this.EventTypeContainer.TryGet(document.Name, out var type)) { throw new NoNullAllowedException($"event name of {document.Name}"); } var data = this.Serializer.Deserialize(document.Data, type); return(new EventUnit <TPrimaryKey> { ActorId = this.ActorId, Event = data as IEvent, Meta = new EventMeta { Version = document.Version, Timestamp = document.Timestamp, FlowId = document.FlowId } }); }); foreach (var evt in evtList) { await this.EventDelivered(evt); this.Snapshot.Meta.ForceUpdateVersion(evt.Meta, this.ActorType); // 更新处理完成的Version } } if (eventUnit.Meta.Version == this.Snapshot.Meta.Version + 1) { await this.EventDelivered(eventUnit); this.Snapshot.Meta.ForceUpdateVersion(eventUnit.Meta, this.ActorType); // 更新处理完成的Version } if (eventUnit.Meta.Version > this.Snapshot.Meta.Version) { throw new EventVersionException(this.ActorId.ToString(), this.ActorType, eventUnit.Meta.Version, this.Snapshot.Meta.Version); } }
protected virtual async Task RecoverySnapshot() { try { await this.ReadSnapshotAsync(); while (!this.Snapshot.Meta.IsLatest) { var documentList = await this.Vertex.GetEventDocuments(this.Snapshot.Meta.Version + 1, this.Snapshot.Meta.Version + this.VertexOptions.EventPageSize); foreach (var document in documentList) { if (!this.EventTypeContainer.TryGet(document.Name, out var type)) { throw new NoNullAllowedException($"event name of {document.Name}"); } var data = this.Serializer.Deserialize(document.Data, type); var evt = new EventUnit <TPrimaryKey> { ActorId = this.ActorId, Event = data as IEvent, Meta = new EventMeta { Version = document.Version, Timestamp = document.Timestamp, FlowId = document.FlowId } }; this.Snapshot.Meta.IncrementDoingVersion(this.ActorType); // Mark the Version to be processed this.SnapshotHandler.Apply(this.Snapshot, evt); this.Snapshot.Meta.UpdateVersion(evt.Meta, this.ActorType); // Version of the update process } if (documentList.Count < this.VertexOptions.EventPageSize) { break; } } if (this.Logger.IsEnabled(LogLevel.Trace)) { this.Logger.LogTrace("Recovery completed: {0}->{1}", this.ActorType.FullName, this.Serializer.Serialize(this.Snapshot)); } } catch (Exception ex) { this.Logger.LogCritical(ex, "Recovery failed: {0}->{1}", this.ActorType.FullName, this.ActorId.ToString()); throw; } }
private void unitSelectorListBox_DrawItem(object sender, DrawItemEventArgs e) { if ((e.Index > -1) && (e.Index < unitSelectorListBox.Items.Count)) { EventUnit unit = unitSelectorListBox.Items[e.Index] as EventUnit; using (Brush textBrush = new SolidBrush(e.ForeColor)) using (Brush backBrush = new SolidBrush(e.BackColor)) { e.Graphics.FillRectangle(backBrush, e.Bounds); e.Graphics.DrawString((unit.HasChanged ? "*" : "") + unit.SpriteSet.Name, e.Font, textBrush, e.Bounds.X + 0, e.Bounds.Y + 0); e.Graphics.DrawString(unit.SpecialName.Name, e.Font, textBrush, e.Bounds.X + columnWidths[0], e.Bounds.Y + 0); e.Graphics.DrawString(unit.Job.Name, e.Font, textBrush, e.Bounds.X + columnWidths[0] + columnWidths[1], e.Bounds.Y + 0); if ((e.State & DrawItemState.Focus) == DrawItemState.Focus) { e.DrawFocusRectangle(); } } } }
protected override async ValueTask OnEventDelivered(EventUnit <TPrimaryKey> eventUnit) { switch (eventUnit.Event) { case CreatingEvent <TSnapshot> evt: await this.CreatingSnapshotHandle(evt); break; case UpdatingEvent <TSnapshot> evt: await this.UpdatingSnapshotHandle(evt); break; case DeletingEvent <TSnapshot> evt: await this.DeletingSnapshotHandle(evt); break; } await base.OnEventDelivered(eventUnit); }
public EventBufferUnit(EventUnit <TPrimaryKey> eventUnit, string flowId, IEventTypeContainer eventTypeContainer, ISerializer serializer) { var evtType = eventUnit.Event.GetType(); if (!eventTypeContainer.TryGet(evtType, out this.eventName)) { throw new NoNullAllowedException($"event name of {evtType.FullName}"); } this.eventBaseArray = eventUnit.Meta.ConvertToBytes(); this.EventBytes = serializer.SerializeToUtf8Bytes(eventUnit.Event, evtType); this.eventTransArray = EventConverter.ConvertToBytes(new EventTransUnit(this.eventName, eventUnit.ActorId, this.eventBaseArray.AsSpan(), this.EventBytes)); this.EventUnit = eventUnit; this.Document = new EventDocument <TPrimaryKey> { ActorId = eventUnit.ActorId, Data = Encoding.UTF8.GetString(this.EventBytes), FlowId = flowId, Name = this.eventName, Version = eventUnit.Meta.Version, Timestamp = eventUnit.Meta.Timestamp }; }
public static string GetEventId <TPrimaryKey>(this EventUnit <TPrimaryKey> @event) { return($"{@event.ActorId}_{@event.Meta.Version}"); }
public override void Apply(SnapshotUnit <TPrimaryKey, TSnapshot> snapshotBox, EventUnit <TPrimaryKey> eventBox) { switch (eventBox.Event) { case CreatingEvent <TSnapshot> : CreatingSnapshotHandle(snapshotBox.Data, (CreatingEvent <TSnapshot>)eventBox.Event); return; case UpdatingEvent <TSnapshot> : UpdatingSnapshotHandle(snapshotBox.Data, (UpdatingEvent <TSnapshot>)eventBox.Event); return; case DeletingEvent <TSnapshot> : DeletingSnapshotHandle(snapshotBox.Data, (DeletingEvent <TSnapshot>)eventBox.Event); return; default: base.Apply(snapshotBox, eventBox); return; } }
protected virtual ValueTask OnRaiseFailed(EventUnit <TPrimaryKey> @event) => ValueTask.CompletedTask;
protected virtual ValueTask OnRaiseSuccess(EventUnit <TPrimaryKey> eventUnit, byte[] eventBits) => this.Archive();
protected virtual async Task <bool> RaiseEvent(IEvent @event, string flowId = null) { if (string.IsNullOrEmpty(flowId)) { flowId = RequestContext.Get(RuntimeConsts.EventFlowIdKey) as string; if (string.IsNullOrEmpty(flowId)) { throw new ArgumentNullException(nameof(flowId)); } } try { var eventBox = new EventUnit <TPrimaryKey> { Event = @event, Meta = new EventMeta { FlowId = flowId, Version = this.Snapshot.Meta.Version + 1, Timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds() }, ActorId = this.Snapshot.Meta.ActorId }; await this.OnRaiseStart(eventBox); this.Snapshot.Meta.IncrementDoingVersion(this.ActorType); // Mark the Version to be processed var evtType = @event.GetType(); if (!this.EventTypeContainer.TryGet(evtType, out var eventName)) { throw new NoNullAllowedException($"event name of {evtType.FullName}"); } var evtBytes = this.Serializer.SerializeToUtf8Bytes(@event, evtType); var appendResult = await this.EventStorage.Append(new EventDocument <TPrimaryKey> { FlowId = eventBox.Meta.FlowId, ActorId = this.ActorId, Data = Encoding.UTF8.GetString(evtBytes), Name = eventName, Timestamp = eventBox.Meta.Timestamp, Version = eventBox.Meta.Version }); if (appendResult) { this.SnapshotHandler.Apply(this.Snapshot, eventBox); this.Snapshot.Meta.UpdateVersion(eventBox.Meta, this.ActorType); // Version of the update process await this.OnRaiseSuccess(eventBox, evtBytes); await this.SaveSnapshotAsync(); using var baseBytes = eventBox.Meta.ConvertToBytes(); using var buffer = EventConverter.ConvertToBytes(new EventTransUnit(eventName, this.Snapshot.Meta.ActorId, baseBytes.AsSpan(), evtBytes)); if (this.EventStream != default) { await this.EventStream.Next(buffer.ToArray()); } if (this.Logger.IsEnabled(LogLevel.Trace)) { this.Logger.LogTrace("RaiseEvent completed: {0}->{1}->{2}", this.ActorType.FullName, this.Serializer.Serialize(eventBox), this.Serializer.Serialize(this.Snapshot)); } return(true); } else { if (this.Logger.IsEnabled(LogLevel.Trace)) { this.Logger.LogTrace("RaiseEvent failed: {0}->{1}->{2}", this.ActorType.FullName, this.Serializer.Serialize(eventBox), this.Serializer.Serialize(this.Snapshot)); } this.Snapshot.Meta.DecrementDoingVersion(); // Restore the doing version await this.OnRaiseFailed(eventBox); return(false); } } catch (Exception ex) { this.Logger.LogCritical(ex, "RaiseEvent failed: {0}->{1}", this.ActorType.FullName, this.Serializer.Serialize(this.Snapshot)); await this.RecoverySnapshot(); // Restore state // Errors may appear repeatedly, so update the previous snapshot to improve the restoration speed await this.SaveSnapshotAsync(true); throw; } }
public ValueTask Tell_Test(EventUnit <long> eventUnit) { return(this.Tell(eventUnit)); }
private void unitSelectorListBox_DrawItem(object sender, DrawItemEventArgs e) { // Find if units have overlapping positions _isPositionOccupied = new bool[evt.Units.Length]; for (int index = 0; index < evt.Units.Length; index++) { _isPositionOccupied[index] = false; } for (int index = 0; index < evt.Units.Length; index++) { EventUnit eventUnit = evt.Units[index]; for (int innerIndex = index + 1; innerIndex < evt.Units.Length; innerIndex++) { EventUnit innerEventUnit = evt.Units[innerIndex]; if ((eventUnit.X == innerEventUnit.X) && (eventUnit.Y == innerEventUnit.Y) && (eventUnit.UpperLevel == innerEventUnit.UpperLevel) && ((eventUnit.AlwaysPresent) && (innerEventUnit.AlwaysPresent)) && (eventUnit.SpriteSet.Value > 0) && (innerEventUnit.SpriteSet.Value > 0)) { _isPositionOccupied[index] = true; _isPositionOccupied[innerIndex] = true; } } } bool canCheckOccupied = (_isPositionOccupied != null); if (canCheckOccupied) { canCheckOccupied = (_isPositionOccupied.Length == unitSelectorListBox.Items.Count); } if ((e.Index > -1) && (e.Index < unitSelectorListBox.Items.Count)) { bool isSelected = ((e.State & DrawItemState.Selected) == DrawItemState.Selected); bool isOccupied = canCheckOccupied ? _isPositionOccupied[e.Index] : false; EventUnit unit = unitSelectorListBox.Items[e.Index] as EventUnit; bool unitExists = (unit.SpriteSet.Value > 0); int colorIndex = (isSelected ? 0 : (unit.AlwaysPresent ? 1 : 2)); int teamIndex = (int)unit.TeamColor; FFTPatcher.Settings.CombinedColor teamColor = Settings.GetTeamColor(teamIndex, colorIndex); bool useConflictColor = (isOccupied && (!isSelected)); bool useTeamColor = (unitExists && teamColor.UseColor); Color foreColor = (useConflictColor ? Color.Red : (useTeamColor ? teamColor.ForegroundColor : e.ForeColor)); Color backColor = (useConflictColor ? Color.White : (useTeamColor ? teamColor.BackgroundColor : e.BackColor)); string strPresentFlags = unit.AlwaysPresent ? (unit.RandomlyPresent ? "Always/Random" : "Always") : (unit.RandomlyPresent ? "Random" : ""); using (Brush backBrush = new SolidBrush(backColor)) { e.Graphics.FillRectangle(backBrush, e.Bounds); TextRenderer.DrawText(e.Graphics, (unit.HasChanged ? "*" : "") + unit.SpriteSet.Name, e.Font, new Point(e.Bounds.X + 0, e.Bounds.Y + 0), foreColor, TextFormatFlags.NoPrefix); if (unitExists) { TextRenderer.DrawText(e.Graphics, unit.SpecialName.Name, e.Font, new Point(e.Bounds.X + cumulativeWidths[0], e.Bounds.Y + 0), foreColor, TextFormatFlags.NoPrefix); TextRenderer.DrawText(e.Graphics, unit.Job.Name, e.Font, new Point(e.Bounds.X + cumulativeWidths[1], e.Bounds.Y + 0), foreColor, TextFormatFlags.NoPrefix); TextRenderer.DrawText(e.Graphics, String.Format("({0}, {1}, {2})", unit.X, unit.Y, (unit.UpperLevel ? 1 : 0)), e.Font, new Point(e.Bounds.X + cumulativeWidths[2], e.Bounds.Y), foreColor); TextRenderer.DrawText(e.Graphics, String.Format("0x{0:X2}", unit.UnitID), e.Font, new Point(e.Bounds.X + cumulativeWidths[3], e.Bounds.Y + 0), foreColor); TextRenderer.DrawText(e.Graphics, strPresentFlags, e.Font, new Point(e.Bounds.X + cumulativeWidths[4], e.Bounds.Y + 0), foreColor); TextRenderer.DrawText(e.Graphics, unit.TeamColor.ToString(), e.Font, new Point(e.Bounds.X + cumulativeWidths[5], e.Bounds.Y + 0), foreColor); } if ((e.State & DrawItemState.Focus) == DrawItemState.Focus) { e.DrawFocusRectangle(); } } } }
public EventBufferUnit(EventUnit <TPrimaryKey> eventUnit, IEventTypeContainer eventTypeContainer, ISerializer serializer) : this(eventUnit, default, eventTypeContainer, serializer) { }
protected virtual ValueTask OnEventDelivered(EventUnit <TPrimaryKey> eventUnit) => ValueTask.CompletedTask;