Skip to content

Сделать коллекцию фоновых заданий самоочищающимся LRU-кешем #1744

Description

@sfaqer

Проблема

МенеджерФоновыхЗаданий хранит все запущенные задания в ConcurrentDictionary<int, BackgroundTask> _tasks (src/OneScript.StandardLibrary/Tasks/BackgroundTasksManager.cs). Записи удаляются из коллекции только:

  • явным вызовом Очистить();
  • после успешного ОжидатьЗавершенияЗадач() (и то только если ни одно задание не упало — иначе выбрасывается исключение и коллекция не чистится);
  • при Dispose() менеджера.

В долгоживущих процессах (веб-серверы, демоны, воркеры очередей и т.п.), которые запускают фоновые задания постоянно и ждут их через ОжидатьВсе/ОжидатьЛюбое или не ждут вовсе, коллекция растёт бесконечно. Каждое ФоновоеЗадание держит ссылки на объект-цель, массив параметров, результат и ИнформацияОбОшибке — это фактически утечка памяти, а ПолучитьФоновыеЗадания() со временем начинает возвращать огромный массив.

Предложение

Сделать коллекцию фоновых заданий самоочищающейся по принципу LRU-кеша с ограниченной ёмкостью: при превышении лимита вытеснять самые старые завершённые задания (Завершено, ЗавершеноАварийно, Отменено). Выполняющиеся задания вытесняться не должны — иначе сломаются ПолучитьТекущее() и ОжидатьЗавершенияЗадач().

Мотивация

Так же устроена «большая» платформа 1С:Предприятие: кластер серверов не хранит историю фоновых заданий бесконечно, а держит только последние ~1000 запущенных ФЗ; более старые завершённые задания просто перестают возвращаться через ФоновыеЗадания.ПолучитьФоновыеЗадания(). Прикладной код на это поведение уже рассчитан, так что аналогичное ограничение в OneScript не ломает ожидания разработчиков, пришедших из 1С, и убирает неконтролируемый рост памяти.

Детали для обсуждения

  • Ёмкость по умолчанию — 1000, по аналогии с платформой. Возможно, стоит дать возможность её переопределить (параметр конструктора менеджера или настройка в oscript.cfg).
  • Задания, на которые у скрипта есть ссылки (например, лежат в массиве для ОжидатьВсе), продолжают работать как обычные объекты — вытеснение касается только внутреннего реестра менеджера.
  • Очистить() и текущая очистка в ОжидатьЗавершенияЗадач() остаются как есть.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions