Пример #1
0
        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);
        }
Пример #4
0
        public async Task <string> FetchGuidFieldTaskRun(string eventKeyRun, string eventFieldRun)       // not used
        {
            string eventGuidFieldRun = await _cache.GetHashedAsync <string>(eventKeyRun, eventFieldRun); //получить guid поле для "task:run"

            return(eventGuidFieldRun);
        }
Пример #5
0
        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);
        }