public async Task <Tuple <long, Task <long> > > PromoteNewVersion(IAsyncBusEntity bus, long baseVersionNumber) { var versionAccumulator = _versions.AddOrUpdate(Interlocked.Increment(ref _versionNumber), v => new SingleVersionAccumulator(v, baseVersionNumber), a => a.ConfirmVersion(baseVersionNumber)); _log.LogVerbose($"Vendor actor instance #{FactoryInstanceId} of factory '{FactoryId}' promote new version #{versionAccumulator.VersionNumber} for base #{baseVersionNumber}"); await bus.PublishMessageAsync(new VersionConfirmNotification(FactoryId, FactoryInstanceId, versionAccumulator.VersionNumber, baseVersionNumber)); return(new Tuple <long, Task <long> >(versionAccumulator.VersionNumber, versionAccumulator.ConfirmTask)); }
public async Task <IActionResult> MoveCitizen(long id) { await _asyncBusEntity.PublishMessageAsync( new MoveCitizen { BaseVersionNumber = id, NewAddress = Guid.NewGuid().ToString("N") }); return(Ok()); }
public async Task <long> ApplyUpdateAsync(ICumulativeUpdate <T> cumulativeUpdate) { _log.LogInformation($"Begin apply update for base #{cumulativeUpdate.BaseVersionNumber} of type {cumulativeUpdate.GetType().Name}"); var versionTuple = await _vendor.PromoteNewVersion(_bus, cumulativeUpdate.BaseVersionNumber); _log.LogVerbose($"Vendor promoted new version #{versionTuple.Item1} for base #{cumulativeUpdate.BaseVersionNumber}"); await _bus.PublishMessageAsync(new VersionCumulativeUpdateNotification <T>(FactoryId, FactoryInstanceId, versionTuple.Item1, cumulativeUpdate)); _log.LogVerbose($"Wait for initial verision #{versionTuple.Item1} to be confirmed or moved by other guys"); return(await versionTuple.Item2); }
public static Task PublishMessageAsync <T>(this IAsyncBusEntity entity, T message) where T : class { return(entity.PublishMessageAsync(new Dictionary <string, string>(), message)); }
private async Task ProcessConfirmedVersions(IAsyncBusEntity bus) { Func <long, VersionAccumulator> moveVersionFunc = null; var confirmedVersionNumber = Volatile.Read(ref _confirmedVersionNumber); var versionNumber = Volatile.Read(ref _versionNumber); _log.LogVerbose($"Start process confirmed versions from #{confirmedVersionNumber} to #{versionNumber}"); while (confirmedVersionNumber <= versionNumber) { _log.LogInformation($"Processing version #{confirmedVersionNumber}"); VersionAccumulator originalAccumulator; var versionAccumulator = _versions.AddOrUpdate(confirmedVersionNumber, v => null, a => a.ApproveOrMoveVersion(out moveVersionFunc), out originalAccumulator); if (versionAccumulator == null) { _log.LogInformation($"Version #{confirmedVersionNumber} doesn't exist"); return; } if (versionAccumulator.IsCompleted && originalAccumulator?.IsCompleted == true) { _log.LogVerbose($"Version #{confirmedVersionNumber} has been already approved or moved"); confirmedVersionNumber = Interlocked.Increment(ref _confirmedVersionNumber); continue; } if (versionAccumulator.IsCompleted || (!versionAccumulator.IsCompleted && confirmedVersionNumber == versionNumber)) { var baseVersion = (versionAccumulator as BaseVersionAccumulator)?.BaseVersionNumber; if (baseVersion == null) { throw new InvalidOperationException($"Version accumulator #{versionAccumulator.VersionNumber} cannot be completed with multiple base versions"); } if (moveVersionFunc != null) { _log.LogInformation((int)Events.Moving, $"Moving version #{versionAccumulator.VersionNumber} for base #{baseVersion}"); VersionAccumulator currentAccumulator; do { versionNumber = Interlocked.Increment(ref _versionNumber); _versions.AddOrUpdate(versionNumber, moveVersionFunc, a => a, out currentAccumulator); } while (currentAccumulator != null); _log.LogInformation((int)Events.Moved, $"Moved version #{versionAccumulator.VersionNumber} for base #{baseVersion} to version #{versionNumber}"); await bus.PublishMessageAsync(new VersionMoveAndConfirmNotification(FactoryId, FactoryInstanceId, versionNumber, baseVersion.Value, versionAccumulator.VersionNumber)); } else { _log.LogInformation((int)Events.Approved, $"Approved version #{versionAccumulator.VersionNumber} for base #{baseVersion}"); await bus.PublishMessageAsync(new VersionConfirmNotification(FactoryId, FactoryInstanceId, versionAccumulator.VersionNumber, baseVersion.Value)); } confirmedVersionNumber = Interlocked.Increment(ref _confirmedVersionNumber); if (confirmedVersionNumber > versionNumber) { if (Interlocked.CompareExchange(ref _versionNumber, confirmedVersionNumber, versionNumber) == versionNumber) { _log.LogInformation((int)Events.SetVersion, $"Set last version number #{confirmedVersionNumber}"); } return; } } } }