Exemplo n.º 1
0
        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));
        }
Exemplo n.º 2
0
        public async Task <IActionResult> MoveCitizen(long id)
        {
            await _asyncBusEntity.PublishMessageAsync(
                new MoveCitizen
            {
                BaseVersionNumber = id,
                NewAddress        = Guid.NewGuid().ToString("N")
            });

            return(Ok());
        }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
 public static Task PublishMessageAsync <T>(this IAsyncBusEntity entity, T message) where T : class
 {
     return(entity.PublishMessageAsync(new Dictionary <string, string>(), message));
 }
Exemplo n.º 5
0
        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;
                    }
                }
            }
        }