private async Task ApplyUpdates(DiffObject updates)
        {
            try
            {
                var sw = new Stopwatch();
                sw.Start();
                var retries = await Context.PersistenceManager.ApplyUpdates(updates);

                sw.Stop();

                var batchInfo = new BatchSavedInfo
                {
                    SavedAt             = DateTime.UtcNow,
                    QuantaCount         = updates.Quanta.Count,
                    EffectsCount        = updates.EffectsCount,
                    ElapsedMilliseconds = sw.ElapsedMilliseconds,
                    Retries             = retries
                };
                _ = Task.Factory.StartNew(() => OnBatchSaved?.Invoke(batchInfo));
            }
            catch (Exception exc)
            {
                //we need to cancel all pending updates
                cancellationTokenSource.Cancel();
                if (Context.AppState.State != ApplicationState.Failed)
                {
                    OnSaveFailed("Error on saving updates.", exc);
                }
            }
        }
Exemplo n.º 2
0
        private void ShowDiffObject(StreamWriter stream, DiffObject parent, int level)
        {
            string indent = level == 0 ? string.Empty : "-".PadLeft(level * 4, '-');

            ConfigObject mdSource = parent.SourceValue as ConfigObject;
            ConfigObject mdTarget = parent.TargetValue as ConfigObject;

            if (mdSource != null && mdTarget != null)
            {
                stream.WriteLine(CreateObjectPresentation(parent, level, indent));
            }
            else if (mdSource != null)
            {
                stream.WriteLine(CreateObjectPresentation(parent, level, indent));
            }
            else if (mdTarget != null)
            {
                stream.WriteLine(CreateObjectPresentation(parent, level, indent));
            }
            else
            {
                stream.WriteLine(CreateDiffPresentation(parent, level, indent));
            }

            foreach (DiffObject diff in parent.DiffObjects)
            {
                ShowDiffObject(stream, diff, level + 1);
            }
        }
Exemplo n.º 3
0
        /**********************************************************************************/

        public async Task Diff(DiffObject diffObject = null)
        {
            var now = DateTime.Now;

            try
            {
                Logger.Trace("Diffiniarizing...");

                if (diffObject == null)
                {
                    diffObject = new DiffObject();
                }

                diffObject.LastSyncronizationTimestamp = _settings.LastServerTimestamp;
                diffObject.ClientTimeStamp             = now.ToTimeStamp();

                diffObject.Transactions = GetPendingTransactions();

                var uri = new Uri(ApiBaseUrl + "/v6/diff/");

                var httpClient = OAuthUtility.CreateOAuthClient(ConsumerKey, ConsumerSecret, _accessToken);
                httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                var postJson = JsonConvert.SerializeObject(diffObject);

                Logger.Trace("Request: \n\n" + postJson);

                var response = await httpClient.PostAsync(uri, new StringContent(postJson, Encoding.UTF8, "application/json"));

                var json = await response.Content.ReadAsStringAsync();

                Logger.Trace("Response: \n\n" + json);

                var diffResponse = JsonConvert.DeserializeObject <DiffRespnseObject>(json);
                _settings.LastSyncTime        = now;
                _settings.LastServerTimestamp = diffResponse.ServerTimestamp;

                await SaveChanges(diffResponse);


                if (diffResponse.Transactions != null)
                {
                    var updatetedTransactionIds = diffResponse.Transactions.Select(x => x.Id).ToArray();
                    Upserts.RemoveAll(x => updatetedTransactionIds.Contains(x.Id));
                    _db.Table <Upsert>().DeleteByKeys(updatetedTransactionIds);
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex, "Exception in (ZenmoneyClient.cs)\\[ZenmoneyClient.GetProfile] ");
                throw;
            }
        }
Exemplo n.º 4
0
        public async Task <int> ApplyUpdates(DiffObject updates)
        {
            await saveSnapshotSemaphore.WaitAsync();

            try
            {
                return(await storage.Update(updates));
            }
            finally
            {
                saveSnapshotSemaphore.Release();
            }
        }
Exemplo n.º 5
0
        public async Task <int> Update(DiffObject update)
        {
            var constellationUpdate = GetConstellationUpdate(update.StellarInfoData);
            var accountUpdates      = GetAccountUpdates(update.Accounts.Values.ToList());
            var balanceUpdates      = GetBalanceUpdates(update.Balances.Values.ToList());
            var orderUpdates        = GetOrderUpdates(update.Orders.Values.ToList());
            var quanta = GetQuantaUpdates(update.Quanta);

            using (var session = await client.StartSessionAsync())
            {
                var result = await session.WithTransactionAsync <bool>(async (s, ct) =>
                {
                    var updateTasks = new List <Task>();

                    if (constellationUpdate != null)
                    {
                        updateTasks.Add(constellationStateCollection.BulkWriteAsync(s, new [] { constellationUpdate }, cancellationToken: ct));
                    }

                    if (update.ConstellationSettings != null)
                    {
                        updateTasks.Add(settingsCollection.InsertOneAsync(s, update.ConstellationSettings, cancellationToken: ct));
                    }

                    if (accountUpdates != null)
                    {
                        updateTasks.AddRange(accountsCollection.WriteBatch(s, accountUpdates, ct));
                    }

                    if (balanceUpdates != null)
                    {
                        updateTasks.AddRange(balancesCollection.WriteBatch(s, balanceUpdates, ct));
                    }

                    if (orderUpdates != null)
                    {
                        updateTasks.AddRange(ordersCollection.WriteBatch(s, orderUpdates, ct));
                    }

                    updateTasks.AddRange(quantaCollection.WriteBatch(s, quanta, ct));

                    await Task.WhenAll(updateTasks);

                    return(true);
                },
                                                                       txOptions,
                                                                       CancellationToken.None);

                return(1);
            }
        }
Exemplo n.º 6
0
        public Task <int> Update(DiffObject update)
        {
            UpdateSettings(update.ConstellationSettings);

            UpdateStellarData(update.StellarInfoData);

            UpdateAccount(update.Accounts.Values.ToList());

            GetBalanceUpdates(update.Balances.Values.ToList());

            UpdateOrders(update.Orders.Values.ToList());

            UpdateQuanta(update.Quanta);

            return(Task.FromResult(1));
        }
Exemplo n.º 7
0
        public void OrderbookPerformanceTest(int iterations, bool useNormalDistribution = false)
        {
            var rnd = new Random();

            var testTradeResults = new Dictionary <RequestQuantum, EffectProcessorsContainer>();

            for (var i = 1; i < iterations; i++)
            {
                var price          = useNormalDistribution ? rnd.NextNormallyDistributed() + 50 : rnd.NextDouble() * 100;
                var accountWrapper = context.AccountStorage.GetAccount(account1.Account.Pubkey);
                var trade          = new RequestQuantum
                {
                    Apex            = i,
                    RequestEnvelope = new MessageEnvelope
                    {
                        Message = new OrderRequest
                        {
                            Account        = accountWrapper.Account.Id,
                            RequestId      = i,
                            Amount         = rnd.Next(1, 20),
                            Asset          = 1,
                            Price          = Math.Round(price * 10) / 10,
                            Side           = rnd.NextDouble() >= 0.5 ? OrderSide.Buy : OrderSide.Sell,
                            AccountWrapper = context.AccountStorage.GetAccount(account1.Account.Pubkey)
                        },
                        Signatures = new List <Ed25519Signature>()
                    },
                    Timestamp = DateTime.UtcNow.Ticks
                };
                var diffObject = new DiffObject();
                var conterOrderEffectsContainer = new EffectProcessorsContainer(context, trade.CreateEnvelope(), diffObject);
                testTradeResults.Add(trade, conterOrderEffectsContainer);
            }

            PerfCounter.MeasureTime(() =>
            {
                foreach (var trade in testTradeResults)
                {
                    context.Exchange.ExecuteOrder(trade.Value);
                }
            }, () =>
            {
                var market = context.Exchange.GetMarket(1);
                return($"{iterations} iterations, orderbook size: {market.Bids.Count} bids,  {market.Asks.Count} asks, {market.Bids.GetBestPrice().ToString("G3")}/{market.Asks.GetBestPrice().ToString("G3")} spread.");
            });
        }
Exemplo n.º 8
0
        public Task <int> Update(DiffObject update)
        {
            UpdateSettings(update.ConstellationSettings, update.Assets);

            UpdateStellarData(update.StellarInfoData);

            UpdateAccount(update.Accounts.Values.ToList());

            GetBalanceUpdates(update.Balances.Values.ToList());

            UpdateOrders(update.Orders.Values.ToList());

            UpdateQuanta(update.Quanta.Select(q => q.Quantum).ToList());

            UpdateEffects(update.Quanta.SelectMany(v => v.Effects.Values).ToList());

            return(Task.FromResult(1));
        }
Exemplo n.º 9
0
        private string CreateObjectPresentation(DiffObject diff, int level, string indent)
        {
            string presentation = indent + "[" + level.ToString() + "] (" + diff.Path + ") ";

            if (diff.SourceValue == null)
            {
                presentation += "NULL";
            }
            else
            {
                presentation += "\"" + diff.SourceValue.ToString() + "\"";
            }
            presentation += " : ";
            if (diff.TargetValue == null)
            {
                presentation += "NULL";
            }
            else
            {
                presentation += "\"" + diff.TargetValue?.ToString() + "\"";
            }
            return(presentation);
        }
Exemplo n.º 10
0
        private string CreateDiffPresentation(DiffObject diff, int level, string indent)
        {
            string token = " "; // None

            if (diff.DiffKind == DiffKind.Update)
            {
                token = "*";
            }
            else if (diff.DiffKind == DiffKind.Insert)
            {
                token = "+";
            }
            else if (diff.DiffKind == DiffKind.Delete)
            {
                token = "-";
            }
            string presentation = indent + "[" + level.ToString() + "] " + token + " (" + diff.Path + ") ";

            if (diff.SourceValue == null)
            {
                presentation += "NULL";
            }
            else
            {
                presentation += "\"" + diff.SourceValue.ToString() + "\"";
            }
            presentation += " : ";
            if (diff.TargetValue == null)
            {
                presentation += "NULL";
            }
            else
            {
                presentation += "\"" + diff.TargetValue?.ToString() + "\"";
            }
            return(presentation);
        }
        private void RefreshUpdatesUnlocked()
        {
            if (Current.Quanta.Count < 1)
            {
                return;
            }
            var pendingUpdates = Current;

            Current = new DiffObject();
            if (awaitedUpdates == null)
            {
                return;
            }

            awaitedUpdates.Add(pendingUpdates);
            if (Context.IsAlpha)
            {
                QuantaThrottlingManager.Current.SetBatchQueueLength(awaitedUpdates.Count);
            }
            else if (awaitedUpdates.Count >= 20 && Context.AppState.State != ApplicationState.Failed)
            {
                OnSaveFailed($"Delayed updates queue ({awaitedUpdates.Count}) is too long.");
            }
        }
Exemplo n.º 12
0
 public EffectProcessorsContainer(ExecutionContext context, MessageEnvelope quantum, DiffObject pendingDiffObject)
     : base(context)
 {
     Envelope          = quantum ?? throw new ArgumentNullException(nameof(quantum));
     PendingDiffObject = pendingDiffObject ?? throw new ArgumentNullException(nameof(pendingDiffObject));
 }
Exemplo n.º 13
0
        private void ExecuteWithOrderbook(int iterations, bool useNormalDistribution, Action <Action> executor)
        {
            var rnd = new Random();

            var market = Global.Exchange.GetMarket(1);

            var testTradeResults = new Dictionary <RequestQuantum, EffectProcessorsContainer>();

            for (var i = 1; i < iterations; i++)
            {
                var price   = useNormalDistribution ? rnd.NextNormallyDistributed() + 50 : rnd.NextDouble() * 100;
                var request = new OrderRequest
                {
                    RequestId = i,
                    Amount    = rnd.Next(1, 20),
                    Asset     = 1,
                    Price     = Math.Round(price * 27) / 13
                };
                if (rnd.NextDouble() >= 0.5)
                {
                    request.Account        = account1.Id;
                    request.AccountWrapper = account1;
                    request.Side           = OrderSide.Buy;
                }
                else
                {
                    request.Account        = account2.Id;
                    request.AccountWrapper = account2;
                    request.Side           = OrderSide.Sell;
                }

                var trade = new RequestQuantum
                {
                    Apex            = i,
                    RequestEnvelope = new MessageEnvelope
                    {
                        Message    = request,
                        Signatures = new List <Ed25519Signature>()
                    },
                    Timestamp = DateTime.UtcNow.Ticks
                };
                var diffObject = new DiffObject();
                var conterOrderEffectsContainer = new EffectProcessorsContainer(trade.CreateEnvelope(), diffObject);
                testTradeResults.Add(trade, conterOrderEffectsContainer);
            }

            var xlmStartBalance   = account1.Account.GetBalance(0).Amount + account2.Account.GetBalance(0).Amount;
            var assetStartBalance = account1.Account.GetBalance(1).Amount + account2.Account.GetBalance(1).Amount;

            executor(() =>
            {
                foreach (var trade in testTradeResults)
                {
                    Global.Exchange.ExecuteOrder(trade.Value);
                }
            });

            //cleanup orders
            foreach (var account in new[] { account1, account2 })
            {
                var activeOrders = Global.Exchange.OrderMap.GetAllAccountOrders(account);
                foreach (var order in activeOrders)
                {
                    var decodedOrderId = OrderIdConverter.Decode(order.OrderId);

                    new OrderRemovedEffectProccessor(new OrderRemovedEffect
                    {
                        OrderId        = order.OrderId,
                        Amount         = order.Amount,
                        QuoteAmount    = order.QuoteAmount,
                        Price          = order.Price,
                        Asset          = decodedOrderId.Asset,
                        AccountWrapper = account
                    }, market.GetOrderbook(decodedOrderId.Side)).CommitEffect();
                }
            }
            Assert.AreEqual(xlmStartBalance, account1.Account.GetBalance(0).Amount + account2.Account.GetBalance(0).Amount);
            Assert.AreEqual(assetStartBalance, account1.Account.GetBalance(1).Amount + account2.Account.GetBalance(1).Amount);
            Assert.AreEqual(0, account1.Account.GetBalance(0).Liabilities);
            Assert.AreEqual(0, account1.Account.GetBalance(1).Liabilities);
            Assert.AreEqual(0, account2.Account.GetBalance(0).Liabilities);
            Assert.AreEqual(0, account2.Account.GetBalance(1).Liabilities);
        }
Exemplo n.º 14
0
        public async Task <int> Update(DiffObject update)
        {
            var stellarUpdates = GetStellarDataUpdate(update.StellarInfoData);
            var accountUpdates = GetAccountUpdates(update.Accounts.Values.ToList());
            var balanceUpdates = GetBalanceUpdates(update.Balances.Values.ToList());
            var orderUpdates   = GetOrderUpdates(update.Orders.Values.ToList());
            var quanta         = update.Quanta.Select(a => a.Quantum);
            var effects        = update.Quanta.SelectMany(a => a.Effects.Values);

            var retries         = 1;
            var maxTries        = 5;
            var isCommitInvoked = false;

            while (true)
            {
                using (var session = await client.StartSessionAsync())
                {
                    try
                    {
                        session.StartTransaction();
                        try
                        {
                            var updateTasks = new List <Task>();

                            if (stellarUpdates != null)
                            {
                                updateTasks.Add(constellationStateCollection.BulkWriteAsync(session, new WriteModel <ConstellationState>[] { stellarUpdates }));
                            }

                            if (update.ConstellationSettings != null)
                            {
                                updateTasks.Add(settingsCollection.InsertOneAsync(session, update.ConstellationSettings));
                            }

                            if (update.Assets != null && update.Assets.Count > 0)
                            {
                                updateTasks.Add(assetsCollection.InsertManyAsync(session, update.Assets));
                            }

                            if (accountUpdates != null)
                            {
                                updateTasks.Add(accountsCollection.BulkWriteAsync(session, accountUpdates));
                            }

                            if (balanceUpdates != null)
                            {
                                updateTasks.Add(balancesCollection.BulkWriteAsync(session, balanceUpdates));
                            }

                            if (orderUpdates != null)
                            {
                                updateTasks.Add(ordersCollection.BulkWriteAsync(session, orderUpdates));
                            }

                            SaveQuanta(ref updateTasks, quanta, session);

                            SaveEffects(ref updateTasks, effects, session);

                            await Task.WhenAll(updateTasks);

                            isCommitInvoked = true;
                            await CommitWithRetry(session);

                            break;
                        }
                        catch
                        {
                            if (!isCommitInvoked)
                            {
                                try
                                {
                                    await session.AbortTransactionAsync();
                                }
                                catch { } //MongoDB best practice ;)
                            }
                            throw;
                        }
                    }
                    catch (Exception exc)
                    {
                        if (retries <= maxTries)
                        {
                            logger.Debug(exc, $"Error during update. {retries} try.");
                            retries++;
                            continue;
                        }
                        new Exception($"Unable to commit transaction after {retries} retries", exc);
                    }
                }
            }
            return(retries);
        }
Exemplo n.º 15
0
 public EffectProcessorsContainer(MessageEnvelope quantum, DiffObject pendingDiffObject)
 {
     Envelope          = quantum ?? throw new ArgumentNullException(nameof(quantum));
     PendingDiffObject = pendingDiffObject ?? throw new ArgumentNullException(nameof(pendingDiffObject));
     QuantumModel      = new QuantumItem(Apex);
 }