Пример #1
0
        /// <summary>
        /// Send Transaction with optimistic lock
        /// Send with multiple thread
        /// </summary>
        /// <param name="repoQuery"></param>
        /// <param name="rpcClass"></param>
        /// <param name="privateKey"></param>
        /// <typeparam name="TBlockchainTransaction"></typeparam>
        /// <returns></returns>
        public virtual async Task <ReturnObject> SendTransactionAsync <TBlockchainTransaction>(
            IRepositoryBlockchainTransaction <TBlockchainTransaction> repoQuery, IBlockchainRpc rpcClass,
            string privateKey = "") where TBlockchainTransaction : BlockchainTransaction
        {
            /*
             * 1. Query Transaction Withdraw pending
             * 2. Update Processing = 1, version = version + 1
             * 3. Commit Transaction
             * 4. Call RPC send transaction
             * 5. Update Transaction Status
             */
            // find transaction pending
            //            var pendingTransaction = repoQuery.FindTransactionPending();
            var pendingTransaction = repoQuery.FindRowPending();

            if (pendingTransaction?.Id == null)
            {
                //if (!CacheHelper.HaveKey("cache"))
                //{
                //	long numberOfTicks = (DateTime.Now.Ticks - startTime);

                //	TimeSpan ts = TimeSpan.FromTicks(numberOfTicks);
                //	double minutesFromTs = ts.TotalMinutes;
                //	CacheHelper.SetCacheString("cache", minutesFromTs.ToString());

                //}
                //Console.WriteLine("END TIME " + CacheHelper.GetCacheString("cache"));
                return(new ReturnObject
                {
                    Status = Status.STATUS_SUCCESS,
                    Message = "Not found Transaction"
                });
            }

            if (DbConnection.State != ConnectionState.Open)
            {
                //Console.WriteLine(DbConnection.State);
                DbConnection.Open();
            }


            //begin first transaction
            var transactionScope = DbConnection.BeginTransaction();

            try
            {
                //lock transaction for process
                var resultLock = await repoQuery.LockForProcess(pendingTransaction);

                if (resultLock.Status == Status.STATUS_ERROR)
                {
                    transactionScope.Rollback();
                    return(new ReturnObject
                    {
                        Status = Status.STATUS_SUCCESS,
                        Message = "Cannot Lock For Process"
                    });
                }

                //commit transaction
                transactionScope.Commit();
            }
            catch (Exception e)
            {
                transactionScope.Rollback();
                return(new ReturnObject
                {
                    Status = Status.STATUS_ERROR,
                    Message = e.ToString()
                });
            }

            //Update Version to Model
            pendingTransaction.Version += 1;

            //start send and update

            var transactionDbSend = DbConnection.BeginTransaction();

            try
            {
                //Call RPC Transaction
                //TODO EDIT RPC Class
                var sendTransaction = await rpcClass.SendTransactionAsync(pendingTransaction);

                pendingTransaction.Status       = sendTransaction.Status;
                pendingTransaction.IsProcessing = 0;
                //                pendingTransaction.UpdatedAt = (int) CommonHelper.GetUnixTimestamp(); // set in SafeUpdate
                pendingTransaction.Hash = sendTransaction.Data;

                //create database email when send success
                if (sendTransaction.Status == Status.STATUS_COMPLETED)
                {
                    var email = GetEmailByTransaction(pendingTransaction);
                    if (email != null)
                    {
                        //                        await CreateDataEmail("Notify send " + pendingTransaction.NetworkName(),
                        //                            email, pendingTransaction.Amount,
                        //                            Constants.TEMPLATE_EMAIL_SENT, pendingTransaction.NetworkName(),Constants.TYPE_SEND);
                        await SendMailBusiness.SendMailBusiness.CreateDataEmail("Notify send " + pendingTransaction.NetworkName(),
                                                                                email, pendingTransaction.Amount, pendingTransaction.Id,
                                                                                EmailTemplate.Sent, pendingTransaction.NetworkName(), VakapayRepositoryFactory, false);
                    }
                }

                var result = await repoQuery.SafeUpdate(pendingTransaction);

                if (result.Status == Status.STATUS_ERROR)
                {
                    transactionDbSend.Rollback();
                    return(new ReturnObject
                    {
                        Status = Status.STATUS_ERROR,
                        Message = "Cannot Save Transaction Status"
                    });
                }

                transactionDbSend.Commit();
                return(new ReturnObject
                {
                    Status = sendTransaction.Status,
                    Message = sendTransaction.Message,
                    Data = sendTransaction.Data
                });
            }
            catch (Exception e)
            {
                //release lock
                transactionDbSend.Rollback();
                var resultRelease = repoQuery.ReleaseLock(pendingTransaction);
                Console.WriteLine(JsonHelper.SerializeObject(resultRelease));
                throw e;
            }
        }
Пример #2
0
        /// <summary>
        /// Send Transaction with optimistic lock
        /// Send with multiple thread
        /// </summary>
        /// <param name="repoQuery"></param>
        /// <param name="rpcClass"></param>
        /// <param name="privateKey"></param>
        /// <typeparam name="TBlockchainTransaction"></typeparam>
        /// <returns></returns>
        public virtual async Task <ReturnObject> SendTransactionAsync <TBlockchainTransaction>(
            IRepositoryBlockchainTransaction <TBlockchainTransaction> repoQuery, IBlockchainRpc rpcClass,
            string privateKey = "") where TBlockchainTransaction : BlockchainTransaction
        {
            /*
             * 1. Query Transaction Withdraw pending
             * 2. Update Processing = 1, version = version + 1
             * 3. Commit Transaction
             * 4. Call RPC send transaction
             * 5. Update Transaction Status
             */

            var pendingTransaction = repoQuery.FindRowPending();

            if (pendingTransaction?.Id == null)
            {
                //Console.WriteLine("END TIME " + CacheHelper.GetCacheString("cache"));
                return(new ReturnObject
                {
                    Status = Status.STATUS_SUCCESS,
                    Message = "Not found Transaction"
                });
            }

            if (DbConnection.State != ConnectionState.Open)
            {
                //Console.WriteLine(DbConnection.State);
                DbConnection.Open();
            }


            //begin first transaction
            var transactionScope = DbConnection.BeginTransaction();

            try
            {
                //lock transaction for process
                var resultLock = await repoQuery.LockForProcess(pendingTransaction);

                if (resultLock.Status == Status.STATUS_ERROR)
                {
                    transactionScope.Rollback();
                    return(new ReturnObject
                    {
                        Status = Status.STATUS_SUCCESS,
                        Message = "Cannot Lock For Process"
                    });
                }

                //commit transaction
                transactionScope.Commit();
            }
            catch (Exception e)
            {
                transactionScope.Rollback();
                return(new ReturnObject
                {
                    Status = Status.STATUS_ERROR,
                    Message = e.ToString()
                });
            }

            //Update Version to Model
            pendingTransaction.Version += 1;

            //start send and update

            var transactionDbSend = DbConnection.BeginTransaction();

            try
            {
                //Call RPC Transaction
                //TODO EDIT RPC Class
                var sendTransaction = await rpcClass.SendTransactionAsync1(pendingTransaction);

                pendingTransaction.Status       = sendTransaction.Status;
                pendingTransaction.IsProcessing = 0;

                pendingTransaction.Hash = sendTransaction.Data;

                //create database email when send success
                if (sendTransaction.Status == Status.STATUS_COMPLETED)
                {
//                    var email = GetEmailByTransaction(pendingTransaction);
//                    if (email != null)
//                    {
//
//                        await SendMailBusiness.SendMailBusiness.CreateDataEmail(
//                            "Notify send " + pendingTransaction.NetworkName(),
//                            email, pendingTransaction.Amount, pendingTransaction.Id,
//                            EmailTemplate.Sent, pendingTransaction.NetworkName(), SmartContractRepositoryFactory,
//                            false);
//                    }
                }

                var result = await repoQuery.SafeUpdate(pendingTransaction);

                if (result.Status == Status.STATUS_ERROR)
                {
                    transactionDbSend.Rollback();
                    return(new ReturnObject
                    {
                        Status = Status.STATUS_ERROR,
                        Message = "Cannot Save Transaction Status"
                    });
                }

                transactionDbSend.Commit();
                return(new ReturnObject
                {
                    Status = sendTransaction.Status,
                    Message = sendTransaction.Message,
                    Data = sendTransaction.Data
                });
            }
            catch (Exception e)
            {
                //release lock
                Console.WriteLine(e.Message);
                transactionDbSend.Rollback();
                var resultRelease = repoQuery.ReleaseLock(pendingTransaction);
                Console.WriteLine(JsonHelper.SerializeObject(resultRelease));
                throw e;
            }
        }