Beispiel #1
0
        public override void Dispose(IIocResolver iocResolver)
        {
            //foreach (var dtx in DbContexts)
            //{
            //    var CurrentTransaction = dataBaseTransactions.FirstOrDefault(t => t.dbContext == dtx);
            //    if (CurrentTransaction != null && !CurrentTransaction.isCommit && CurrentTransaction.Transaction != null)
            //    {

            //        CurrentTransaction.Transaction.Rollback();
            //        CurrentTransaction.Transaction.Dispose();
            //        dataBaseTransactions.Remove(CurrentTransaction);
            //    }
            //}
            foreach (var activeTransaction in ActiveTransactions.Values)
            {
                activeTransaction.DbContextTransaction.Dispose();

                foreach (var attendedDbContext in activeTransaction.AttendedDbContexts)
                {
                    iocResolver.Release(attendedDbContext);
                }

                iocResolver.Release(activeTransaction.StarterDbContext);
            }

            ActiveTransactions.Clear();
            base.Dispose(iocResolver);
        }
        public async Task StartDistributedTransaction(string transactionName, IEnumerable <string> transactionActors)
        {
            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            if (await ActiveTransactions.ContainsKeyAsync(transactionName))
            {
                string warnMessage = $"{baseLogString} StartDistributedUpdate => Transaction with name '{transactionName}' has already been stated.";
                Logger.LogWarning(warnMessage);
                return;
            }

            var actorsHashSet = new HashSet <string>(transactionActors);
            await ActiveTransactions.SetAsync(transactionName, actorsHashSet);

            await TransactionEnlistmentLedger.SetAsync(transactionName, new HashSet <string>());

            var actorsSb = new StringBuilder();

            foreach (var actor in actorsHashSet)
            {
                actorsSb.Append($"'{actor}', ");
            }

            Logger.LogInformation($"{baseLogString} StartDistributedUpdate => Distributed transaction '{transactionName}' SUCCESSFULLY started. Waiting for transaction actors [{actorsSb}] to enlist.");
        }
Beispiel #3
0
        private static async Task CreateActiveTransactionsDocIfNotExists(ActiveTransactions activeTransactionsDoc)
        {
            var  client         = new DocumentClient(new Uri(Endpoint), AuthKey);
            Uri  collectionLink = UriFactory.CreateDocumentCollectionUri(DbName, CollectionName);
            bool needToCreate   = false;

            try
            {
                await client.ReadDocumentAsync(UriFactory.CreateDocumentUri(DbName, CollectionName, activeTransactionsDoc.Id.ToString()));
            }
            catch (DocumentClientException de)
            {
                if (de.StatusCode != HttpStatusCode.NotFound)
                {
                    throw;
                }
                else
                {
                    needToCreate = true;
                }
            }
            if (needToCreate)
            {
                await client.CreateDocumentAsync(collectionLink, activeTransactionsDoc);
            }
        }
        public virtual void Dispose()
        {
            foreach (var activeTransaction in ActiveTransactions.Values)
            {
                //if (activeTransaction.AttendedDbContexts != null && activeTransaction.AttendedDbContexts.Count > 0)
                //{
                //    foreach (var attendedDbContext in activeTransaction.AttendedDbContexts)
                //    {
                //        attendedDbContext.Dispose();
                //    }
                //}
                if (activeTransaction.DbContextTransaction != null)
                {
                    activeTransaction.DbContextTransaction.Dispose();
                }

                if (activeTransaction.DbContext.Database.CurrentTransaction != null)
                {
                    activeTransaction.DbContext.Database.CurrentTransaction.Dispose();
                }
            }

            ActiveTransactions.Clear();

            if (CurrentTransaction != null)
            {
                CurrentTransaction.Dispose();
                CurrentTransaction = null;
            }
        }
        public ISession GetOrCreateSession <TSessionContext>(Type type = null) where TSessionContext : ISessionContext
        {
            // var context = Ioc.Create(typeof(TSessionContext));
            var             _context       = Ioc.Create <ISessionContext>(typeof(TSessionContext));
            ISessionFactory sessionFactory = _sessionFactoryProvider.GetSessionFactory(_context.Name);

            string sessionKey       = _context.Name + "#";
            string connectionString = _context.GetConnectionString();

            if (!ActiveSessions.TryGetValue(sessionKey, out ISession session))
            {
                if (Options.IsTransactional == true)
                {
                    ActiveTransactionInfo activeTransactionInfo = ActiveTransactions.GetOrDefault(connectionString);
                    if (activeTransactionInfo == null)
                    {
                        session = DbConnection != null
                            ? sessionFactory.WithOptions().Connection(DbConnection).OpenSession()
                            : sessionFactory.OpenSession();

                        ITransaction transaction = Options.IsolationLevel.HasValue
                            ? session.BeginTransaction(Options.IsolationLevel.Value.ToSystemDataIsolationLevel())
                            : session.BeginTransaction();

                        activeTransactionInfo = new ActiveTransactionInfo(transaction, session.Connection, session);
                        ActiveTransactions[connectionString] = activeTransactionInfo;
                    }
                    else
                    {
                        session = activeTransactionInfo.StarterSession;
                        activeTransactionInfo.AttendedSessions.Add(session);
                    }
                }
                else
                {
                    session = DbConnection != null
                        ? sessionFactory.OpenSessionWithConnection(DbConnection)
                        : sessionFactory.OpenSession();
                }

                ActiveSessions[sessionKey] = session;
            }

            var filters = _context.Filters().ToList();

            foreach (var filter in filters)
            {
                var name       = filter.Name();
                var parameters = filter.Parameters();
                var _filter    = session.EnableFilter(name);
                foreach (var parameter in parameters)
                {
                    _filter.SetParameter(parameter.Key, parameter.Value);
                }
            }
            return(session);
        }
Beispiel #6
0
        public override DbContext CreateDbContext <TDbContext>(string connectionString, IDbContextResolver dbContextResolver, string moduleName)
        {
            //var dtx = base.CreateDbContext<TDbContext>(connectionString, dbContextResolver, moduleName);

            //var currentIsolation = (IsolationLevel)SafeConvert.ToEnum(typeof(IsolationLevel), (object)Options.IsolationLevel, IsolationLevel.ReadUncommitted);
            //if (Options.IsTransactional == true && isBeginTransaction)
            //{
            //    dataBaseTransactions.Add(new DataBaseTransaction()
            //    {
            //        Transaction = dtx.Database.BeginTransaction(currentIsolation),
            //        dbContext = dtx,
            //        isCommit = false
            //    });
            //}
            //return dtx;
            DbContext dbContext;

            var activeTransaction = ActiveTransactions.GetOrDefault(connectionString);

            if (activeTransaction == null)
            {
                dbContext = dbContextResolver.Resolve <TDbContext>(connectionString, moduleName);

                var dbtransaction = dbContext.Database.BeginTransaction((Options.IsolationLevel ?? IsolationLevel.ReadCommitted).ToSystemDataIsolationLevel());
                activeTransaction = new ActiveTransactionInfo(dbtransaction, dbContext);
                ActiveTransactions[connectionString] = activeTransaction;
            }
            else
            {
                dbContext = dbContextResolver.Resolve <TDbContext>(
                    activeTransaction.DbContextTransaction.GetDbTransaction().Connection,
                    moduleName,
                    true
                    );

                if (dbContext.HasRelationalTransactionManager())
                {
                    dbContext.Database.UseTransaction(activeTransaction.DbContextTransaction.GetDbTransaction());
                }
                else
                {
                    dbContext.Database.BeginTransaction();
                }

                activeTransaction.AttendedDbContexts.Add(dbContext);
            }

            return(dbContext);
        }
Beispiel #7
0
        public ISession GetOrCreateSession <TSessionContext>() where TSessionContext : StoveSessionContext
        {
            ISessionFactory sessionFactory = _sessionFactoryProvider.GetSessionFactory <TSessionContext>();
            var             connectionStringResolveArgs = new ConnectionStringResolveArgs();

            connectionStringResolveArgs["SessionContextType"] = typeof(TSessionContext);
            string connectionString = ResolveConnectionString(connectionStringResolveArgs);

            string sessionKey = typeof(TSessionContext).FullName + "#" + connectionString;

            if (!ActiveSessions.TryGetValue(sessionKey, out ISession session))
            {
                if (Options.IsTransactional == true)
                {
                    ActiveTransactionInfo activeTransactionInfo = ActiveTransactions.GetOrDefault(connectionString);
                    if (activeTransactionInfo == null)
                    {
                        session = DbConnection != null
                            ? sessionFactory.WithOptions().Connection(DbConnection).OpenSession()
                            : sessionFactory.OpenSession();

                        ITransaction transaction = Options.IsolationLevel.HasValue
                            ? session.BeginTransaction(Options.IsolationLevel.Value.ToSystemDataIsolationLevel())
                            : session.BeginTransaction();

                        activeTransactionInfo = new ActiveTransactionInfo(transaction, session.Connection, session);
                        ActiveTransactions[connectionString] = activeTransactionInfo;
                    }
                    else
                    {
                        session = activeTransactionInfo.StarterSession;

                        activeTransactionInfo.AttendedSessions.Add(session);
                    }
                }
                else
                {
                    session = DbConnection != null
                        ? sessionFactory.OpenSessionWithConnection(DbConnection)
                        : sessionFactory.OpenSession();
                }

                ActiveSessions[sessionKey] = session;
            }

            return(session);
        }
Beispiel #8
0
        private static async Task ResetActiveTransactionsDocIfNotExists()
        {
            var client         = new DocumentClient(new Uri(Endpoint), AuthKey);
            Uri collectionLink = UriFactory.CreateDocumentUri(DbName, CollectionName, activeTransactionsDocId.ToString());

            ActiveTransactions activeTransactionsDoc = new ActiveTransactions
            {
                Id           = activeTransactionsDocId,
                Transactions = new List <string>()
            };

            try {
                await client.ReplaceDocumentAsync(collectionLink, activeTransactionsDoc);
            }
            catch (DocumentClientException de)
            {
                throw;
            }
        }
        private async Task InvokeRollbackOnActors(string transactionName)
        {
            var enumerableActiveTransactions = await ActiveTransactions.GetEnumerableDictionaryAsync();

            if (!enumerableActiveTransactions.ContainsKey(transactionName))
            {
                string errorMessage = $"{baseLogString} InvokeRollbackOnActors => transaction '{transactionName}' not found in '{ReliableDictionaryNames.ActiveTransactions}'.";
                Logger.LogError(errorMessage);
                throw new Exception(errorMessage);
            }

            var result = await TransactionEnlistmentLedger.TryGetValueAsync(transactionName);

            if (!result.HasValue)
            {
                string errorMessage = $"{baseLogString} InvokeRollbackOnActors => Transaction '{transactionName}' not found in '{ReliableDictionaryNames.TransactionEnlistmentLedger}'.";
                Logger.LogError(errorMessage);
                throw new Exception(errorMessage);
            }

            var transactionLedger = result.Value;

            List <Task> tasks = new List <Task>();

            foreach (var transactionActorName in transactionLedger)
            {
                if (enumerableActiveTransactions[transactionName].Contains(transactionActorName))
                {
                    var task = Task.Run(async() =>
                    {
                        ITransactionActorContract transactionActorClient = TransactionActorClient.CreateClient(transactionActorName);
                        await transactionActorClient.Rollback();
                        Logger.LogInformation($"{baseLogString} InvokeRollbackOnActors => Rollback invoked on Transaction actor: {transactionActorName}.");
                    });

                    tasks.Add(task);
                }
            }

            Task.WaitAll(tasks.ToArray());
            Logger.LogInformation($"{baseLogString} InvokeRollbackOnActors => Rollback SUCCESSFULLY invoked on all transaction actors.");
        }
        /// <summary>
        ///     Rollbacks transaction and closes database connection.
        /// </summary>
        protected override void DisposeUow()
        {
            foreach (ActiveTransactionInfo activeTransaction in ActiveTransactions.Values)
            {
                foreach (ISession session in activeTransaction.AttendedSessions)
                {
                    session.Dispose();
                }

                activeTransaction.Transaction.Dispose();
                activeTransaction.StarterSession.Dispose();
            }

            foreach (ISession activeSession in ActiveSessions.Values)
            {
                activeSession.Dispose();
            }

            ActiveSessions.Clear();
            ActiveTransactions.Clear();
        }
        public async Task <bool> Enlist(string transactionName, string transactionActorName)
        {
            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            var enumerableActiveTransactions = await ActiveTransactions.GetEnumerableDictionaryAsync();

            if (!enumerableActiveTransactions.ContainsKey(transactionName))
            {
                string errorMessage = $"{baseLogString} Enlist => transaction '{transactionName}' not found in '{ReliableDictionaryNames.ActiveTransactions}'.";
                Logger.LogError(errorMessage);
                throw new Exception(errorMessage);
            }

            var result = await TransactionEnlistmentLedger.TryGetValueAsync(transactionName);

            if (!result.HasValue)
            {
                string errorMessage = $"{baseLogString} Enlist => Transaction '{transactionName}' not found in '{ReliableDictionaryNames.TransactionEnlistmentLedger}'.";
                Logger.LogError(errorMessage);
                throw new Exception(errorMessage);
            }

            var transactionLedger = result.Value;

            if (!enumerableActiveTransactions[transactionName].Contains(transactionActorName))
            {
                string errorMessage = $"{baseLogString} InvokePreparationOnActors => Transaction '{transactionName}' not found in '{ReliableDictionaryNames.TransactionEnlistmentLedger}'.";
                Logger.LogError(errorMessage);
                return(false);
            }

            transactionLedger.Add(transactionActorName);
            await TransactionEnlistmentLedger.SetAsync(transactionName, transactionLedger);

            return(true);
        }
Beispiel #12
0
        // This console application accomplishes the following:
        //     1. Creates and inserts a document designated for keeping track of the list of currently active transaction ids.
        //     2. Generates a GUID (let's call this tId0 for the new transaction and adds this to the document created in step 1.
        //     3. Invokes the bulk import stored procedure. Upon insertion of each document, a new property TransactionId with value = tId0 is added to associate each processed document
        //        with the current active transaction.
        //     4. If the bulk import stored procedure completes successfully, remove tId0 from the document created in step 1.
        //     5. If the bulk import stored procedure fails to complete, clean up the processed documents with TransactionId = tId0. Do this by invoking the bulk delete stored procedure.
        //        Remove tId0 from teh document created in step 1.
        static void Main(string[] args)
        {
            Console.WriteLine("Using {0}, {1}, {2}", Endpoint, DbName, CollectionName);

            activeTransactionsDocId = Guid.NewGuid();
            ActiveTransactions activeTransactionsDoc = new ActiveTransactions
            {
                Id           = activeTransactionsDocId,
                Transactions = new List <string>()
            };

            // Generate the document that keeps track of active transactions if it does not already exist.
            CreateActiveTransactionsDocIfNotExists(activeTransactionsDoc).Wait();

            // Add a new guid to the list of active transactions for the current transaction.
            AddActiveTransaction().Wait();

            // Invoke bulk import sproc, adding new property TransactionId with value = current active transaction to each imported document.
            InvokeBulkImportSproc().Wait();

            // If bulk import succeeded (or if bulk delete completed successfully), remove id of the current transaction from the active transactions document.
            RemoveActiveTransaction().Wait();
        }
Beispiel #13
0
        // This console application accomplishes the following: 
        //     1. Creates and inserts a document designated for keeping track of the list of currently active transaction ids. 
        //     2. Generates a GUID (let's call this tId0 for the new transaction and adds this to the document created in step 1.
        //     3. Invokes the bulk import stored procedure. Upon insertion of each document, a new property TransactionId with value = tId0 is added to associate each processed document
        //        with the current active transaction.
        //     4. If the bulk import stored procedure completes successfully, remove tId0 from the document created in step 1.
        //     5. If the bulk import stored procedure fails to complete, clean up the processed documents with TransactionId = tId0. Do this by invoking the bulk delete stored procedure.
        //        Remove tId0 from teh document created in step 1. 
        static void Main(string[] args)
        {
            Console.WriteLine("Using {0}, {1}, {2}", Endpoint, DbName, CollectionName);

            activeTransactionsDocId = Guid.NewGuid();
            ActiveTransactions activeTransactionsDoc = new ActiveTransactions
            {
                Id = activeTransactionsDocId,
                Transactions = new List<string>()
            };

            // Generate the document that keeps track of active transactions if it does not already exist.
            CreateActiveTransactionsDocIfNotExists(activeTransactionsDoc).Wait();

            // Add a new guid to the list of active transactions for the current transaction.
            AddActiveTransaction().Wait();

            // Invoke bulk import sproc, adding new property TransactionId with value = current active transaction to each imported document.
            InvokeBulkImportSproc().Wait();

            // If bulk import succeeded (or if bulk delete completed successfully), remove id of the current transaction from the active transactions document.
            RemoveActiveTransaction().Wait();
        }
        public async Task <bool> FinishDistributedTransaction(string transactionName, bool success)
        {
            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            bool result;

            try
            {
                if (success)
                {
                    bool prepareSuccess = false;
                    int  retryCount     = 30;

                    while (--retryCount > 0)
                    {
                        try
                        {
                            prepareSuccess = await InvokePreparationOnActors(transactionName);

                            break;
                        }
                        catch (NotAllActorsEnlistedException)
                        {
                            prepareSuccess = false;
                            await Task.Delay(2000);

                            continue;
                        }
                        catch (Exception e)
                        {
                            prepareSuccess = false;

                            string errorMessage = $"{baseLogString} FinishDistributedTransaction => Exception in InvokePreparationOnActors: {e.Message}";
                            Logger.LogError(errorMessage);
                            break;
                        }
                    }

                    if (prepareSuccess)
                    {
                        await InvokeCommitOnActors(transactionName);

                        Logger.LogInformation($"{baseLogString} FinishDistributedUpdate => Distributed transaction finsihed SUCCESSFULLY.");
                    }
                    else
                    {
                        await InvokeRollbackOnActors(transactionName);

                        Logger.LogInformation($"{baseLogString} FinishDistributedUpdate => Distributed transaction finsihed UNSUCCESSFULLY.");
                    }

                    result = prepareSuccess;
                }
                else
                {
                    Logger.LogInformation($"{baseLogString} FinishDistributedUpdate => Distributed transaction finsihed UNSUCCESSFULLY.");
                    result = false;
                }
            }
            catch (Exception e)
            {
                Logger.LogError($"{baseLogString} FinishDistributedUpdate => Exception: {e.Message}");
                result = false;
            }
            finally
            {
                await ActiveTransactions.TryRemoveAsync(transactionName);

                await TransactionEnlistmentLedger.TryRemoveAsync(transactionName);
            }

            return(result);
        }
 protected virtual IReadOnlyList <ITransaction> GetAllActiveTransactions()
 {
     return(ActiveTransactions.Select(x => x.Value.Transaction).ToList());
 }
Beispiel #16
0
        private static async Task ResetActiveTransactionsDocIfNotExists()
        {
            var client = new DocumentClient(new Uri(Endpoint), AuthKey);
            Uri collectionLink = UriFactory.CreateDocumentUri(DbName, CollectionName, activeTransactionsDocId.ToString());

            ActiveTransactions activeTransactionsDoc = new ActiveTransactions
            {
                Id = activeTransactionsDocId,
                Transactions = new List<string>()
            };

            try {
                await client.ReplaceDocumentAsync(collectionLink, activeTransactionsDoc);
            }
            catch (DocumentClientException de)
            {
                throw;
            }
        }
Beispiel #17
0
        private static async Task CreateActiveTransactionsDocIfNotExists(ActiveTransactions activeTransactionsDoc)
        {
            var client = new DocumentClient(new Uri(Endpoint), AuthKey);
            Uri collectionLink = UriFactory.CreateDocumentCollectionUri(DbName, CollectionName);
            bool needToCreate = false;

            try
            {
                await client.ReadDocumentAsync(UriFactory.CreateDocumentUri(DbName, CollectionName, activeTransactionsDoc.Id.ToString()));
            }
            catch (DocumentClientException de)
            {
                if (de.StatusCode != HttpStatusCode.NotFound)
                {
                    throw;
                }
                else
                {
                    needToCreate = true;
                }
            }
            if (needToCreate)
            {
                await client.CreateDocumentAsync(collectionLink, activeTransactionsDoc);
            }
        }
        private async Task <bool> InvokePreparationOnActors(string transactionName)
        {
            bool success;

            var enumerableActiveTransactions = await ActiveTransactions.GetEnumerableDictionaryAsync();

            if (!enumerableActiveTransactions.ContainsKey(transactionName))
            {
                string errorMessage = $"{baseLogString} InvokePreparationOnActors => transaction '{transactionName}' not found in '{ReliableDictionaryNames.ActiveTransactions}'.";
                Logger.LogError(errorMessage);
                throw new Exception(errorMessage);
            }

            var result = await TransactionEnlistmentLedger.TryGetValueAsync(transactionName);

            if (!result.HasValue)
            {
                string errorMessage = $"{baseLogString} InvokePreparationOnActors => Transaction '{transactionName}' not found in '{ReliableDictionaryNames.TransactionEnlistmentLedger}'.";
                Logger.LogError(errorMessage);
                throw new Exception(errorMessage);
            }

            var transactionLedger = result.Value;

            if (!enumerableActiveTransactions[transactionName].SetEquals(transactionLedger))
            {
                string errorMessage = $"{baseLogString} InvokePreparationOnActors => not all actors have enlisted for the transaction '{transactionName}'.";
                Logger.LogError(errorMessage);
                throw new NotAllActorsEnlistedException(errorMessage);
            }

            List <Task <Tuple <string, bool> > > tasks = new List <Task <Tuple <string, bool> > >();

            foreach (var transactionActorName in transactionLedger)
            {
                var task = Task.Run(async() =>
                {
                    ITransactionActorContract transactionActorClient = TransactionActorClient.CreateClient(transactionActorName);
                    var prepareSuccess = await transactionActorClient.Prepare();
                    Logger.LogInformation($"{baseLogString} InvokePreparationOnActors => Prepare invoked on Transaction actor: {transactionActorName}, Success: {prepareSuccess}.");

                    return(new Tuple <string, bool>(transactionActorName, prepareSuccess));
                });

                tasks.Add(task);
            }

            var taskResults = await Task.WhenAll(tasks);

            success = true;

            foreach (var taskResult in taskResults)
            {
                var actorUri       = taskResult.Item1;
                var prepareSuccess = taskResult.Item2;

                success = success && prepareSuccess;

                if (success)
                {
                    Logger.LogInformation($"{baseLogString} InvokePreparationOnActors => Preparation on Transaction actor: {actorUri} finsihed SUCCESSFULLY.");
                }
                else
                {
                    Logger.LogInformation($"{baseLogString} InvokePreparationOnActors => Preparation on Transaction actor: {actorUri} finsihed UNSUCCESSFULLY.");
                    break;
                }
            }

            return(success);
        }
Beispiel #19
0
        protected internal virtual void TerminateTransactionsForValidUser(string username)
        {
            KernelTransaction currentTx = CurrentTx;

            ActiveTransactions.Where(tx => tx.subject().hasUsername(username) && !tx.isUnderlyingTransaction(currentTx)).ForEach(tx => tx.markForTermination(Org.Neo4j.Kernel.Api.Exceptions.Status_Transaction.Terminated));
        }