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; } }
public async Task CommitAsync(CancellationToken cancellationToken) { if (_clientSession.IsInTransaction) { await _clientSession.CommitTransactionAsync(cancellationToken).ConfigureAwait(false); } }
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); }
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() }); }
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; } } }
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(); } }
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)); } }
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); }
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; } }
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); }
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); } } }
public async Task CommitAsync() { if (_session != null) { await _session.CommitTransactionAsync(); } _session = null; }
internal Task CommitTransactionAsync() { if (IsInRunningState()) { return(_transactionSession.CommitTransactionAsync()); } return(Task.CompletedTask); }
public Task Commit(CancellationToken token) { if (_clientSessionHandle != null) { return(_clientSessionHandle.CommitTransactionAsync(token)); } return(Task.CompletedTask); }
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}'."); }
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); }
public async void CommitAsync() { if (_session == null) { throw new Exception("Session has been gone somehow!"); } await _session.CommitTransactionAsync(); _session.Dispose(); }
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()); }
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); }
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(); }
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}'."); }
public async Task <int> SaveAsync() { try { await session.CommitTransactionAsync().ConfigureAwait(false); return(actions); } catch { await session.AbortTransactionAsync().ConfigureAwait(false); return(0); } }