public async Task <string> FetchGuidFieldTaskRun(string eventKeyRun, string eventFieldRun, TimeSpan ttl) // not used { await _front.FrontServerEmulationCreateGuidField(eventKeyRun, eventFieldRun, ttl); // создаём эмулятором сервера guid поле для ключа "task:run" (и сразу же его читаем) string eventGuidFieldRun = await _cache.GetHashedAsync <string>(eventKeyRun, eventFieldRun); //получить guid поле для "task:run" return(eventGuidFieldRun); }
public void StartWorkItem(string backServerPrefixGuid, string tasksPakageGuidField, string singleTaskGuid, int assignmentTerms) { // Enqueue a background work item _taskQueue.QueueBackgroundWorkItem(async token => { // Simulate loopCount 3-second tasks to complete for each enqueued work item int delayLoop = 0; int loopRemain = assignmentTerms; //var guid = Guid.NewGuid().ToString(); _logger.LogInformation(2101, "Queued Background Task {Guid} is starting.", singleTaskGuid); while (!token.IsCancellationRequested && delayLoop < assignmentTerms) { try { await Task.Delay(TimeSpan.FromSeconds(3), token); } catch (OperationCanceledException) { // Prevent throwing if the Delay is cancelled } // здесь записать в ключ ??? и поле ??? номер текущего цикла и всего циклов, а также время и так далее (потом) // рассмотреть два варианта - ключ - сервер, поле - пакет, а в значении указать номер конкретной задачи и прочее в модели // второй вариант - ключ - пакет, поле - задача, а в значении сразу проценты (int) // ключ - сервер не имеет большого смысла, пакет и так не потеряется, а искать его будут именно по номеру пакета, поэтому пока второй вариант loopRemain--; int multiplier = 10000; int completionTaskPercentage = (delayLoop * multiplier / assignmentTerms) / multiplier; _logger.LogInformation("completionTaskPercentage {0} = delayLoop {1} / assignmentTerms {2}", completionTaskPercentage, delayLoop, assignmentTerms); // обновляем отчёт о прогрессе выполнения задания await _cache.SetHashedAsync(tasksPakageGuidField, singleTaskGuid, completionTaskPercentage); // TimeSpan.FromDays - !!! delayLoop++; _logger.LogInformation("Queued Background Task {Guid} is running. Current Loop = {DelayLoop} / Loop remaining = {3}", singleTaskGuid, delayLoop, loopRemain); } if (delayLoop == assignmentTerms) { bool isDeletedSuccess = await _cache.RemoveHashedAsync(backServerPrefixGuid, singleTaskGuid); //HashExistsAsync _logger.LogInformation("Queued Background Task {Guid} is complete on Server No. {ServerNum} / isDeleteSuccess = {3}.", singleTaskGuid, backServerPrefixGuid, isDeletedSuccess); //int checkDeletedSuccess = await _cache.GetHashedAsync<int>(serverNum, guid); // проверку и сообщение о нём можно убрать после отладки //_logger.LogInformation("Deleted field {Guid} checked on Server No. {ServerNum} / value = {3}.", guid, serverNum, checkDeletedSuccess); } else { bool isDeletedSuccess = await _cache.RemoveHashedAsync(backServerPrefixGuid, singleTaskGuid); _logger.LogInformation("Queued Background Task {Guid} was cancelled on Server No. {ServerNum} / isDeleteSuccess = {3}.", singleTaskGuid, backServerPrefixGuid, isDeletedSuccess); // записать какой-то ключ насчёт неудачи и какую-то информацию о процессе? int checkDeletedSuccess = await _cache.GetHashedAsync <int>(backServerPrefixGuid, singleTaskGuid); } }); }
private async Task <int> FrontServerFetchConditions(string eventKeyFrom, string eventFieldFrom) { //получить число пакетов задач (по этому ключу метод вызвали) int tasksCount = await _cache.GetHashedAsync <int>(eventKeyFrom, eventFieldFrom); _logger.LogInformation(30020, "TaskCount = {TasksCount} from key {Key} was fetched.", tasksCount, eventKeyFrom); if (tasksCount < 3) { tasksCount = 3; } if (tasksCount > 50) { tasksCount = 50; } return(tasksCount); }
public async Task <string> FetchGuidFieldTaskRun(string eventKeyRun, string eventFieldRun) // not used { string eventGuidFieldRun = await _cache.GetHashedAsync <string>(eventKeyRun, eventFieldRun); //получить guid поле для "task:run" return(eventGuidFieldRun); }
private async Task BackgroundProcessing(CancellationToken stoppingToken) { EventKeyNames eventKeysSet = await _data.FetchAllConstants(); //string backServerGuid = _guid ?? throw new ArgumentNullException(nameof(_guid)); //eventKeysSet.BackServerGuid = backServerGuid; //string backServerPrefixGuid = $"{eventKeysSet.PrefixBackServer}:{backServerGuid}"; //eventKeysSet.BackServerPrefixGuid = backServerPrefixGuid; //string eventKey = "task:add"; string cancelKey = "task:del"; int createdProcessesCount = 0; string backServerGuid = $"{eventKeysSet.PrefixBackServer}:{_guid}"; // backserver:(this server guid) _logger.LogInformation(1101, "INIT No: {0} - guid of This Server was fetched in QueuedHostedService.", backServerGuid); // создать ключ для подписки из констант string prefixProcessAdd = eventKeysSet.PrefixProcessAdd; // process:add string eventKeyProcessAdd = $"{prefixProcessAdd}:{_guid}"; // process:add:(this server guid) // поле-пустышка, но одинаковое с тем, что создаётся в основном методе - чтобы достать значение string eventFieldBack = eventKeysSet.EventFieldBack; _logger.LogInformation(1103, "Processes creation on This Server was subscribed on key {0} / field {1}.", eventKeyProcessAdd, eventFieldBack); // подписка на ключ добавления бэкграунд процессов(поле без разницы), в значении можно было бы ставить количество необходимых процессов // типовая блокировка множественной подписки до специального разрешения повторной подписки bool flagToBlockEventAdd = true; _keyEvents.Subscribe(eventKeyProcessAdd, async(string key, KeyEvent cmd) => { if (cmd == KeyEvent.HashSet && flagToBlockEventAdd) { // временная защёлка, чтобы подписка выполнялась один раз flagToBlockEventAdd = false; _logger.LogInformation(1111, "Received key {0} with command {1}", eventKeyProcessAdd, cmd); // название поля тоже можно создать здесь и передать в метод // ещё лучше - достать нужное значение заранее и передать только его, тогда метод будет синхронный (наверное) // не лучше // лучше int requiredProcessesCount = await _cache.GetHashedAsync <int>(eventKeyProcessAdd, eventFieldBack); if (requiredProcessesCount > 0) { createdProcessesCount = await AddProcessesToPerformingTasks(stoppingToken, requiredProcessesCount); _logger.LogInformation(1131, "AddProcessesToPerformingTasks created processes count {0}", createdProcessesCount); if (createdProcessesCount > 0) { flagToBlockEventAdd = true; } } // если вызвали с неправильным значением в ключе, подписка навсегда останется заблокированной, где-то тут ее надо разблокировать } }); string eventKeyCommand = $"Key {eventKeyProcessAdd}, HashSet command"; _logger.LogInformation(1311, "You subscribed on event - {EventKey}.", eventKeyCommand); _keyEvents.Subscribe(cancelKey, (string key, KeyEvent cmd) => { if (cmd == KeyEvent.HashSet) { _logger.LogInformation("key {0} - command {1}", key, cmd); if (createdProcessesCount > 0) { // останавливаем процесс var cts = completingTasksProcesses[createdProcessesCount - 1].CancellationTaskToken; cts.Cancel(); completingTasksProcesses.RemoveAt(createdProcessesCount - 1); createdProcessesCount--; _logger.LogInformation("One Task for Background Processes was removed, total count left {Count}", createdProcessesCount); } else { _logger.LogInformation("Task for Background Processes cannot be removed for some reason, total count is {Count}", createdProcessesCount); } } }); List <Task> processingTask = completingTasksProcesses.Select(t => t.ProcessingTask).ToList(); await Task.WhenAll(processingTask); _logger.LogInformation("All Background Processes were finished, total count was {Count}", processingTask.Count); }