Esempio n. 1
0
        /// <summary>
        /// SQLを実行します。
        /// </summary>
        /// <typeparam name="T">戻り値</typeparam>
        /// <param name="execute">実行内容を表すアクション</param>
        /// <param name="sql">SQL文</param>
        /// <param name="parameters">SQLパラメータ</param>
        /// <returns></returns>
        private async Task <T> ExecuteAsync <T>(Func <Task <T> > execute, string sql, DbParameter[] parameters)
        {
            var sp = new Stopwatch();

            sp.Start();

            try
            {
                await SemaphoreManager.WaitAsync(GetLockKey());

                command.CommandText = sql;
                command.Parameters.Clear();
                command.Parameters.AddRange(parameters);
                return(await execute());
            }
            catch
            {
                // エラーが発生したらコンソールに表示
                var sb = new StringBuilder();
                sb.AppendLine($"{sp.Elapsed} ******************************************************************");
                sb.AppendLine(sql.ToString());
                sb.AppendLine(parameters.Select(p => p.Value.ToString()).GetString(","));
                ServiceFactory.MessageService.Debug(sb.ToString());
                throw;
            }
            finally
            {
                if (1000 < sp.ElapsedMilliseconds)
                {
                    // 1秒超えたらコンソールに表示
                    var sb = new StringBuilder();
                    sb.AppendLine($"{sp.Elapsed} ******************************************************************");
                    sb.AppendLine(sql.ToString());
                    sb.AppendLine(parameters.Select(p => p.Value.ToString()).GetString(","));
                    ServiceFactory.MessageService.Debug(sb.ToString());
                }
                SemaphoreManager.Release(GetLockKey());
            }
        }
Esempio n. 2
0
 /// <summary>
 /// 実行完了を他スレッドに通知します。
 /// </summary>
 internal void Release()
 {
     SemaphoreManager.Release(GetLockKey());
 }
Esempio n. 3
0
        private async ValueTask HandleEvents(IReadOnlyList <ExBalanceUpdateMessage> messages)
        {
            using var activity = MyTelemetry.StartActivity("Handle ExBalanceUpdateMessage's")
                                 ?.AddTag("count-events", messages.Count);
            try
            {
                var sw = new Stopwatch();
                sw.Start();

                var list           = new List <AvgPriceUpdate>();
                var calculatedList = new List <AvgPriceUpdate>();

                if (!messages.Any())
                {
                    return;
                }

                list.AddRange(GetOperationUpdates(messages));
                if (!list.Any())
                {
                    return;
                }

                await using var ctx = DatabaseContext.Create(_dbContextOptionsBuilder);
                var groups = list.GroupBy(t => new { t.AssetId, t.WalletId });
                foreach (var group in groups)
                {
                    var semaphore = SemaphoreManager.GetOrCreate(group.Key.WalletId, group.Key.AssetId);
                    await semaphore.WaitAsync();

                    try
                    {
                        var groupedList = group.OrderBy(t => t.TimeStamp).ToList();

                        var snapshot = await _snapshotManager.GetSnapshot(group.Key.WalletId, group.Key.AssetId);

                        if (snapshot != null)
                        {
                            groupedList = groupedList.Where(t => t.TimeStamp > snapshot.LastTimestamp).ToList();
                        }

                        if (!groupedList.Any())
                        {
                            continue;
                        }

                        groupedList = AvgPriceCalculator.CalculateAvgPrice(groupedList, snapshot);
                        calculatedList.AddRange(groupedList);

                        var openTimestamp = groupedList.LastOrDefault(t => t.Balance == 0)?.TimeStamp ??
                                            snapshot?.OpenTimestamp ?? default;

                        var lastUpdate  = groupedList.Last();
                        var newSnapshot = new SnapshotEntity
                        {
                            WalletId      = lastUpdate.WalletId,
                            AssetId       = lastUpdate.AssetId,
                            Balance       = lastUpdate.Balance,
                            AvgOpenPrice  = lastUpdate.AvgOpenPrice,
                            OpenTimestamp = openTimestamp,
                            LastTimestamp = lastUpdate.TimeStamp
                        };
                        await _snapshotManager.UpsertSnapshots(new() { newSnapshot });
                    }
                    finally
                    {
                        semaphore.Release();
                    }
                }

                await ctx.UpsertAvgPriceAsync(calculatedList.Where(t => t.EventType != "Refund Blockchain Withdrawal").Select(update => new OperationHistoryEntity(update)));

                await ctx.SaveChangesAsync();

                sw.Stop();

                _logger.LogDebug(
                    "Write {countUpdates} avg price updates in database from {countEvents} ME events. Time: {elapsedText} [{elapsedMilliseconds} ms]",
                    list.Count, messages.Count, sw.Elapsed.ToString(), sw.ElapsedMilliseconds);
            }
            catch (Exception ex)
            {
                ex.FailActivity();
                messages.AddToActivityAsJsonTag("me events");
                throw;
            }
        }
Esempio n. 4
0
 /// <summary>
 /// 同期実行が必要なSQL実行を待機します。
 /// </summary>
 /// <returns></returns>
 internal async Task WaitAsync()
 {
     await SemaphoreManager.WaitAsync(GetLockKey());
 }