public async Task<RemoteClusterActivationResponse> ProcessActivationRequest(GrainId grain, string requestClusterId, int hopCount = 0) { // check if the requesting cluster id is in the current configuration view of this cluster // if not, reject the message. var multiClusterConfiguration = Runtime.Silo.CurrentSilo.LocalMultiClusterOracle?.GetMultiClusterConfiguration(); if (multiClusterConfiguration == null || !multiClusterConfiguration.Clusters.Contains(requestClusterId)) { logger.Warn(ErrorCode.GlobalSingleInstance_WarningInvalidOrigin, "GSIP:Rsp {0} Origin={1} GSI request rejected because origin is not in MC configuration", grain.ToString(), requestClusterId); return new RemoteClusterActivationResponse(ActivationResponseStatus.Failed); } var forwardAddress = router.CheckIfShouldForward(grain, 0, "ProcessActivationRequest"); // on all silos other than first, we insert a retry delay and recheck owner before forwarding if (hopCount > 0 && forwardAddress != null) { await Task.Delay(LocalGrainDirectory.RETRY_DELAY); forwardAddress = router.CheckIfShouldForward(grain, hopCount, "ProcessActivationRequest(recheck)"); } if (forwardAddress == null) { return ProcessRequestLocal(grain, requestClusterId); } else { if (logger.IsVerbose2) logger.Verbose("GSIP:Rsp {0} Origin={1} forward to {2}", grain.ToString(), requestClusterId, forwardAddress); var clusterGrainDir = InsideRuntimeClient.Current.InternalGrainFactory.GetSystemTarget<IClusterGrainDirectory>(Constants.ClusterDirectoryServiceId, forwardAddress); return await clusterGrainDir.ProcessActivationRequest(grain, requestClusterId, hopCount + 1); } }
internal async Task Start(StatisticsProviderManager statsManager, IMessageCenter transport, GrainId clientId) { runtimeStats.Start(); // Configure Metrics IProvider statsProvider = null; if (!string.IsNullOrEmpty(config.StatisticsProviderName)) { var extType = config.StatisticsProviderName; statsProvider = statsManager.GetProvider(extType); var metricsDataPublisher = statsProvider as IClientMetricsDataPublisher; if (metricsDataPublisher == null) { var msg = String.Format("Trying to create {0} as a metrics publisher, but the provider is not configured." , extType); throw new ArgumentException(msg, "ProviderType (configuration)"); } var configurableMetricsDataPublisher = metricsDataPublisher as IConfigurableClientMetricsDataPublisher; if (configurableMetricsDataPublisher != null) { configurableMetricsDataPublisher.AddConfiguration( config.DeploymentId, config.DNSHostName, clientId.ToString(), transport.MyAddress.Endpoint.Address); } tableStatistics = new ClientTableStatistics(transport, metricsDataPublisher, runtimeStats) { MetricsTableWriteInterval = config.StatisticsMetricsTableWriteInterval }; } else if (config.UseAzureSystemStore) { // Hook up to publish client metrics to Azure storage table var publisher = AssemblyLoader.LoadAndCreateInstance<IClientMetricsDataPublisher>(Constants.ORLEANS_AZURE_UTILS_DLL, logger); await publisher.Init(config, transport.MyAddress.Endpoint.Address, clientId.ToParsableString()); tableStatistics = new ClientTableStatistics(transport, publisher, runtimeStats) { MetricsTableWriteInterval = config.StatisticsMetricsTableWriteInterval }; } // Configure Statistics if (config.StatisticsWriteLogStatisticsToTable) { if (statsProvider != null) { logStatistics.StatsTablePublisher = statsProvider as IStatisticsPublisher; // Note: Provider has already been Init-ialized above. } else if (config.UseAzureSystemStore) { var statsDataPublisher = AssemblyLoader.LoadAndCreateInstance<IStatisticsPublisher>(Constants.ORLEANS_AZURE_UTILS_DLL, logger); await statsDataPublisher.Init(false, config.DataConnectionString, config.DeploymentId, transport.MyAddress.Endpoint.ToString(), clientId.ToParsableString(), config.DNSHostName); logStatistics.StatsTablePublisher = statsDataPublisher; } } logStatistics.Start(); }
/// <summary> /// Removes an activation of the given grain from the partition /// </summary> /// <param name="grain">the identity of the grain</param> /// <param name="activation">the id of the activation</param> /// <param name="cause">reason for removing the activation</param> /// <param name="entry">returns the entry, if found </param> /// <param name="wasRemoved">returns whether the entry was actually removed</param> internal void RemoveActivation(GrainId grain, ActivationId activation, UnregistrationCause cause, out IActivationInfo entry, out bool wasRemoved) { wasRemoved = false; entry = null; lock (lockable) { if (partitionData.ContainsKey(grain) && partitionData[grain].RemoveActivation(activation, cause, out entry, out wasRemoved)) // if the last activation for the grain was removed, we remove the entire grain info partitionData.Remove(grain); } if (log.IsVerbose3) log.Verbose3("Removing activation for grain {0} cause={1} was_removed={2}", grain.ToString(), cause, wasRemoved); }
public async Task RollbackTransaction(long transactionId) { if (CurrentTransactionId == transactionId && CurrentTransactionStartVersion != -1 && Snapshot.Base.Version >= CurrentTransactionStartVersion) { try { if (BackupSnapshot.Base.Version == CurrentTransactionStartVersion - 1) { Snapshot = new Snapshot <PrimaryKey, StateType>(GrainId) { Base = BackupSnapshot.Base.Clone(), State = BackupSnapshot.State.Clone() }; } else { if (BackupSnapshot.Base.Version >= CurrentTransactionStartVersion) { await EventStorage.DeleteAfter(Snapshot.Base.StateId, CurrentTransactionStartVersion, Snapshot.Base.LatestMinEventTimestamp); } await RecoverySnapshot(); } WaitingForTransactionTransports.Clear(); RestoreTransactionTemporaryState(); TransactionSemaphore.Release(); if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Transaction rollbacked: {0}->{1}->{2}", GrainType.FullName, GrainId.ToString(), transactionId); } } catch (Exception ex) { Logger.LogCritical(ex, "Transaction rollback failed: {0}->{1}->{2}", GrainType.FullName, GrainId.ToString(), transactionId); throw; } } }
/// <summary> /// Grain激活时调用用来初始化的方法(禁止在子类重写,请使用) /// </summary> /// <returns></returns> public override async Task OnActivateAsync() { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Start activation grain with id = {0}", GrainId.ToString()); } var dITask = DependencyInjection(); if (!dITask.IsCompletedSuccessfully) { await dITask; } try { if (ArchiveOptions.On) { //加载归档信息 BriefArchiveList = (await ArchiveStorage.GetBriefList(GrainId)).OrderBy(a => a.Index).ToList(); LastArchive = BriefArchiveList.LastOrDefault(); ClearedArchive = BriefArchiveList.Where(a => a.EventIsCleared).OrderByDescending(a => a.Index).FirstOrDefault(); var secondLastArchive = BriefArchiveList.Count > 1 ? BriefArchiveList.SkipLast(1).Last() : default; if (LastArchive != default && !LastArchive.IsCompletedArchive(ArchiveOptions, secondLastArchive) && !LastArchive.EventIsCleared) { await DeleteArchive(LastArchive.Id); BriefArchiveList.Remove(LastArchive); NewArchive = LastArchive; LastArchive = BriefArchiveList.LastOrDefault(); } } //修复状态 await RecoveryState(); if (ArchiveOptions.On) { if (Snapshot.Base.Version != 0 && (LastArchive == default || LastArchive.EndVersion < Snapshot.Base.Version) && (NewArchive == default || NewArchive.EndVersion < Snapshot.Base.Version)) { //归档恢复 while (true) { var startTimestamp = Snapshot.Base.StartTimestamp; long startVersion = 0; if (NewArchive != default) { startVersion = NewArchive.EndVersion; startTimestamp = NewArchive.StartTimestamp; } else if (NewArchive == default && LastArchive != default) { startVersion = LastArchive.EndVersion; startTimestamp = LastArchive.EndTimestamp; } var eventList = await EventStorage.GetList(GrainId, startTimestamp, startVersion + 1, startVersion + CoreOptions.NumberOfEventsPerRead); foreach (var @event in eventList) { var task = EventArchive(@event); if (!task.IsCompletedSuccessfully) { await task; } } if (eventList.Count < CoreOptions.NumberOfEventsPerRead) { break; } } ; } } var onActivatedTask = OnBaseActivated(); if (!onActivatedTask.IsCompletedSuccessfully) { await onActivatedTask; } if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Grain activation completed with id = {0}", GrainId.ToString()); } } catch (Exception ex) { Logger.LogCritical(ex, "Grain activation failed with Id = {0}", GrainId.ToString()); throw; } }
protected async ValueTask Tell(IFullyEvent <PrimaryKey> @event) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.FollowEventProcessing, "Start event handling, grain Id = {0} and state version = {1},event type = {2} ,event = {3}", GrainId.ToString(), this.Snapshot.Base.Version, @event.GetType().FullName, Serializer.SerializeToString(@event)); } try { if (@event.Base.Version == Snapshot.Base.Version + 1) { var onEventDeliveredTask = OnEventDelivered(@event); if (!onEventDeliveredTask.IsCompletedSuccessfully) { await onEventDeliveredTask; } Snapshot.Base.FullUpdateVersion(@event.Base, GrainType);//更新处理完成的Version } else if (@event.Base.Version > Snapshot.Base.Version) { var eventList = await EventStorage.GetList(GrainId, Snapshot.Base.StartTimestamp, Snapshot.Base.Version + 1, @event.Base.Version - 1); foreach (var evt in eventList) { var onEventDeliveredTask = OnEventDelivered(evt); if (!onEventDeliveredTask.IsCompletedSuccessfully) { await onEventDeliveredTask; } Snapshot.Base.FullUpdateVersion(evt.Base, GrainType);//更新处理完成的Version } } if (@event.Base.Version == Snapshot.Base.Version + 1) { var onEventDeliveredTask = OnEventDelivered(@event); if (!onEventDeliveredTask.IsCompletedSuccessfully) { await onEventDeliveredTask; } Snapshot.Base.FullUpdateVersion(@event.Base, GrainType);//更新处理完成的Version } if (@event.Base.Version > Snapshot.Base.Version) { throw new EventVersionNotMatchStateException(GrainId.ToString(), GrainType, @event.Base.Version, this.Snapshot.Base.Version); } if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.FollowEventProcessing, "Event Handling Completion, grain Id ={0} and state version = {1},event type = {2}", GrainId.ToString(), this.Snapshot.Base.Version, @event.GetType().FullName); } } catch (Exception ex) { if (Logger.IsEnabled(LogLevel.Critical)) { Logger.LogCritical(LogEventIds.FollowEventProcessing, ex, "FollowGrain Event handling failed with Id = {0},event = {1}", GrainId.ToString(), Serializer.SerializeToString(@event)); } throw; } }
protected async Task BeginTransaction(long transactionId) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Transaction begin: {0}->{1}->{2}", GrainType.FullName, GrainId.ToString(), transactionId); } if (TransactionStartMilliseconds != 0 && DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - TransactionStartMilliseconds > CoreOptions.TransactionMillisecondsTimeout) { if (await TransactionTimeoutLock.WaitAsync(CoreOptions.TransactionMillisecondsTimeout)) { try { if (TransactionStartMilliseconds != 0 && DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - TransactionStartMilliseconds > CoreOptions.TransactionMillisecondsTimeout) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Transaction timeout: {0}->{1}->{2}", GrainType.FullName, GrainId.ToString(), transactionId); } await RollbackTransaction(CurrentTransactionId);//事务超时自动回滚 } } finally { TransactionTimeoutLock.Release(); } } } if (await TransactionSemaphore.WaitAsync(CoreOptions.TransactionMillisecondsTimeout)) { try { SnapshotCheck(); CurrentTransactionStartVersion = Snapshot.Base.Version + 1; CurrentTransactionId = transactionId; TransactionStartMilliseconds = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); } catch { TransactionSemaphore.Release(); throw; } } else { throw new BeginTxTimeoutException(GrainId.ToString(), transactionId, GrainType); } }
public override Task OnDeactivateAsync() { var needSaveSnap = Snapshot.Version - SnapshotEventVersion >= 1; if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation("Followgrain start deactivation with id = {0} ,{1}", GrainId.ToString(), needSaveSnap ? "updated snapshot" : "no update snapshot"); } if (needSaveSnap) { return(SaveSnapshotAsync(true).AsTask()); } else { return(Task.CompletedTask); } }
protected virtual async Task ReadSnapshotAsync() { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.GrainSnapshot, "Start read snapshot with Id = {0} ,state version = {1}", GrainId.ToString(), this.Snapshot.Base.Version); } try { Snapshot = await SnapshotStorage.Get(GrainId); if (Snapshot == default) { //从归档中恢复状态 if (ArchiveOptions.On && LastArchive != default) { Snapshot = await ArchiveStorage.GetState(LastArchive.Id); } } if (Snapshot == default) { //新建状态 var createTask = CreateState(); if (!createTask.IsCompletedSuccessfully) { await createTask; } } if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.GrainSnapshot, "The snapshot of id = {0} read completed, state version = {1}", GrainId.ToString(), this.Snapshot.Base.Version); } } catch (Exception ex) { if (Logger.IsEnabled(LogLevel.Critical)) { Logger.LogCritical(LogEventIds.GrainSnapshot, ex, "The snapshot of id = {0} read failed", GrainId.ToString()); } throw; } }
public async Task OnNext(Immutable <List <byte[]> > items) { var events = items.Value.Select(bytes => { var(success, transport) = EventBytesTransport.FromBytesWithNoId(bytes); if (success) { var eventType = TypeFinder.FindType(transport.EventTypeCode); var data = Serializer.Deserialize(transport.EventBytes, eventType); if (data is IEvent @event) { var eventBase = EventBase.FromBytes(transport.BaseBytes); if (eventBase.Version > Snapshot.Base.Version) { return(new FullyEvent <PrimaryKey> { StateId = GrainId, Base = eventBase, Event = @event }); } } else { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Non-Event: {0}->{1}->{2}", GrainType.FullName, GrainId.ToString(), Serializer.Serialize(data, eventType)); } } } return(default);
protected virtual async ValueTask <bool> RaiseEvent(IEventBase <K> @event, string uniqueId = null, string hashKey = null) { try { State.IncrementDoingVersion();//标记将要处理的Version @event.StateId = GrainId; @event.Version = State.Version + 1; @event.Timestamp = DateTime.UtcNow; var serializer = GetSerializer(); using (var ms = new PooledMemoryStream()) { serializer.Serialize(ms, @event); var bytes = ms.ToArray(); if (await(await GetEventStorage()).SaveAsync(@event, bytes, uniqueId)) { if (SupportAsync) { var data = new W { TypeCode = @event.TypeCode, BinaryBytes = bytes }; ms.Position = 0; ms.SetLength(0); serializer.Serialize(ms, data); //消息写入消息队列,以提供异步服务 Apply(State, @event); GetMQService().Publish(ms.ToArray(), string.IsNullOrEmpty(hashKey) ? GrainId.ToString() : hashKey); } else { Apply(State, @event); } State.UpdateVersion(@event);//更新处理完成的Version await SaveSnapshotAsync(); OnRaiseSuccess(@event, bytes); return(true); } else { State.DecrementDoingVersion();//还原doing Version } } } catch (Exception ex) { await RecoveryState();//还原状态 ExceptionDispatchInfo.Capture(ex).Throw(); } return(false); }
protected virtual async Task ReadSnapshotAsync() { try { Snapshot = await SnapshotStorage.Get(GrainId); if (Snapshot is null) { //从归档中恢复状态 if (ArchiveOptions.On && LastArchive != null) { Snapshot = await ArchiveStorage.GetById(LastArchive.Id); } } if (Snapshot is null) { //新建状态 var createTask = CreateSnapshot(); if (!createTask.IsCompletedSuccessfully) { await createTask; } } else if (IsTxShadow) { Snapshot = new TxSnapshot <PrimaryKey, StateType>() { Base = new TxSnapshotBase <PrimaryKey>(Snapshot.Base), State = Snapshot.State }; } if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("ReadSnapshot completed: {0}->{1}", GrainType.FullName, Serializer.Serialize(Snapshot)); } } catch (Exception ex) { Logger.LogCritical(ex, "ReadSnapshot failed: {0}->{1}", GrainType.FullName, GrainId.ToString()); throw; } }
public Task OnNext(Immutable <byte[]> bytes) { var(success, transport) = EventBytesTransport.FromBytesWithNoId(bytes.Value); if (success) { var eventType = TypeFinder.FindType(transport.EventTypeCode); var data = Serializer.Deserialize(transport.EventBytes, eventType); if (data is IEvent @event) { var eventBase = EventBase.FromBytes(transport.BaseBytes); if (eventBase.Version > Snapshot.Base.Version) { var tellTask = Tell(new FullyEvent <PrimaryKey> { StateId = GrainId, Base = eventBase, Event = @event }); if (!tellTask.IsCompletedSuccessfully) { return(tellTask.AsTask()); } } if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("OnNext completed: {0}->{1}->{2}", GrainType.FullName, GrainId.ToString(), Serializer.Serialize(data, eventType)); } } else { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Non-Event: {0}->{1}->{2}", GrainType.FullName, GrainId.ToString(), Serializer.Serialize(data, eventType)); } } } return(Task.CompletedTask); }
public override async Task OnActivateAsync() { var dITask = DependencyInjection(); if (!dITask.IsCompletedSuccessfully) { await dITask; } try { if (ArchiveOptions.On) { //加载最后一条归档 LastArchive = await ArchiveStorage.GetLatestBrief(GrainId); } await ReadSnapshotAsync(); if (FullyActive) { await RecoveryFromStorage(); } if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Activation completed: {0}->{1}", GrainType.FullName, Serializer.Serialize(Snapshot)); } } catch (Exception ex) { Logger.LogCritical(ex, "Activation failed: {0}->{1}", GrainType.FullName, GrainId.ToString()); throw; } }
protected virtual async ValueTask SaveSnapshotAsync(bool force = false) { if (SaveSnapshot) { if (force || (Snapshot.Version - SnapshotEventVersion >= ConfigOptions.FollowSnapshotVersionInterval)) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Start saving state snapshots with Id = {0} ,state version = {1}", GrainId.ToString(), Snapshot.Version); } try { var onSaveSnapshotTask = OnSaveSnapshot();//自定义保存项 if (!onSaveSnapshotTask.IsCompletedSuccessfully) { await onSaveSnapshotTask; } if (SnapshotEventVersion == 0) { await FollowSnapshotStorage.Insert(Snapshot); } else { await FollowSnapshotStorage.Update(Snapshot); } SnapshotEventVersion = Snapshot.Version; var onSavedSnapshotTask = OnSavedSnapshot(); if (!onSavedSnapshotTask.IsCompletedSuccessfully) { await onSavedSnapshotTask; } if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("State snapshot saved successfully with Id {0} ,state version = {1}", GrainId.ToString(), Snapshot.Version); } } catch (Exception ex) { Logger.LogError(ex, "State snapshot save failed with Id = {0}", GrainId.ToString()); throw; } } } }
protected virtual async Task ReadSnapshotAsync() { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Start read snapshot with Id = {0} ,state version = {1}", GrainId.ToString(), Snapshot.Version); } try { Snapshot = await FollowSnapshotStorage.Get(GrainId); if (Snapshot == null) { var createTask = CreateState(); if (!createTask.IsCompletedSuccessfully) { await createTask; } } SnapshotEventVersion = Snapshot.Version; if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("The snapshot of id = {0} read completed, state version = {1}", GrainId.ToString(), Snapshot.Version); } } catch (Exception ex) { Logger.LogCritical(ex, "The snapshot of id = {0} read failed", GrainId.ToString()); throw; } }
/// <summary> /// Removes an activation of the given grain from the partition /// </summary> /// <param name="grain"></param> /// <param name="activation"></param> /// <param name="force"></param> internal void RemoveActivation(GrainId grain, ActivationId activation, bool force) { lock (lockable) { if (partitionData.ContainsKey(grain) && partitionData[grain].RemoveActivation(activation, force)) { partitionData.Remove(grain); } } if (log.IsVerbose3) log.Verbose3("Removing activation for grain {0}", grain.ToString()); }
/// <summary> /// Removes an activation of the given grain from the partition /// </summary> /// <param name="grain">the identity of the grain</param> /// <param name="activation">the id of the activation</param> /// <param name="cause">reason for removing the activation</param> /// <param name="entry">returns the entry, if found </param> /// <param name="wasRemoved">returns whether the entry was actually removed</param> internal void RemoveActivation(GrainId grain, ActivationId activation, UnregistrationCause cause, out IActivationInfo entry, out bool wasRemoved) { wasRemoved = false; entry = null; lock (lockable) { if (partitionData.ContainsKey(grain) && partitionData[grain].RemoveActivation(activation, cause, out entry, out wasRemoved)) { // if the last activation for the grain was removed, we remove the entire grain info partitionData.Remove(grain); } } if (log.IsVerbose3) { log.Verbose3("Removing activation for grain {0} cause={1} was_removed={2}", grain.ToString(), cause, wasRemoved); } }
public Task EventHandle(TransferEvent evt, EventBase eventBase) { var toActor = GrainFactory.GetGrain <IAccount>(evt.ToId); return(toActor.TransferArrived(evt.Amount, new EventUID(eventBase.GetEventId(GrainId.ToString()), eventBase.Timestamp))); }
private RemoteClusterActivationResponse ProcessRequestLocal(GrainId grain, string requestClusterId) { RemoteClusterActivationResponse response; //This function will be called only on the Owner silo. try { ActivationAddress address; int version; GrainDirectoryEntryStatus existingActivationStatus = router.DirectoryPartition.TryGetActivation(grain, out address, out version); //Return appropriate protocol response, given current mc status switch (existingActivationStatus) { case GrainDirectoryEntryStatus.Invalid: response = RemoteClusterActivationResponse.Pass; break; case GrainDirectoryEntryStatus.Owned: response = new RemoteClusterActivationResponse(ActivationResponseStatus.Failed) { ExistingActivationAddress = new AddressAndTag() { Address = address, VersionTag = version }, ClusterId = clusterId, Owned = true }; break; case GrainDirectoryEntryStatus.Cached: case GrainDirectoryEntryStatus.RaceLoser: response = RemoteClusterActivationResponse.Pass; break; case GrainDirectoryEntryStatus.RequestedOwnership: case GrainDirectoryEntryStatus.Doubtful: var iWin = MultiClusterUtils.ActivationPrecedenceFunc(grain, clusterId, requestClusterId); if (iWin) { response = new RemoteClusterActivationResponse(ActivationResponseStatus.Failed) { ExistingActivationAddress = new AddressAndTag() { Address = address, VersionTag = version }, ClusterId = clusterId, Owned = false }; } else { response = RemoteClusterActivationResponse.Pass; //update own activation status to race loser. if (existingActivationStatus == GrainDirectoryEntryStatus.RequestedOwnership) { logger.Verbose2("GSIP:Rsp {0} Origin={1} RaceLoser", grain.ToString(), requestClusterId); var success = router.DirectoryPartition.UpdateClusterRegistrationStatus(grain, address.Activation, GrainDirectoryEntryStatus.RaceLoser, GrainDirectoryEntryStatus.RequestedOwnership); if (!success) { // there was a race. retry. logger.Verbose2("GSIP:Rsp {0} Origin={1} Retry", grain.ToString(), requestClusterId); return ProcessRequestLocal(grain, requestClusterId); } } } break; default: throw new InvalidOperationException("Invalid MultiClusterStatus value"); } } catch (Exception ex) { //LOG exception response = new RemoteClusterActivationResponse(ActivationResponseStatus.Faulted) { ResponseException = ex }; } if (logger.IsVerbose) logger.Verbose("GSIP:Rsp {0} Origin={1} Result={2}", grain.ToString(), requestClusterId, response); return response; }
private async Task BatchInputProcessing(List <ConcurrentTransport <Snapshot <PrimaryKey, SnapshotType> > > inputs) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Start batch event processing with id = {0},state version = {1},the number of events = {2}", GrainId.ToString(), CurrentTransactionStartVersion, inputs.Count.ToString()); } await BeginTransaction(defaultTransactionId); try { foreach (var input in inputs) { await input.Handler(Snapshot, (evt, uniqueId) => { TransactionRaiseEvent(evt, uniqueId); input.Executed = true; return(Task.CompletedTask); }); } await CommitTransaction(defaultTransactionId); await FinishTransaction(defaultTransactionId); foreach (var input in inputs) { if (input.Executed) { var completeTask = input.CompletedHandler(true); if (!completeTask.IsCompletedSuccessfully) { await completeTask; } } } } catch (Exception batchEx) { Logger.LogError(batchEx, batchEx.Message); try { await RollbackTransaction(defaultTransactionId); await ReTry(); } catch (Exception ex) { Logger.LogError(ex, ex.Message); inputs.ForEach(input => input.ExceptionHandler(ex)); } } var onCompletedTask = OnBatchInputProcessed(); if (!onCompletedTask.IsCompletedSuccessfully) { await onCompletedTask; } if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Batch events have been processed with id = {0},state version = {1},the number of events = {2}", GrainId.ToString(), CurrentTransactionStartVersion, inputs.Count.ToString()); } async Task ReTry() { foreach (var input in inputs) { try { await input.Handler(Snapshot, async (evt, uniqueId) => { var result = await RaiseEvent(evt, uniqueId); var completeTask = input.CompletedHandler(result); if (!completeTask.IsCompletedSuccessfully) { await completeTask; } }); } catch (Exception ex) { Logger.LogError(ex, ex.Message); input.ExceptionHandler(ex); } } } }
protected virtual async Task RecoveryState() { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.GrainStateRecoveryId, "The state of id = {0} begin to recover", GrainType.FullName, GrainId.ToString()); } try { await ReadSnapshotAsync(); while (!Snapshot.Base.IsLatest) { var eventList = await EventStorage.GetList(GrainId, Snapshot.Base.LatestMinEventTimestamp, Snapshot.Base.Version + 1, Snapshot.Base.Version + CoreOptions.NumberOfEventsPerRead); foreach (var @event in eventList) { Snapshot.Base.IncrementDoingVersion(GrainType); //标记将要处理的Version EventHandler.Apply(Snapshot, @event); Snapshot.Base.UpdateVersion(@event.Base, GrainType); //更新处理完成的Version } if (eventList.Count < CoreOptions.NumberOfEventsPerRead) { break; } } ; if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.GrainStateRecoveryId, "The state of id = {0} recovery has been completed ,state version = {1}", GrainId.ToString(), Snapshot.Base.Version); } } catch (Exception ex) { Logger.LogCritical(LogEventIds.GrainStateRecoveryId, ex, "The state of id = {0} recovery has failed ,state version = {1}", GrainId.ToString(), Snapshot.Base.Version); throw; } }
public override async Task OnActivateAsync() { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.GrainActivateId, "Start activation followgrain with id = {0}", GrainId.ToString()); } var dITask = DependencyInjection(); if (!dITask.IsCompletedSuccessfully) { await dITask; } try { if (ArchiveOptions.On) { //加载最后一条归档 LastArchive = await ArchiveStorage.GetLatestBrief(GrainId); } await ReadSnapshotAsync(); if (FullyActive) { await FullActive(); } if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.GrainActivateId, "Followgrain activation completed with id = {0}", GrainId.ToString()); } } catch (Exception ex) { if (Logger.IsEnabled(LogLevel.Critical)) { Logger.LogCritical(LogEventIds.FollowGrainActivateId, ex, "Followgrain activation failed with Id = {0}", GrainId.ToString()); } throw; } }
public override async Task OnDeactivateAsync() { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.GrainDeactivateId, "Grain start deactivation with id = {0}", GrainId.ToString()); } var needSaveSnap = Snapshot.Base.Version - SnapshotEventVersion >= CoreOptions.MinSnapshotIntervalVersion; try { if (needSaveSnap) { var saveTask = SaveSnapshotAsync(true, true); if (!saveTask.IsCompletedSuccessfully) { await saveTask; } var onDeactivatedTask = OnDeactivated(); if (!onDeactivatedTask.IsCompletedSuccessfully) { await onDeactivatedTask; } } if (ArchiveOptions.On && NewArchive != default) { if (NewArchive.EndVersion - NewArchive.StartVersion >= ArchiveOptions.MinIntervalVersion) { var archiveTask = Archive(true); if (!archiveTask.IsCompletedSuccessfully) { await archiveTask; } } } if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.GrainDeactivateId, "Grain has been deactivated with id= {0} ,{1}", GrainId.ToString(), needSaveSnap ? "updated snapshot" : "no update snapshot"); } } catch (Exception ex) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError(LogEventIds.GrainActivateId, ex, "Grain Deactivate failed with Id = {0}", GrainType.FullName, GrainId.ToString()); } throw; } }
public Task Tell(byte[] bytes) { var(success, transport) = EventBytesTransport.FromBytesWithNoId(bytes); if (success) { var eventType = TypeContainer.GetType(transport.EventType); var data = Serializer.Deserialize(eventType, transport.EventBytes); if (data is IEvent @event) { var eventBase = EventBase.FromBytes(transport.BaseBytes); if (eventBase.Version > Snapshot.Base.Version) { var tellTask = Tell(new FullyEvent <PrimaryKey> { StateId = GrainId, Base = eventBase, Event = @event }); if (!tellTask.IsCompletedSuccessfully) { return(tellTask.AsTask()); } } } else { if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation(LogEventIds.FollowEventProcessing, "Receive non-event messages, grain Id = {0} ,message type = {1}", GrainId.ToString(), transport.EventType); } } } return(Task.CompletedTask); }
protected async ValueTask SaveSnapshotAsync(bool force = false, bool isLatest = false) { if (Snapshot.Base.Version != Snapshot.Base.DoingVersion) { throw new StateInsecurityException(Snapshot.Base.StateId.ToString(), GrainType, Snapshot.Base.DoingVersion, Snapshot.Base.Version); } if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.GrainSnapshot, "Start save snapshot with Id = {0} ,state version = {1}", GrainId.ToString(), Snapshot.Base.Version); } //如果版本号差超过设置则更新快照 if (force || (Snapshot.Base.Version - SnapshotEventVersion >= CoreOptions.SnapshotIntervalVersion)) { var oldLatestMinEventTimestamp = Snapshot.Base.LatestMinEventTimestamp; try { var onSaveSnapshotTask = OnStartSaveSnapshot(); if (!onSaveSnapshotTask.IsCompletedSuccessfully) { await onSaveSnapshotTask; } Snapshot.Base.LatestMinEventTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); Snapshot.Base.IsLatest = isLatest; if (SnapshotEventVersion == 0) { await SnapshotStorage.Insert(Snapshot); } else { await SnapshotStorage.Update(Snapshot); } SnapshotEventVersion = Snapshot.Base.Version; if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.GrainSnapshot, "The snapshot of id={0} save completed ,state version = {1}", GrainId.ToString(), Snapshot.Base.Version); } } catch (Exception ex) { Snapshot.Base.LatestMinEventTimestamp = oldLatestMinEventTimestamp; if (Logger.IsEnabled(LogLevel.Critical)) { Logger.LogCritical(LogEventIds.GrainSnapshot, ex, "The snapshot of id= {0} save failed", GrainId.ToString()); } throw; } } }
private RemoteClusterActivationResponse ProcessRequestLocal(GrainId grain, string requestClusterId) { RemoteClusterActivationResponse response; //This function will be called only on the Owner silo. try { ActivationAddress address; int version; GrainDirectoryEntryStatus existingActivationStatus = router.DirectoryPartition.TryGetActivation(grain, out address, out version); //Return appropriate protocol response, given current mc status switch (existingActivationStatus) { case GrainDirectoryEntryStatus.Invalid: response = RemoteClusterActivationResponse.Pass; break; case GrainDirectoryEntryStatus.Owned: response = new RemoteClusterActivationResponse(ActivationResponseStatus.Failed) { ExistingActivationAddress = new AddressAndTag() { Address = address, VersionTag = version }, ClusterId = clusterId, Owned = true }; break; case GrainDirectoryEntryStatus.Cached: case GrainDirectoryEntryStatus.RaceLoser: response = RemoteClusterActivationResponse.Pass; break; case GrainDirectoryEntryStatus.RequestedOwnership: case GrainDirectoryEntryStatus.Doubtful: var iWin = MultiClusterUtils.ActivationPrecedenceFunc(grain, clusterId, requestClusterId); if (iWin) { response = new RemoteClusterActivationResponse(ActivationResponseStatus.Failed) { ExistingActivationAddress = new AddressAndTag() { Address = address, VersionTag = version }, ClusterId = clusterId, Owned = false }; } else { response = RemoteClusterActivationResponse.Pass; //update own activation status to race loser. if (existingActivationStatus == GrainDirectoryEntryStatus.RequestedOwnership) { logger.Trace("GSIP:Rsp {0} Origin={1} RaceLoser", grain.ToString(), requestClusterId); var success = router.DirectoryPartition.UpdateClusterRegistrationStatus(grain, address.Activation, GrainDirectoryEntryStatus.RaceLoser, GrainDirectoryEntryStatus.RequestedOwnership); if (!success) { // there was a race. retry. logger.Trace("GSIP:Rsp {0} Origin={1} Retry", grain.ToString(), requestClusterId); return(ProcessRequestLocal(grain, requestClusterId)); } } } break; default: throw new InvalidOperationException("Invalid MultiClusterStatus value"); } } catch (Exception ex) { //LOG exception response = new RemoteClusterActivationResponse(ActivationResponseStatus.Faulted) { ResponseException = ex }; } if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug("GSIP:Rsp {0} Origin={1} Result={2}", grain.ToString(), requestClusterId, response); } return(response); }
protected virtual async Task <bool> RaiseEvent(IEvent @event, EventUID uniqueId = null) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.GrainSnapshot, "Start raise event, grain Id ={0} and state version = {1},event type = {2} ,event ={3},uniqueueId= {4}", GrainId.ToString(), Snapshot.Base.Version, @event.GetType().FullName, Serializer.SerializeToString(@event), uniqueId); } if (Snapshot.Base.IsOver) { throw new StateIsOverException(Snapshot.Base.StateId.ToString(), GrainType); } try { var fullyEvent = new FullyEvent <PrimaryKey> { Event = @event, Base = new EventBase { Version = Snapshot.Base.Version + 1 }, StateId = Snapshot.Base.StateId }; if (uniqueId == default) { uniqueId = EventUID.Empty; } if (string.IsNullOrEmpty(uniqueId.UID)) { fullyEvent.Base.Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); } else { fullyEvent.Base.Timestamp = uniqueId.Timestamp; } var startTask = OnRaiseStart(fullyEvent); if (!startTask.IsCompletedSuccessfully) { await startTask; } Snapshot.Base.IncrementDoingVersion(GrainType);//标记将要处理的Version var bytesTransport = new EventBytesTransport { EventType = @event.GetType().FullName, ActorId = Snapshot.Base.StateId, EventBytes = Serializer.SerializeToBytes(@event), BaseBytes = fullyEvent.Base.GetBytes() }; if (await EventStorage.Append(new SaveTransport <PrimaryKey>(fullyEvent, bytesTransport, uniqueId.UID))) { EventHandler.Apply(Snapshot, fullyEvent); Snapshot.Base.UpdateVersion(fullyEvent.Base, GrainType);//更新处理完成的Version var task = OnRaiseSuccessed(fullyEvent, bytesTransport); if (!task.IsCompletedSuccessfully) { await task; } var saveSnapshotTask = SaveSnapshotAsync(); if (!saveSnapshotTask.IsCompletedSuccessfully) { await saveSnapshotTask; } var handlers = FollowUnit.GetAllEventHandlers(); if (handlers.Count > 0) { try { if (CoreOptions.PriorityAsyncEventBus) { try { var publishTask = EventBusProducer.Publish(bytesTransport.GetBytes(), GrainId.ToString()); if (!publishTask.IsCompletedSuccessfully) { await publishTask; } } catch (Exception ex) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError(LogEventIds.GrainRaiseEvent, ex, "EventBus error,state Id ={0}, version ={1}", GrainId.ToString(), Snapshot.Base.Version); } //当消息队列出现问题的时候同步推送 await Task.WhenAll(handlers.Select(func => func(bytesTransport.GetBytes()))); } } else { try { await Task.WhenAll(handlers.Select(func => func(bytesTransport.GetBytes()))); } catch (Exception ex) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError(LogEventIds.GrainRaiseEvent, ex, "EventBus error,state Id ={0}, version ={1}", GrainId.ToString(), Snapshot.Base.Version); } //当消息队列出现问题的时候异步推送 var publishTask = EventBusProducer.Publish(bytesTransport.GetBytes(), GrainId.ToString()); if (!publishTask.IsCompletedSuccessfully) { await publishTask; } } } } catch (Exception ex) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError(LogEventIds.GrainRaiseEvent, ex, "EventBus error,state Id ={0}, version ={1}", GrainId.ToString(), Snapshot.Base.Version); } } } if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.GrainRaiseEvent, "Raise event successfully, grain Id= {0} and state version = {1}}", GrainId.ToString(), Snapshot.Base.Version); } return(true); } else { if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation(LogEventIds.GrainRaiseEvent, "Raise event failure because of idempotency limitation, grain Id = {0},state version = {1},event type = {2} with version = {3}", GrainId.ToString(), Snapshot.Base.Version, @event.GetType().FullName, fullyEvent.Base.Version); } var task = OnRaiseFailed(fullyEvent); if (!task.IsCompletedSuccessfully) { await task; } Snapshot.Base.DecrementDoingVersion();//还原doing Version } } catch (Exception ex) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError(LogEventIds.GrainRaiseEvent, ex, "Raise event produces errors, state Id = {0}, version ={1},event type = {2},event = {3}", GrainId.ToString(), Snapshot.Base.Version, @event.GetType().FullName, Serializer.SerializeToString(@event)); } await RecoveryState();//还原状态 throw; } return(false); }
public async Task CommitTransaction(long transactionId) { if (WaitingForTransactionTransports.Count > 0) { if (CurrentTransactionId != transactionId) { throw new TxCommitException(); } try { var onCommitTask = OnCommitTransaction(transactionId); if (!onCommitTask.IsCompletedSuccessfully) { await onCommitTask; } foreach (var transport in WaitingForTransactionTransports) { var startTask = OnRaiseStart(transport.FullyEvent); if (!startTask.IsCompletedSuccessfully) { await startTask; } var evtType = transport.FullyEvent.Event.GetType(); transport.BytesTransport = new EventBytesTransport( TypeContainer.GetTypeCode(evtType), GrainId, transport.FullyEvent.Base.GetBytes(), Serializer.SerializeToUtf8Bytes(transport.FullyEvent.Event, evtType) ); } await EventStorage.TransactionBatchAppend(WaitingForTransactionTransports); if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Transaction Commited: {0}->{1}->{2}", GrainType.FullName, GrainId.ToString(), transactionId); } } catch (Exception ex) { Logger.LogError(ex, "Transaction failed: {0}->{1}->{2}", GrainType.FullName, GrainId.ToString(), transactionId); throw; } } }
/// <summary> /// 发送无状态更改的消息到消息队列 /// </summary> /// <returns></returns> protected async ValueTask Publish <T>(T msg, string hashKey = null) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace(LogEventIds.MessagePublish, "Start publishing, grain Id= {0}, message type = {1},message = {2},hashkey={3}", GrainId.ToString(), msg.GetType().FullName, Serializer.SerializeToString(msg), hashKey); } if (string.IsNullOrEmpty(hashKey)) { hashKey = GrainId.ToString(); } try { var wrapper = new CommonTransport(msg.GetType().FullName, Serializer.SerializeToBytes(msg)); var pubLishTask = EventBusProducer.Publish(wrapper.GetBytes(), hashKey); if (!pubLishTask.IsCompletedSuccessfully) { await pubLishTask; } } catch (Exception ex) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError(LogEventIds.MessagePublish, ex, "Publish message errors, grain Id= {0}, message type = {1},message = {2},hashkey={3}", GrainId.ToString(), msg.GetType().FullName, Serializer.SerializeToString(msg), hashKey); } throw; } }
private GrainId RoundTripGrainIdToParsable(GrainId input) { string str = input.ToString(); return(GrainId.Parse(str)); }
protected async Task BeginTransaction(long transactionId) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Begin transaction with grainid {0} and transactionId {1},transaction start state version {2}", GrainId.ToString(), transactionId, CurrentTransactionStartVersion.ToString()); } if (TransactionStartMilliseconds != 0 && DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - TransactionStartMilliseconds > CoreOptions.TransactionMillisecondsTimeout) { if (await TransactionTimeoutLock.WaitAsync(CoreOptions.TransactionMillisecondsTimeout)) { try { if (TransactionStartMilliseconds != 0 && DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - TransactionStartMilliseconds > CoreOptions.TransactionMillisecondsTimeout) { await RollbackTransaction(CurrentTransactionId);//事务超时自动回滚 Logger.LogError("Transaction timeout, automatic rollback,grain id = {1}", GrainId.ToString()); } } finally { TransactionTimeoutLock.Release(); } } } if (await TransactionSemaphore.WaitAsync(CoreOptions.TransactionMillisecondsTimeout)) { try { SnapshotCheck(); CurrentTransactionStartVersion = Snapshot.Base.Version + 1; CurrentTransactionId = transactionId; TransactionStartMilliseconds = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); } catch { TransactionSemaphore.Release(); throw; } } else { throw new BeginTxTimeoutException(GrainId.ToString(), transactionId, GrainType); } }
public async Task CommitTransaction(long transactionId) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Commit transaction with id = {0},event counts = {1}, from version {2} to version {3}", GrainId.ToString(), WaitingForTransactionTransports.Count.ToString(), CurrentTransactionStartVersion.ToString(), Snapshot.Base.Version.ToString()); } if (WaitingForTransactionTransports.Count > 0) { if (CurrentTransactionId != transactionId) { throw new TxCommitException(); } try { var onCommitTask = OnCommitTransaction(transactionId); if (!onCommitTask.IsCompletedSuccessfully) { await onCommitTask; } foreach (var transport in WaitingForTransactionTransports) { var startTask = OnRaiseStart(transport.FullyEvent); if (!startTask.IsCompletedSuccessfully) { await startTask; } transport.BytesTransport = new EventBytesTransport( TypeContainer.GetTypeCode(transport.FullyEvent.Event.GetType()), GrainId, transport.FullyEvent.Base.GetBytes(), Serializer.SerializeToBytes(transport.FullyEvent.Event) ); } await EventStorage.TransactionBatchAppend(WaitingForTransactionTransports); } catch (Exception ex) { Logger.LogError(ex, "Commit transaction failed, grain Id = {1}", GrainId.ToString()); throw; } } }
public async Task RollbackTransaction(long transactionId) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Start rollback transaction with id = {0},event counts = {1}, from version {2} to version {3}", GrainId.ToString(), WaitingForTransactionTransports.Count.ToString(), CurrentTransactionStartVersion.ToString(), Snapshot.Base.Version.ToString()); } if (CurrentTransactionId == transactionId && CurrentTransactionStartVersion != -1 && Snapshot.Base.Version >= CurrentTransactionStartVersion) { try { if (BackupSnapshot.Base.Version == CurrentTransactionStartVersion - 1) { Snapshot = new Snapshot <PrimaryKey, StateType>(GrainId) { Base = BackupSnapshot.Base.Clone(), State = BackupSnapshot.State.Clone() }; } else { if (BackupSnapshot.Base.Version >= CurrentTransactionStartVersion) { await EventStorage.DeleteEnd(Snapshot.Base.StateId, CurrentTransactionStartVersion, Snapshot.Base.LatestMinEventTimestamp); } await RecoverySnapshot(); } WaitingForTransactionTransports.Clear(); RestoreTransactionTemporaryState(); TransactionSemaphore.Release(); if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Rollback transaction successfully with id = {0},state version = {1}", GrainId.ToString(), Snapshot.Base.Version.ToString()); } } catch (Exception ex) { Logger.LogCritical(ex, "Rollback transaction failed with Id = {1}", GrainId.ToString()); throw; } } }
/// <summary> /// Adds a new activation to the directory partition /// </summary> /// <param name="grain"></param> /// <param name="activation"></param> /// <param name="silo"></param> /// <returns>The version associated with this directory mapping</returns> internal virtual int AddActivation(GrainId grain, ActivationId activation, SiloAddress silo) { if (!IsValidSilo(silo)) { return GrainInfo.NO_ETAG; } lock (lockable) { if (!partitionData.ContainsKey(grain)) { partitionData[grain] = new GrainInfo(); } partitionData[grain].AddActivation(activation, silo); } if (log.IsVerbose3) log.Verbose3("Adding activation for grain {0}", grain.ToString()); return partitionData[grain].VersionTag; }
/// <summary> /// 事务性事件提交 /// 使用该函数前必须开启事务,不然会出现异常 /// </summary> /// <param name="event"></param> /// <param name="eUID"></param> protected void TxRaiseEvent(IEvent @event, EventUID eUID = null) { if (Logger.IsEnabled(LogLevel.Trace)) { Logger.LogTrace("Start transactionRaiseEvent, grain Id ={0} and state version = {1},event type = {2} ,event = {3},uniqueueId = {4}", GrainId.ToString(), Snapshot.Base.Version, @event.GetType().FullName, Serializer.SerializeToString(@event), eUID); } try { if (CurrentTransactionStartVersion == -1) { throw new UnopenedTransactionException(GrainId.ToString(), GrainType, nameof(TxRaiseEvent)); } Snapshot.Base.IncrementDoingVersion(GrainType);//标记将要处理的Version var fullyEvent = new FullyEvent <PrimaryKey> { StateId = GrainId, Event = @event, Base = new EventBase { Version = Snapshot.Base.Version + 1 } }; string unique = default; if (eUID == default) { fullyEvent.Base.Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); unique = fullyEvent.GetEventId(); } else { fullyEvent.Base.Timestamp = eUID.Timestamp; unique = eUID.UID; } WaitingForTransactionTransports.Add(new EventTransport <PrimaryKey>(fullyEvent, unique, fullyEvent.StateId.ToString())); SnapshotHandler.Apply(Snapshot, fullyEvent); Snapshot.Base.UpdateVersion(fullyEvent.Base, GrainType);//更新处理完成的Version } catch (Exception ex) { Logger.LogCritical(ex, "Grain Id = {0},event type = {1} and event = {2}", GrainId.ToString(), @event.GetType().FullName, Serializer.SerializeToString(@event)); Snapshot.Base.DecrementDoingVersion();//还原doing Version throw; } }
/// <summary> /// Removes the grain (and, effectively, all its activations) from the diretcory /// </summary> /// <param name="grain"></param> internal void RemoveGrain(GrainId grain) { lock (lockable) { partitionData.Remove(grain); } if (log.IsVerbose3) log.Verbose3("Removing grain {0}", grain.ToString()); }
/// <summary> /// Adds a new activation to the directory partition /// </summary> /// <param name="grain"></param> /// <param name="activation"></param> /// <param name="silo"></param> /// <returns>The version associated with this directory mapping</returns> internal virtual int AddActivation(GrainId grain, ActivationId activation, SiloAddress silo) { if (!IsValidSilo(silo)) { return GrainInfo.NO_ETAG; } IGrainInfo grainInfo; lock (lockable) { if (!partitionData.TryGetValue(grain, out grainInfo)) { partitionData[grain] = grainInfo = new GrainInfo(); } grainInfo.AddActivation(activation, silo); } if (log.IsVerbose3) log.Verbose3("Adding activation for grain {0}", grain.ToString()); return grainInfo.VersionTag; }