示例#1
0
        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);
                }
            }
        }
示例#2
0
 private void RemoveUserActivationCode(string userName)
 {
     try
     {
         DBSession.StartTransaction();
         UserCollection.DeleteOne(user => user.UserName.Equals(user.UserName));
         DBSession.CommitTransaction();
     }
     catch (System.Exception)
     {
         DBSession.AbortTransaction();
         throw;
     }
 }
示例#3
0
 /// <summary>
 /// Start transaction if transaction is already in progress
 /// </summary>
 private void StartTransaction()
 {
     if (!_session.IsInTransaction)
     {
         _session.StartTransaction();
     }
 }
示例#4
0
        public async Task <ITransaction> StartTransactionAsync()
        {
            IClientSessionHandle session = await _client.StartSessionAsync();

            session.StartTransaction();
            return(new MongoTransaction(session));
        }
示例#5
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()
            });
        }
示例#6
0
        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);
                }
            }
        }
示例#7
0
        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();
 }
示例#9
0
        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();
        }
示例#10
0
        public IClientSessionHandle BeginTransaction()
        {
            _session = _context.GetMongoClient().StartSession();
            _session.StartTransaction();

            return(_session);
        }
示例#11
0
 public BancoSession(IClientSessionHandle session)
 {
     this.Session = session;
     session.StartTransaction();
     Database  = session.Client.GetDatabase("Dragon");
     Jogadores = Database.GetCollection <RPJogador>(nameof(RPJogador));
 }
示例#12
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);
        }
示例#13
0
        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);
        }
示例#14
0
        // 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);
        }
示例#17
0
 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();
            }
        }
示例#19
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;
            }
        }
示例#20
0
        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);
        }
示例#21
0
        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();
 }
示例#23
0
        /// <summary>
        /// Start Transaction
        /// </summary>
        public async Task StartTransaction()
        {
            _transactionStartDateTime = DateTime.Now;

            _session = await _client.StartSessionAsync();

            _session.StartTransaction();
        }
示例#24
0
 internal MongoUowTransaction(IClientSessionHandle session)
 {
     Transaction = session;
     if (!Transaction.IsInTransaction)
     {
         Transaction.StartTransaction();
     }
 }
示例#25
0
        /// <summary>
        /// Start Transaction
        /// </summary>
        public async Task startTransaction()
        {
            transactionStartDateTime = DateTime.Now;

            session = await context.dbClient.StartSessionAsync();

            session.StartTransaction();
        }
示例#26
0
 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);
     }
 }
示例#28
0
 /// <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();
 }
示例#29
0
        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);
        }
示例#30
0
        // 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;
                    }
                }
            }
        }