Библиотека для кеширования зависящих друг от друга объектов
Постановка задачи всё ещё содержит изрядно элементов её решения, увы ☹.
Дано пространство объектов (изначально пустое). У каждого возможного объекта есть:
- Тип 
- Имя 
- Родословная — сеть (ограф без циклов) предков, из которых получен объект (  возможно, достаточно множества?) возможно, достаточно множества?)
- Контент 
Имена могут быть составными: например, могут быть объекты, имена которых имеют одинаковые суффиксы, и с такими группами объектов предполагается работать. Также частью имени является версия (timestamp).
 Вариант: можно заранее договориться, что у имени есть синтаксическая структура Вариант: можно заранее договориться, что у имени есть синтаксическая структура
 Вариант: имя можно оставить в покое и ввести отдельное поле категории с хештегами или чем-то подобным Вариант: имя можно оставить в покое и ввести отдельное поле категории с хештегами или чем-то подобным
 Вариант: такие категории можно оформить как часть родословной, тогда нового поля не надо (версию, наверное, нельзя выносить в родословную) Вариант: такие категории можно оформить как часть родословной, тогда нового поля не надо (версию, наверное, нельзя выносить в родословную)
Далее в тексте под термином имя предполагается вариант № 1
Объекты могут образовываться двумя путями:
- Попадать в систему извне (входные данные) 
- Генерироваться на основании других объектов (генерат) 
Среди типов объектов выделяется особый тип рецепт ( один или несколько?). Рецепт описывает граф генерации объектов (логика работы рецепта может быть любой — это контент объекта типа рецепт).
 один или несколько?). Рецепт описывает граф генерации объектов (логика работы рецепта может быть любой — это контент объекта типа рецепт). 
- На вход рецепту подаётся шаблон объектов-исходников 
- На выходе порождаются объекты-генераты, имена которых (частично) вычисляются из имён исходников
- Рецепт является предком всех генерируемых им объектов
- Использованные при генерации исходники и родословные добавляются в родословную генерата
- Необходим инструмент, описывающий, - может ли данный рецепт породить данный генерат, и если да, то какие именно исходники для этого требуются;
- каковы требования к шаблонам этих исходников (например, к версиям).
 
- Если требования к шаблонам исходников удовлетворены, рецепт считается выполненным
В шаблоне могут встречаться:
- Фильтры на имя
- Фильтры на родословную
Требуется: на основании имени ( шаблона?) объекта-целевого генерата
 шаблона?) объекта-целевого генерата 
- вычислить рекурсивно всю его предполагаемую родословную;
- определить, какой подграф родословной следует (пере)генерировать;
- сгенерировать целевой генерат, соблюдая порядок родословной.
Пример «Make»
(синтаксис условный) Собрать объект программа: prog (программа — тип, prog — имя).
Рецепты (два объекта в системе):
компоновка:: generates = программа: «имя»; файл_лог: «имя».log sources = файл_obj: «имя».o; файл_obj: lib.o content = call_gnu_ld
и
компиляция:: generates = файл_obj: «имя».o sources = файл_си: «имя».c content = call_gcc
В этом примере
- нет фильтров на родословную;
- действует умолчание для фильтров на имя: - используется наибольшая версия всех объектов,
- в требование к шаблонам автоматически добавляется условие «версия генерата не меньше версии любого из исходников»
 
Процедуры call_gnu_ld / call_gcc устанавливают версию генерата равной текущему времени:
 Вариант: Сообразно внутренней логике — это не контролируется синтаксисом Вариант: Сообразно внутренней логике — это не контролируется синтаксисом
 Вариант: Сообразно умолчаниям, которые (в иных случаях) можно поменять, например, на «сделать версию равной версии исходника» Вариант: Сообразно умолчаниям, которые (в иных случаях) можно поменять, например, на «сделать версию равной версии исходника»
Пример «HWorker»
(синтаксис условный) Собрать объект оценка: финал (user: Никифор) (user: Никифор — фильтр на родословную)
Рецепты
финальный_балл::
  gerenates = оценка: финал (user: «студент»)
  sources = оценка: за_задачу (user: «студент»; задача: «задача»);
            оценка: за_посещаемость (user: «студент»; задача: «задача»)
  content = вычислить_формулуЗдесь:
- Есть свободная переменная — «задача» (т. к. упоминается только в sources). Это значит, что годится любой объект типа задача, проходящий фильтры 
оценка_задачи:: gerenates = оценка: за_задачу (user: «студент»; задача: «задача») sources = решение: «имя_программы» (user: «студент»; задача: «задача») content = оценить_решение
Здесь «решение» — это входные данные, в которых предполагается единственный объект с произвольным именем (отсюда свободная переменная «имя_программы»)
оценка_посещаемости::
  gerenates = оценка: за_посещаемость (user: «студент»; задача: «задача»)
  sources = решение: «имя_программы» (user: «студент»; задача: «задача», version=MIN);
            дедлайн: «неважно_что» (задача: «задача»)
  content = оценить_времяЗдесь выбирается самое раннее решение с помощью явного фильтра имени; а имя дедлайна значения не имеет вообще.
TODO очистка неиспользованных генератов
Предыдущий вариант постановки.
Дано
- Задано некоторое (изначально пустое) пространство объектов разных категорий - Часть категорий — это объекты-исходники - Исходник (возможно, несколько, и возможно — различных категорий) появляется или обновляется (увеличивает версию) в результате запуска некоторой процедуры загрузкии 
 
- Оставшиеся категории — это объекты-генераты - Генерат (возможно, несколько, и возможно — различных категорий) конструируется из объектов других категорий (как исходников, так и генератов) с помощью процедуры сборки 
 
 
- У каждого объекта и каждой процедуры есть уникальный идентификатор 
- У каждого объекта и каждой процедуры есть версия («время создания»). Версия не может уменьшаться. - Появление процедуры или объекта с имеющимся идентификатором, но новой (более поздней) версией называется обновлением 
- Решение о присвоении объекту определённой версии принимает процедура
- Если идентификатор и версия совпадают, считается, что объект не изменился.
 
Известны:
- категории объектов
- спецификация (описание входа и выхода) каждой процедуры загрузки - процедура загрузки допускает спецификацию вида «загрузить все объекты таких-то категорий» 
 
- спецификация (описание входа и выхода) каждой процедуры сборки.
Понятие «актуальности» и «недоступности»
Актуальный объект или процедура всегда имеют наибольшую версию.
Дополнительно:
- Исходник актуален, если он получен с помощью актуальной процедуры загрузки, обновлять его не требуется
- Процедуру загрузки можно вызвать явно, даже если все её исходники актуальны, потому что это может привести к обновлению исходников и появлению новых 
- Генерат актуален, если он получен последовательностью актуальных сборок из актуальных исходников
Недоступным называется объект, который не может быть получен никакой актуальной процедурой.
Хранение
Хранятся как минимум все версии исходников и все доступные генераты.
Требуется
На основании заданных процедур и хранимого пространства объектов получить цель — заданный набор актуальных исходников и/или генератов.
Если по каким-то причинам объект получить нельзя, возвращается т. н. пустой объект, при этом доступен вердикт — обоснование, отчего объект не получен.
Условия
- Если хранимый объект актуален, процедуры не выполняются — выдаётся хранимый объект
- Сборка и загрузка объекта могут окончиться неуспехом — возвращается пустой объект + вердикт
- Цель может быть задана неявно: например, «загрузить все возможные исходники, а затем все генераты данной категории, которые можно собрать из имеющихся исходников» 
- Должна быть возможность удаления недоступных объектов
- Должна быть возможность удаления всех генератов
- Сборка должна иметь два режима работы с исходниками  - Используются только актуальные исходники
- Используются все версии актуальных исходников
 
Реализация
TODO Пока только идеи
- Построение графа зависимостей на основании спецификации процедур
- Запихивание под капот всего, что только можно, вплоть до того, что достаточно будет написать - … и система запомнит, что:
- bin_file — это категория генерата 
- bin_file изготавливается из c_file 
- c_file берётся последней версии (для работы со всеми версиями будет другой декоратор, например @versioned_build) - Генерат ли c_file или исходник — определится по какому-нибудь 
 
- c_compile — это процедура сборки (@build) 
- …
 
