public async ValueTask <SubTableInfo> GetTable(long eventTimestamp) { var getTask = GetSubTables(); if (!getTask.IsCompletedSuccessfully) { await getTask; } var subTable = SubTableMillionSecondsInterval == 0 ? getTask.Result.LastOrDefault() : getTask.Result.SingleOrDefault(table => table.StartTime <= eventTimestamp && table.EndTime > eventTimestamp); if (subTable == default) { await semaphore.WaitAsync(); subTable = SubTableMillionSecondsInterval == 0 ? getTask.Result.LastOrDefault() : getTask.Result.SingleOrDefault(table => table.StartTime <= eventTimestamp && table.EndTime > eventTimestamp); try { if (subTable == default) { var lastSubTable = getTask.Result.LastOrDefault(); var startTime = lastSubTable != default ? (lastSubTable.EndTime == lastSubTable.StartTime ? DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() : lastSubTable.EndTime) : eventTimestamp; var index = lastSubTable == default ? 0 : lastSubTable.Index + 1; subTable = new SubTableInfo { TableName = EventTable, SubTable = $"{EventTable}_{index}", Index = index, StartTime = startTime, EndTime = startTime + SubTableMillionSecondsInterval }; try { await tableRepository.CreateEventTable(Connection, subTable, StateIdLength); _subTables.Add(subTable); } catch (Exception ex) { logger.LogCritical(ex, serializer.SerializeToString(subTable)); subTable = default; _subTables = (await tableRepository.GetSubTableList(Connection, EventTable)).OrderBy(table => table.EndTime).ToList(); } } } finally { semaphore.Release(); } } if (subTable == default) { subTable = await GetTable(eventTimestamp); } return(subTable); }
public async Task CreateEventTable(string conn, SubTableInfo subTable, int stateIdLength) { const string sql = @" create table {0} ( StateId varchar({1}) not null, UniqueId varchar(250) null, TypeCode varchar(100) not null, Data jsonb not null, Version int8 not null, Timestamp int8 not null, constraint {0}_id_unique unique(StateId,TypeCode,UniqueId) ) WITH (OIDS=FALSE); CREATE UNIQUE INDEX IF NOT EXISTS {0}_Version ON {0} USING btree(StateId, Version);"; const string insertSql = "INSERT into Ray_SubTable VALUES(@TableName,@SubTable,@Index,@StartTime,@EndTime)"; using (var connection = SqlFactory.CreateConnection(conn)) { await connection.OpenAsync(); using (var trans = connection.BeginTransaction()) { try { await connection.ExecuteAsync(string.Format(sql, subTable.SubTable, stateIdLength), transaction : trans); await connection.ExecuteAsync(insertSql, subTable, trans); trans.Commit(); } catch { trans.Rollback(); throw; } } } }