public async IAsyncEnumerable <Envelope> Load <TInvariant>( string invariantId, string causationId, long fromPosition ) { if (!_session.IsInTransaction) { _session.StartTransaction(); } var envelopes = await _events.AsQueryable() .Where(x => x.InvariantType == typeof(TInvariant).Name) .Where(x => x.InvariantId == invariantId) .Where(x => x.Sequence > fromPosition) .OrderBy(x => x.Sequence) .ToCursorAsync(); while (envelopes.MoveNext()) { foreach (var envelope in envelopes.Current) { if (null != causationId && envelope.CausationId == causationId) { throw new IdempotencyException(causationId); } yield return(envelope); } } }
private void RemoveUserActivationCode(string userName) { try { DBSession.StartTransaction(); UserCollection.DeleteOne(user => user.UserName.Equals(user.UserName)); DBSession.CommitTransaction(); } catch (System.Exception) { DBSession.AbortTransaction(); throw; } }
/// <summary> /// Start transaction if transaction is already in progress /// </summary> private void StartTransaction() { if (!_session.IsInTransaction) { _session.StartTransaction(); } }
public async Task <ITransaction> StartTransactionAsync() { IClientSessionHandle session = await _client.StartSessionAsync(); session.StartTransaction(); return(new MongoTransaction(session)); }
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() }); }
public static async Task <TResult> ExecuteWithRetriesAsync <TResult>( IClientSessionHandle clientSession, Func <IClientSessionHandle, CancellationToken, Task <TResult> > callbackAsync, TransactionOptions transactionOptions, IClock clock, CancellationToken cancellationToken) { var startTime = clock.UtcNow; while (true) { clientSession.StartTransaction(transactionOptions); var callbackOutcome = await ExecuteCallbackAsync(clientSession, callbackAsync, startTime, clock, cancellationToken).ConfigureAwait(false); if (callbackOutcome.ShouldRetryTransaction) { continue; } if (!IsTransactionInStartingOrInProgressState(clientSession)) { return(callbackOutcome.Result); // assume callback intentionally ended the transaction } var transactionHasBeenCommitted = await CommitWithRetriesAsync(clientSession, startTime, clock, cancellationToken).ConfigureAwait(false); if (transactionHasBeenCommitted) { return(callbackOutcome.Result); } } }
private async Task RunTransactionAsync(Func <CancellationToken, Task> txnFunc, IClientSessionHandle session, IClientSessionHandle parentSession = default(IClientSessionHandle), Action <Behavior> transactionBehaviorAction = default(Action <Behavior>), CancellationToken cancellationToken = default(CancellationToken)) { try { var transactionBehavior = new Behavior(); transactionBehaviorAction?.Invoke(transactionBehavior); transactionBehavior = transactionBehaviorAction == null ? this.configurationSource.Model.TransactionBehavior : default(Behavior); if (parentSession != null) { session.AdvanceClusterTime(parentSession.ClusterTime); session.AdvanceOperationTime(parentSession.OperationTime); } session.StartTransaction(transactionBehavior.ToTransactionOptions()); #if NETFULL await txnFunc(cancellationToken).ConfigureAwait(false); await commitRetryPolicy.ExecuteAsync((cToken) => CommitAsync(session, cToken), cancellationToken).ConfigureAwait(false); #else await txnFunc(cancellationToken); await commitRetryPolicy.ExecuteAsync((cToken) => CommitAsync(session, cToken), cancellationToken); #endif } catch (Exception) { #if NETFULL await session.AbortTransactionAsync(cancellationToken).ConfigureAwait(false); #else await session.AbortTransactionAsync(cancellationToken); #endif throw; } }
/// <summary> /// Instantiates and begins a transaction. /// </summary> /// <param name="database">The name of the database to use for this transaction</param> /// <param name="options">Client session options for this transaction</param> public Transaction(string database = null, ClientSessionOptions options = null) { db = database; client = DB.GetClient(db); Session = client.StartSession(options); Session.StartTransaction(); }
public async Task AddUserAndAddAudit_Abort_UserNull() { //arrange var user = User.CreateSample(); IMongoDatabase db = _mongoRsResource.CreateDatabase(); await db.CreateCollectionAsync("users"); using (IClientSessionHandle session = await _mongoRsResource.Client.StartSessionAsync()) { var repo = new UserRepositoryWithTransaction(db); session.StartTransaction(); //act await repo.AddAsync(user, session); await session.AbortTransactionAsync(); } //assert User createdUser = await GetUserAsync(db, user.Id); createdUser.Should().BeNull(); }
public IClientSessionHandle BeginTransaction() { _session = _context.GetMongoClient().StartSession(); _session.StartTransaction(); return(_session); }
public BancoSession(IClientSessionHandle session) { this.Session = session; session.StartTransaction(); Database = session.Client.GetDatabase("Dragon"); Jogadores = Database.GetCollection <RPJogador>(nameof(RPJogador)); }
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 override void MigrateAsTransaction(IMongoDatabase database, IClientSessionHandle session) { database.CreateCollection(session, "Students"); var students = database.GetCollection <BsonDocument>("Students"); session.StartTransaction(); var document = new BsonDocument { { "student_id", 10000 }, { "scores", new BsonArray { new BsonDocument { { "type", "exam" }, { "score", 88.12334193287023 } }, new BsonDocument { { "type", "quiz" }, { "score", 74.92381029342834 } }, new BsonDocument { { "type", "homework" }, { "score", 89.97929384290324 } }, new BsonDocument { { "type", "homework" }, { "score", 82.12931030513218 } } } }, { "class_id", 480 } }; students.InsertOne(session, document); }
// updates two collections in a transaction public void UpdateEmployeeInfo(IMongoClient client, IClientSessionHandle session) { var employeesCollection = client.GetDatabase("hr").GetCollection <BsonDocument>("employees"); var eventsCollection = client.GetDatabase("reporting").GetCollection <BsonDocument>("events"); session.StartTransaction(new TransactionOptions( readConcern: ReadConcern.Snapshot, writeConcern: WriteConcern.WMajority)); try { employeesCollection.UpdateOne( session, Builders <BsonDocument> .Filter.Eq("employee", 3), Builders <BsonDocument> .Update.Set("status", "Inactive")); eventsCollection.InsertOne( session, new BsonDocument { { "employee", 3 }, { "status", new BsonDocument { { "new", "Inactive" }, { "old", "Active" } } } }); } catch (Exception exception) { Console.WriteLine($"Caught exception during transaction, aborting: {exception.Message}."); session.AbortTransaction(); throw; } CommitWithRetry(session); }
public IAccess StartTransaction() { _transaction = _store.Client.StartSession(); _transaction.StartTransaction(); Access = new MongoDbAccess(_store); return(Access); }
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); }
public MongoDBStorageTransaction(IMongoClient client, MongoDBOptions options) { _options = options; _database = client.GetDatabase(options.DatabaseName); _session = client.StartSession(); _session.StartTransaction(); }
/// <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 <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; } }
private async Task <AppendResult> InsertEvent(EventCommit commit, bool versionCheck) { IClientSessionHandle session = null; if (UseTransactions) { session = await Database.Client.StartSessionAsync(new ClientSessionOptions()); session.StartTransaction(new TransactionOptions()); } var watch = Stopwatch.StartNew(); commit.Ordinal = await identifier.Next("commit"); AppendResult result = AppendResult.NoUpdate; try { var currentVersion = await GetVersion(commit.AggregateType, commit.AggregateId); if (versionCheck && currentVersion != commit.ExpectedPreviousVersion) { logger.LogWarning("Event Version check requested and version was wrong . was: {0} expected: {1}", currentVersion, commit.ExpectedPreviousVersion); //TODO If version check throw exception! result = AppendResult.WrongVersion(commit.VersionCommit); } commit.VersionCommit = currentVersion + commit.Events.Count; await Collection.InsertOneAsync(commit); result = new AppendResult(commit.Id.ToString(), false, commit.VersionCommit, "SUCCESS"); } catch (MongoWriteException e) { if (e.Message.Contains("E11000 duplicate key")) { result = AppendResult.WrongVersion(commit.VersionCommit); } else { logger.LogError(e, "Error when saving a commit for {type} {id}", commit.AggregateType, commit.AggregateId); throw; } } finally { await CommitOrAbortTx(session, result); watch.Stop(); logger.LogDebug("{Count} events for {Type} - {Id} handled. Result: {Result}.", commit.Events.Count, commit.AggregateType, commit.AggregateId, result.CommitId); } return(result); }
public override void MigrateAsTransaction(IMongoDatabase db, IClientSessionHandle session) { var filter = Builders <BsonDocument> .Filter.Empty; var updateClientIdTemp = Builders <BsonDocument> .Update.Set(x => x["class_id_temp"], string.Empty); var students = db.GetCollection <BsonDocument>("Students"); var allStudents = students.Find(filter).ToList(); session.StartTransaction(); students.UpdateMany(session, filter, updateClientIdTemp); List <UpdateOneModel <BsonDocument> > updateAll = new List <UpdateOneModel <BsonDocument> >(); foreach (var student in allStudents) { var studentFilter = Builders <BsonDocument> .Filter.Where(x => x["_id"] == student["_id"]); var studentUpdate = Builders <BsonDocument> .Update.Set(x => x["class_id_temp"], student["class_id"].AsInt32.ToString()); updateAll.Add(new UpdateOneModel <BsonDocument>(studentFilter, studentUpdate)); } students.BulkWrite(session, updateAll); updateAll = new List <UpdateOneModel <BsonDocument> >(); foreach (var student in allStudents) { var studentFilter = Builders <BsonDocument> .Filter.Where(x => x["_id"] == student["_id"]); var studentUpdate = Builders <BsonDocument> .Update.Unset(x => x["class_id"]); updateAll.Add(new UpdateOneModel <BsonDocument>(studentFilter, studentUpdate)); } students.BulkWrite(session, updateAll); updateAll = new List <UpdateOneModel <BsonDocument> >(); foreach (var student in allStudents) { var studentFilter = Builders <BsonDocument> .Filter.Where(x => x["_id"] == student["_id"]); var studentUpdate = Builders <BsonDocument> .Update.Rename(x => x["class_id_temp"], "class_id"); updateAll.Add(new UpdateOneModel <BsonDocument>(studentFilter, studentUpdate)); } students.BulkWrite(updateAll); updateAll = new List <UpdateOneModel <BsonDocument> >(); foreach (var student in allStudents) { var studentFilter = Builders <BsonDocument> .Filter.Where(x => x["_id"] == student["_id"]); var studentUpdate = Builders <BsonDocument> .Update.Unset(x => x["class_id_temp"]); updateAll.Add(new UpdateOneModel <BsonDocument>(studentFilter, studentUpdate)); } }
public MongoDbSession(MongoDBContext Context) { this.Context = Context; Session = Context.Client.StartSession(); Database = Session.Client.GetDatabase(Context.Options.DatabaseName); Session.StartTransaction(); Ping(); }
/// <summary> /// Start Transaction /// </summary> public async Task StartTransaction() { _transactionStartDateTime = DateTime.Now; _session = await _client.StartSessionAsync(); _session.StartTransaction(); }
internal MongoUowTransaction(IClientSessionHandle session) { Transaction = session; if (!Transaction.IsInTransaction) { Transaction.StartTransaction(); } }
/// <summary> /// Start Transaction /// </summary> public async Task startTransaction() { transactionStartDateTime = DateTime.Now; session = await context.dbClient.StartSessionAsync(); session.StartTransaction(); }
public MongoDBEventStore(IServiceProvider serviceProvider, MongoDBOptions options) { client = serviceProvider.GetRequiredService <IMongoClient>(); database = client.GetDatabase(options.DatabaseName); session = client.StartSession(); session.StartTransaction(); collectionName = options.EventCollectionName; collection = database.GetCollection <EventStream>(collectionName); }
/// <summary> /// Begins a transaction. /// </summary> /// <param name="clientSessionOptions">Optional client session options.</param> /// <param name="transactionOptions">Optional transaction options.</param> /// <param name="cancellationToken">Optional cancellation token.</param> public void BeginTransaction(ClientSessionOptions clientSessionOptions = null, TransactionOptions transactionOptions = null, CancellationToken cancellationToken = default) { if (Session == null) { CreateContext(); Session = Context.Client.StartSession(clientSessionOptions, cancellationToken); Session.StartTransaction(transactionOptions); } }
/// <summary> /// Start MongoDB Transaction. This should be used when more than one MongoDB operation is to be executed in one operation /// </summary> public void StartTransaction() { if (session != null) { throw new CjExpInvalidOperationException("Transaction session already started"); } session = Client.StartSession(); session.StartTransaction(); }
public Result BookingSeat(int totalSeats, string seatIds, string jsonBooked, IMessage msg) { Result result; using (IDataAdapter da = DataManager.Build(this.DbConfig)) { IClientSessionHandle Session = null; try { string tickets = ""; string seatUnavailable = @" { _id: {'$in': <ids>}, 'bookingStatus._id': {'$ne': 'bs01'} } ".Replace("<ids>", seatIds); Session = da.Open() .CreateTransaction(); Session.StartTransaction(); da.Get(seatUnavailable, out tickets); if (tickets != "[]") { Session.AbortTransaction(); throw new System.InvalidOperationException("Unavailable ticket:" + tickets); } string bookSeats = @" { '_id': {'$in': <ids>} } ".Replace("<ids>", seatIds); long total = 0; da.EditMany(bookSeats, jsonBooked, out total); if (totalSeats != total) { Session.AbortTransaction(); throw new System.InvalidOperationException("Unavailable book all ticktes!"); } Session.CommitTransaction(); result = Result.GetResult(BusinessStatus.Completed, 210, msg, "Booking is successfully."); } catch (Exception err) { if (Session != null) { Session.AbortTransaction(); } result = Result.GetResult(BusinessStatus.Completed, 500, msg, err.Message); } } return(result); }
// Start Transaction Intro Example 1 public void UpdateEmployeeInfo(IMongoClient client, IClientSessionHandle session) { var employeesCollection = client.GetDatabase("hr").GetCollection <BsonDocument>("employees"); var eventsCollection = client.GetDatabase("reporting").GetCollection <BsonDocument>("events"); session.StartTransaction(new TransactionOptions( readConcern: ReadConcern.Snapshot, writeConcern: WriteConcern.WMajority)); try { employeesCollection.UpdateOne( session, Builders <BsonDocument> .Filter.Eq("employee", 3), Builders <BsonDocument> .Update.Set("status", "Inactive")); eventsCollection.InsertOne( session, new BsonDocument { { "employee", 3 }, { "status", new BsonDocument { { "new", "Inactive" }, { "old", "Active" } } } }); } catch (Exception exception) { Console.WriteLine($"Caught exception during transaction, aborting: {exception.Message}."); session.AbortTransaction(); throw; } while (true) { try { session.CommitTransaction(); // uses write concern set at transaction start Console.WriteLine("Transaction committed."); break; } catch (MongoException exception) { // can retry commit if (exception.HasErrorLabel("UnknownTransactionCommitResult")) { Console.WriteLine("UnknownTransactionCommitResult, retrying commit operation."); continue; } else { Console.WriteLine("Error during commit."); throw; } } } }