public async Task SetManualSuspicionLevelsAsync(ManualSuspicionLevels manualSuspicionLevels) { var executionStrategy = new NpgsqlRetryingExecutionStrategy(db, 3); await executionStrategy.ExecuteAsync(async() => { using (var ts = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(30), TransactionScopeAsyncFlowOption.Enabled)) { db.AddOrUpdate(manualSuspicionLevels, p => p.TaskId == manualSuspicionLevels.TaskId && p.Language == manualSuspicionLevels.Language); await db.SaveChangesAsync().ConfigureAwait(false); ts.Complete(); } }); }
public async Task <WorkQueueItem> TakeNoTracking(int queueId, List <string> types, TimeSpan?timeLimit = null) { timeLimit = timeLimit ?? TimeSpan.FromMinutes(5); // skip locked пропускает заблокированные строки // for update подсказывает блокировать строки, а не страницы var typesCondition = types.Count == 0 ? "" : $"and \"{TypeColumnName}\" in ({string.Join(", ", types.Select(t => $"'{t}'"))})"; var sql = $@"with next_task as ( select ""{IdColumnName}"" from ""{nameof(db.WorkQueueItems)}"" where ""{QueueIdColumnName}"" = @queueId and (""{TakeAfterTimeColumnName}"" is NULL or ""{TakeAfterTimeColumnName}"" < @now) {typesCondition} order by ""{PriorityColumnName}"" desc, ""{IdColumnName}"" limit 1 for update skip locked ) update ""{nameof(db.WorkQueueItems)}"" set ""{TakeAfterTimeColumnName}"" = @timeLimit from next_task where ""{nameof(db.WorkQueueItems)}"".""{IdColumnName}"" = next_task.""{IdColumnName}"" returning next_task.""{IdColumnName}"", ""{QueueIdColumnName}"", ""{ItemIdColumnName}"", ""{PriorityColumnName}"", ""{TypeColumnName}"", ""{TakeAfterTimeColumnName}"";"; // Если написать *, Id возвращается дважды try { var executionStrategy = new NpgsqlRetryingExecutionStrategy(db, 3); return(await executionStrategy.ExecuteAsync(async() => { using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions { IsolationLevel = IsolationLevel.RepeatableRead }, TransactionScopeAsyncFlowOption.Enabled)) { var taken = (await db.WorkQueueItems.FromSqlRaw( sql, new NpgsqlParameter <int>("@queueId", queueId), new NpgsqlParameter <DateTime>("@now", DateTime.UtcNow), new NpgsqlParameter <DateTime>("@timeLimit", (DateTime.UtcNow + timeLimit).Value) ).AsNoTracking().ToListAsync()).FirstOrDefault(); scope.Complete(); return taken; } })); } catch (InvalidOperationException ex) { log.Warn(ex); return(null); } }
/* It's very important that SaveTaskStatisticsParametersAsync() works with disabled EF's Change Tracker */ public async Task SaveTaskStatisticsParametersAsync(TaskStatisticsParameters parameters, List <TaskStatisticsSourceData> sourceData) { var executionStrategy = new NpgsqlRetryingExecutionStrategy(db, 5); await executionStrategy.ExecuteAsync(async() => { using (var ts = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(30), TransactionScopeAsyncFlowOption.Enabled)) { await db.TaskStatisticsSourceData .Where(d => d.Submission1.TaskId == parameters.TaskId && d.Submission1.Language == parameters.Language) .DeleteAsync(); db.AddOrUpdate(parameters, p => p.TaskId == parameters.TaskId && p.Language == parameters.Language); db.TaskStatisticsSourceData.AddRange(sourceData); await db.SaveChangesAsync().ConfigureAwait(false); ts.Complete(); } }); }
public async Task TrySaveMostSimilarSubmissionAsync(MostSimilarSubmission mostSimilarSubmission) { try { var executionStrategy = new NpgsqlRetryingExecutionStrategy(db, 3); await executionStrategy.ExecuteAsync(async() => { using (var ts = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(30), TransactionScopeAsyncFlowOption.Enabled)) { db.AddOrUpdate(mostSimilarSubmission, p => p.SubmissionId == mostSimilarSubmission.SubmissionId); await db.SaveChangesAsync().ConfigureAwait(false); ts.Complete(); return(0); } }); } catch (InvalidOperationException ex) { log.Warn(ex); } }