Пример #1
0
        private async Task CommitAsync(IClientSessionHandle session, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
#if NETFULL
                await session.CommitTransactionAsync(cancellationToken).ConfigureAwait(false);
#else
                await session.CommitTransactionAsync(cancellationToken);
#endif
            }
            catch (Exception)
            {
                throw;
            }
        }
Пример #2
0
 public async Task CommitAsync(CancellationToken cancellationToken)
 {
     if (_clientSession.IsInTransaction)
     {
         await _clientSession.CommitTransactionAsync(cancellationToken).ConfigureAwait(false);
     }
 }
Пример #3
0
        public override async Task <IList <TransactionLog> > PerformTransactions(
            IEnumerable <Transaction <T> > transactions,
            CancellationToken token = default)
        {
            List <Action> adjustBalanceActions = new List <Action>();

            using IClientSessionHandle session = await _mongoClient.StartSessionAsync(cancellationToken : token);

            var transactionLogEntries = await session.WithTransactionAsync(async (sessionInner, tokenInner) =>
            {
                IList <TransactionLog> logEntries = new List <TransactionLog>();
                foreach (Transaction <T> transaction in transactions)
                {
                    TransactionLog log = await PerformSingleTransaction(transaction, sessionInner, tokenInner);
                    // defer all in-memory adjustments until the end in case any of the transactions failed.
                    adjustBalanceActions.Add(() => _currencyFieldSetter(transaction.User, log.NewBalance));
                    logEntries.Add(log);
                }
                return(logEntries);
            },
                                                                           new TransactionOptions(), token);

            await session.CommitTransactionAsync(token);

            adjustBalanceActions.ForEach(action => action());
            return(transactionLogEntries);
        }
Пример #4
0
        public async Task <Status> IsReadyAsync(CancellationToken cancellationToken)
        {
            var            client  = new MongoClient(_connectionString);
            IMongoDatabase adminDb = client.GetDatabase("admin");
            var            command = new BsonDocumentCommand <BsonDocument>(new BsonDocument
            {
                { "isMaster", 1 }
            });

            BsonDocument res = await adminDb.RunCommandAsync(command);

            bool isMaster = res.GetValue("ismaster").AsBoolean;

            if (isMaster)
            {
                IClientSessionHandle session = await client.StartSessionAsync();

                session.StartTransaction();
                await session.CommitTransactionAsync();
            }

            return(new Status
            {
                IsReady = isMaster,
                Message = res.ToString()
            });
        }
Пример #5
0
        private static async Task <bool> CommitWithRetriesAsync(IClientSessionHandle clientSession, DateTime startTime, IClock clock, CancellationToken cancellationToken)
        {
            while (true)
            {
                try
                {
                    await clientSession.CommitTransactionAsync(cancellationToken).ConfigureAwait(false);

                    return(true);
                }
                catch (Exception ex)
                {
                    var now = clock.UtcNow; // call UtcNow once since we need to facilitate predictable mocking
                    if (ShouldRetryCommit(ex, startTime, now))
                    {
                        continue;
                    }

                    if (HasErrorLabel(ex, TransientTransactionErrorLabel) && !HasTimedOut(startTime, now))
                    {
                        return(false); // the transaction will be retried
                    }

                    throw;
                }
            }
        }
Пример #6
0
 public async Task CommitTransactionAsync()
 {
     if (_session != null && _session.IsInTransaction)
     {
         await _session?.CommitTransactionAsync();
     }
 }
        /// <summary>
        /// Executed on each HTTP request
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            // Should not happen, but let's stay safe
            if (next is null)
            {
                return;
            }

            _logger.LogDebug($"[Transaction] Starting transaction [ID: {_session.ServerSession.Id}]");
            _session.StartTransaction();

            var executedContext = await next.Invoke();

            if (executedContext.Exception is null)
            {
                _logger.LogDebug($"[Transaction] Commiting transaction [ID: {_session.ServerSession.Id}]");
                await _session.CommitTransactionAsync();
            }
            else
            {
                // If an exception happens anywhere, we just abort the transation
                _logger.LogDebug($"[Transaction] Aborting transaction [ID: {_session.ServerSession.Id}]");
                await _session.AbortTransactionAsync();
            }
        }
Пример #8
0
        public async Task <AsyncExecutedResult <EventStreamSavedResult> > SaveAsync(EventStream stream)
        {
            if (GetAll().Any(e => e.AggregateRootId == stream.AggregateRootId && e.Version == stream.Version))
            {
                return(AsyncExecutedResult <EventStreamSavedResult> .Success(EventStreamSavedResult.DuplicatedEvent));
            }

            if (GetAll().Any(e => e.AggregateRootId == stream.AggregateRootId && e.CommandId == stream.CommandId))
            {
                return(AsyncExecutedResult <EventStreamSavedResult> .Success(EventStreamSavedResult.DuplicatedCommand));
            }

            try
            {
                await collection.InsertOneAsync(session, stream);

                await session.CommitTransactionAsync();

                return(AsyncExecutedResult <EventStreamSavedResult> .Success(EventStreamSavedResult.Success));
            }
            catch (Exception ex)
            {
                return(AsyncExecutedResult <EventStreamSavedResult> .Failed(ex, EventStreamSavedResult.Failed));
            }
        }
Пример #9
0
        public async Task AddUserAndAddAudit_Commit_RecordsExsists()
        {
            //arrange
            var user  = User.CreateSample();
            var audit = UserAudit.CreateSample(user.Id);

            IMongoDatabase db = _mongoRsResource.CreateDatabase();
            await db.CreateCollectionAsync("users");

            await db.CreateCollectionAsync("audit");

            using (IClientSessionHandle session =
                       await _mongoRsResource.Client.StartSessionAsync())
            {
                var repo = new UserRepositoryWithTransaction(db);
                session.StartTransaction();

                //act
                await repo.AddAsync(user, session);

                await repo.AddAuditAsync(audit, session);

                await session.CommitTransactionAsync();
            }


            //assert
            User createdUser = await GetUserAsync(db, user.Id);

            createdUser.Should().BeEquivalentTo(user);

            UserAudit createdAudit = await GetUserAuditAsync(db, audit.Id);

            createdAudit.Should().BeEquivalentTo(audit);
        }
Пример #10
0
        public async Task <int> SaveChanges()
        {
            try
            {
                ConfigureMongo();

                using (Session = await MongoClient.StartSessionAsync())
                {
                    Session.StartTransaction();

                    IEnumerable <Task> commandTasks = _commands.Select(c => c());

                    await Task.WhenAll(commandTasks);

                    await Session.CommitTransactionAsync();
                }

                int count = _commands.Count;

                _commands.Clear();

                return(count);
            }
            catch (Exception ex)
            {
                throw;
            }
        }
Пример #11
0
        public async Task CommitAsync(CancellationToken cancellation = default)
        {
            await Retryer.RetryAsync(async() => await _session.CommitTransactionAsync(cancellation));

            _onCompleted(true);
            _isCompleted = true;
        }
        public async Task <int> SaveChangesAsync()
        {
            CheckMongo();

            // we know the app will throw an exception if the previous statement fails to deliver
            if (clientProvider.Client !.CanSupportTransactions)
            {
                using (session = await clientProvider.Client !.StartSessionAsync())
                {
                    session.StartTransaction();

                    var commandTasks = commands.Select(c => c());

                    await Task.WhenAll(commandTasks);

                    await session.CommitTransactionAsync();
                }

                return(commands.Count);
            }

            await Task.WhenAll(commands.Select(c => c()));

            return(commands.Count);
        }
Пример #13
0
        private static async Task CommitWithRetry(IClientSessionHandle session)
        {
            var maxTries = 5;
            var retries  = 0;

            while (true)
            {
                try
                {
                    await session.CommitTransactionAsync();

                    break;
                }
                catch (MongoException exc)
                {
                    if (!(exc is MongoException mongoException &&
                          mongoException.ErrorLabels.Any(l => retriableCommitErrors.Contains(l))))
                    {
                        throw;
                    }
                    retries++;
                    if (retries < maxTries)
                    {
                        logger.Warn(exc, $"Error on commit. Labels: {string.Join(',', mongoException.ErrorLabels)}. {retries} try.");
                        continue;
                    }
                    throw new UnknownCommitResultException($"UnknownTransactionCommitResult or TransientTransactionError errors occurred after {retries} retries", exc);
                }
            }
        }
Пример #14
0
 public async Task CommitAsync()
 {
     if (_session != null)
     {
         await _session.CommitTransactionAsync();
     }
     _session = null;
 }
Пример #15
0
 internal Task CommitTransactionAsync()
 {
     if (IsInRunningState())
     {
         return(_transactionSession.CommitTransactionAsync());
     }
     return(Task.CompletedTask);
 }
Пример #16
0
        public Task Commit(CancellationToken token)
        {
            if (_clientSessionHandle != null)
            {
                return(_clientSessionHandle.CommitTransactionAsync(token));
            }

            return(Task.CompletedTask);
        }
Пример #17
0
        public async Task CommitAsync(CancellationToken cancellationToken)
        {
            await EnsureTransaction();

            if (session.IsInTransaction)
            {
                await session.CommitTransactionAsync(cancellationToken);
            }
        }
        public async Task HandleAsync(IMessage message, Func <Task> handler, string module)
        {
            if (!Enabled)
            {
                _logger.LogWarning("Inbox is disabled, incoming messages won't be processed.");
                return;
            }

            if (message.Id == Guid.Empty)
            {
                // A synchronous request
                await handler();

                return;
            }

            var collection = _database.GetCollection <InboxMessage>($"{module}-module.{_collectionName}");

            _logger.LogTrace($"Received a message with ID: '{message.Id}' to be processed.");
            if (await collection.AsQueryable().AnyAsync(x => x.Id == message.Id))
            {
                _logger.LogWarning($"Message with ID: '{message.Id}' was already processed.");
                return;
            }

            IClientSessionHandle session = null;

            if (_transactionsEnabled)
            {
                session = await _sessionFactory.CreateAsync();

                session.StartTransaction();
            }

            try
            {
                _logger.LogTrace($"Handling a message with ID: '{message.Id}'...");
                await handler();

                await collection.InsertOneAsync(new InboxMessage
                {
                    Id            = message.Id,
                    CorrelationId = message.CorrelationId,
                    Name          = message.GetType().Name.Underscore(),
                    Module        = message.GetModuleName(),
                    Timestamp     = DateTime.UtcNow.ToUnixTimeMilliseconds()
                });

                if (session is {})
                {
                    await session.CommitTransactionAsync();
                }

                _logger.LogTrace($"Handled a message with ID: '{message.Id}'.");
            }
Пример #19
0
        public async Task <UpdateResult> PatchAttribute(ICallistoUpdate <Person> update)
        {
            IClientSessionHandle session = await StartSessionAsync(update);

            UpdateResult result = await Operators.Update.One(update);

            await session.CommitTransactionAsync();

            EndSession(update);
            return(result);
        }
Пример #20
0
        public async void CommitAsync()
        {
            if (_session == null)
            {
                throw new Exception("Session has been gone somehow!");
            }

            await _session.CommitTransactionAsync();

            _session.Dispose();
        }
Пример #21
0
        public async Task <IActionResult> DeploySimulator(SimulatorDto simulatorDto)
        {
            logger.LogInformation("Deploying simulator...");
            bool simulatorExists = await this.simulatorFamilyRepository.SimulatorExists(simulatorDto.Identifier, simulatorDto.Version);

            if (simulatorExists)
            {
                return(Conflict($"Simulator(Identifier='{simulatorDto.Identifier}', Version={simulatorDto.Version}, NameLanguageKey='{simulatorDto.NameLanguageKey}' already exists."));
            }

            SimulatorFamily family = new SimulatorFamily
            {
                Identifier      = simulatorDto.SimulatorFamilyIdentifier,
                NameLanguageKey = simulatorDto.SimulatorFamilyNameLanguageKey
            };

            Simulator    simulator = this.mapper.Map <Simulator>(simulatorDto);
            List <Scene> scenes    = this.mapper.Map <IEnumerable <Scene> >(simulatorDto.Sections.SelectMany(x => x.Scenes)).ToList();

            scenes.ForEach(scene => { scene.SimulatorIdentifier = simulatorDto.Identifier; scene.SimulatorVersion = simulatorDto.Version; });

            using (IClientSessionHandle session = await this.clientWrapper.Client.StartSessionAsync(new ClientSessionOptions()))
            {
                try
                {
                    session.StartTransaction();
                    await this.sceneRepository.InsertMany(scenes, session);

                    foreach (var sectionDto in simulatorDto.Sections)
                    {
                        var section = simulator.SceneSections.FirstOrDefault(x => x.Identifier == sectionDto.Identifier);
                        foreach (var sceneOfSection in sectionDto.Scenes)
                        {
                            section.SceneIdentifiers.Add(scenes.FirstOrDefault(x => x.Identifier == sceneOfSection.Identifier).Id);
                        }
                    }

                    await this.simulatorFamilyRepository.UpsertAndAddSimulator(family, simulator, session);

                    await session.CommitTransactionAsync();
                }
                catch (Exception)
                {
                    await session.AbortTransactionAsync();

                    throw;
                }
            }


            logger.LogInformation("Deploying simulator finished");
            return(Ok());
        }
Пример #22
0
        public async Task <int> SaveChanges()
        {
            using (Session = await MongoClient.StartSessionAsync())
            {
                Session.StartTransaction();
                var commandTask = _commands.Select(c => c());
                await Task.WhenAll(commandTask);

                await Session.CommitTransactionAsync();
            }
            return(_commands.Count);
        }
            public async Task <Maybe <string> > Handle(CreateTechSpecificationByVehicleIdCommand request, CancellationToken cancellationToken)
            {
                var vehicleIdFilter = Builders <Vehicle> .Filter.Eq(v => v.Id, new ObjectId(request.VehicleId));

                var techSpecificationFilter = Builders <Vehicle> .Filter.ElemMatch(
                    v => v.VehicleTechSpecifications, request.VehicleTechSpecificationDTO.ToBsonDocument());

                var filter = Builders <Vehicle> .Filter.And(vehicleIdFilter, techSpecificationFilter);

                var vehicles = await sparePartsDbContext.Vehicles.FindAsync(filter);

                var vehicle = await vehicles.FirstOrDefaultAsync();

                if (vehicle == null)
                {
                    return(Maybe <string> .None);
                }

                var vehicleTechSpecifictaion = MapDtoToVehicleTechSpecification(request.VehicleTechSpecificationDTO);

                var vehicleTechSpecificationUpdateDefinition = Builders <Vehicle> .Update.Push(v => v.VehicleTechSpecifications, vehicleTechSpecifictaion);

                var askForSparePartsEvent = new AskForSparePartsPricesIntegrationEvent(
                    new VehicleDTO
                {
                    Id = vehicle.Id.ToString(),
                    ManufacturerName         = vehicle.ManufacturerName,
                    Model                    = vehicle.Model,
                    Generation               = vehicle.Generation,
                    EndProductionYear        = vehicle.EndProductionYear,
                    StartProductionYear      = vehicle.StartProductionYear,
                    VehicleTechSpecification = request.VehicleTechSpecificationDTO
                });

                clientSessionHandle.StartTransaction();

                try
                {
                    await sparePartsDbContext.Vehicles.UpdateOneAsync(filter, vehicleTechSpecificationUpdateDefinition);

                    await sparePartsIntegrationEventService.PublishThroughEventBusAsync(askForSparePartsEvent);

                    await clientSessionHandle.CommitTransactionAsync();
                }
                catch (Exception ex)
                {
                    logger.Information($"Can`t create vehicle tech specification : {vehicleTechSpecifictaion.ToJson()}. Exception: {ex.Message}");
                    clientSessionHandle.AbortTransaction();
                    return(Maybe <string> .None);
                }

                return(vehicleTechSpecifictaion.Id.ToString());
            }
        public async Task <OperationResult> ExecuteAsync(CancellationToken cancellationToken)
        {
            try
            {
                await _session.CommitTransactionAsync(cancellationToken).ConfigureAwait(false);

                return(OperationResult.Empty());
            }
            catch (Exception ex)
            {
                return(OperationResult.FromException(ex));
            }
        }
        public async Task <int> SaveChanges()
        {
            ConfigureMongo();

            using (session = await MongoClient.StartSessionAsync())
            {
                session.StartTransaction();
                var commnadTasks = _commands.Select(c => c());
                await Task.WhenAll(commnadTasks);

                await session.CommitTransactionAsync();
            }
            return(_commands.Count);
        }
Пример #26
0
        public async Task SaveChanges()
        {
            using (Session = await MongoClient.StartSessionAsync())
            {
                Session.StartTransaction();

                var commandTasks = commands.Select(c => c());

                await Task.WhenAll(commandTasks);

                await Session.CommitTransactionAsync();
            }
            commands.Clear();
        }
Пример #27
0
 public Task CommitTransactionAsync(CancellationToken cancellationToken = default(CancellationToken))
 {
     if (DotUseTransaction)
     {
         return(Task.FromResult(0));
     }
     return(Policy.Handle <MongoConnectionException>(i => i.InnerException.GetType() == typeof(IOException) || i.InnerException.GetType() == typeof(SocketException))
            .Or <MongoException>(i => i.HasErrorLabel("UnknownTransactionCommitResult") || i.HasErrorLabel("TransientTransactionError"))
            .Retry(3, (exception, retryCount) => { Console.WriteLine("Retry." + retryCount); })
            .ExecuteAsync(() =>
     {
         return session.CommitTransactionAsync(cancellationToken);
     }));
 }
        async Task <AsyncExecutedResult> CreateAsync(string aggregateRootTypeName, string aggregateRootId)
        {
            try
            {
                var descriptor = new EventVersionDescriptor
                {
                    AggregateRootId       = aggregateRootId,
                    AggregateRootTypeName = aggregateRootTypeName,
                    CreatedOn             = DateTime.UtcNow,
                    Id      = SnowflakeId.Default().NewId(),
                    Version = 1
                };
                await collection.InsertOneAsync(session, descriptor);

                await session.CommitTransactionAsync();

                return(AsyncExecutedResult.Success);
            }
            catch (Exception ex)
            {
                return(AsyncExecutedResult.Failed(ex));
            }
        }
        public async Task HandleAsync(string messageId, Func <Task> handler)
        {
            if (!Enabled)
            {
                _logger.LogWarning("Outbox is disabled, incoming messages won't be processed.");
                return;
            }

            if (string.IsNullOrWhiteSpace(messageId))
            {
                throw new ArgumentException("Message id to be processed cannot be empty.", nameof(messageId));
            }
            // unique check for our message - if messageId already processed we will not call our handler that means we will not involve our command or event handler again
            _logger.LogTrace($"Received a message with id: '{messageId}' to be processed.");
            if (await _inboxRepository.ExistsAsync(m => m.Id == messageId))
            {
                _logger.LogTrace($"Message with id: '{messageId}' was already processed.");
                return;
            }

            IClientSessionHandle session = null;

            if (_transactionsEnabled)
            {
                session = await _sessionFactory.CreateAsync();

                //important thing is here, using a transaction
                session.StartTransaction();
            }

            try
            {
                _logger.LogTrace($"Processing a message with id: '{messageId}'...");
                //we need to store all inbox and outbox data in same transaction and database
                await handler();                                 //outbox pattern - adding outbox event to database here with doing IMessageOutbox.SendAsync in out handler

                await _inboxRepository.AddAsync(new InboxMessage //inbox pattern
                {
                    Id          = messageId,
                    ProcessedAt = DateTime.UtcNow
                });

                if (session is {})
                {
                    await session.CommitTransactionAsync();
                }

                _logger.LogTrace($"Processed a message with id: '{messageId}'.");
            }
Пример #30
0
        public async Task <int> SaveAsync()
        {
            try
            {
                await session.CommitTransactionAsync().ConfigureAwait(false);

                return(actions);
            }
            catch
            {
                await session.AbortTransactionAsync().ConfigureAwait(false);

                return(0);
            }
        }