TrackDB

TrackDB — ClickHouse-база событий Altflow. Она хранит историю стадий сборки OCI-образа и даёт компонентам быстрый способ читать текущее состояние задачи, историю состояний и расширенный контекст образа.

Актуальная схема описана в файле основного репозитория: scripts/trackdb/createEvents.sql.

Поток данных

Поток данных TrackDB

Все компоненты пишут события только во входную таблицу imageEvents. Она использует ENGINE = Null: сама таблица не хранит строки, а служит точкой fan-out для materialized views.

Поток выглядит так:

  1. Saver вставляет первичное событие BUILD/NEW.
  2. Distributor вставляет SUSPEND или FAIL после попытки создать Helm release.
  3. Tracker вставляет RUNNING, DONE или FAIL по состоянию Kubernetes pod.
  4. Stager вставляет NEW для следующей стадии или CLEANUP после FAIL.
  5. Materialized views раскладывают поток в таблицы чтения: stateEvents, stateList_State, imagesByNames.

Таблицы и представления

ОбъектТипНазначение
imageEventsNull tableВходной append-only stream событий. Все INSERT идут сюда.
stateEvents_mvmaterialized viewПроецирует компактные поля состояния из imageEvents в stateEvents.
stateEventsMergeTreeИстория состояний задач без полного OCI metadata. Используется API, Tracker, Stager.
stateList_State_mvmaterialized viewАгрегирует последние состояния задачи по стадии.
stateList_StateAggregatingMergeTreeХранит промежуточные aggregate states для stateList.
stateListviewУдобное представление с states, eventTimes, imageIds.
imagesByNames_mvmaterialized viewПроецирует расширенные данные образа из imageEvents в imagesByNames.
imagesByNamesMergeTreeДанные образов, build context, tags, architectures, entrypoints и userGID.

В текущей схеме нет stateEvents_live: старое live view было удалено.

Стадии и состояния

eventStage:

ЗначениеОписание
BUILDСборка OCI-образа.
TESTЗапуск пользовательских test entrypoints.
SIGNПодпись образа.
PUSHПубликация образа в пользовательский registry.
CLEANUPУдаление временных ресурсов и данных задачи.

eventStageState:

ЗначениеОписание
NEWСтадия поставлена в pipeline и ожидает Distributor.
SUSPENDDistributor создал Kubernetes Job; дальнейшее состояние пишет Tracker.
RUNNINGРабочий контейнер стадии начал выполняться.
DONEСтадия успешно завершилась.
FAILСтадия завершилась ошибкой или не была создана.
REJECTЗарезервированное состояние отказа в запуске.

imageEvents

imageEvents — единственная таблица для записи событий.

Ключевые поля:

ПолеТипОписание
insertTimeDateTime64(9) DEFAULT now64(9)Время вставки события в ClickHouse. Не передаётся в INSERT.
eventTimeDateTimeВремя события со стороны компонента.
eventStageenumСтадия pipeline.
eventStageStateenumСостояние стадии.
taskIdFixedString(26)ULID задачи.
userStringПользователь задачи.
stageImageNameStringИмя образа без registry.
stageImageTagString DEFAULT ''Тег образа на стадии, если известен.
errorTypeNumUInt32 DEFAULT 0Код ошибки.
errorMessageString DEFAULT ''Текст ошибки.
registryNameStringRegistry.
buildGitURLStringGit URL исходников.
buildGitBranchStringGit branch/tag.
buildConfigPathStringПуть к пользовательскому config file.
buildDockerfilePathStringПуть к Dockerfile.
buildContextPathStringКонтекст сборки.
imageIdString DEFAULT ''ID образа, если известен.
digestString DEFAULT ''Digest образа.
repoTagsArray(String)Теги результирующего образа.
repoDigestsArray(String)Digest-адреса образа.
userUIDUInt32 DEFAULT 0UID пользователя внутри образа.
userGIDUInt32GID пользователя Altflow; используется gate-логикой SIGN.
envArray(String)Environment образа.
entrypointsArray(Array(String))Команды для стадии TEST.
labelsMap(String, String)Labels образа.
architectureArray(String)Целевые архитектуры.
osString DEFAULT ''OS образа.
sizeUInt32 DEFAULT 0Размер образа.
layersArray(String)Layers образа.
annotationsMap(String, String)OCI annotations.
manifestTypeString DEFAULT ''Тип manifest.
historyArray(Map(String, String))OCI image history.

Пример начального события от Saver:

INSERT INTO imageEvents (
  eventTime, eventStage, eventStageState, taskId, user,
  stageImageName, registryName, buildGitURL, buildGitBranch,
  buildConfigPath, buildDockerfilePath, buildContextPath,
  repoTags, userGID, entrypoints, architecture
) VALUES (
  now(), 'BUILD', 'NEW', '01JBV2S4PGNV87EGC5WKYA0RND', 'alexander',
  'project/image', 'registry.example.org', 'https://github.com/user/repo.git', 'master',
  '', './Dockerfile', '.', ['latest'], 200, [['/app/altflow-tests/run']], ['amd64']
);

stateEvents

stateEvents хранит компактную историю состояний. Таблица создаётся как:

ENGINE = MergeTree()
ORDER BY (eventTime, taskId)
PRIMARY KEY (eventTime, taskId)

Поля:

insertTime, eventTime, eventStage, eventStageState, taskId, user,
stageImageName, stageImageTag, errorTypeNum, errorMessage, registryName, imageId

API читает статусы именно из stateEvents:

SELECT eventTime, eventStage, eventStageState, user
FROM stateEvents
WHERE taskId = '01JBV2S4PGNV87EGC5WKYA0RND'
ORDER BY insertTime DESC;

Stager может читать инкрементальный поток по insertTime:

SELECT *
FROM stateEvents
WHERE insertTime > '2026-05-02 11:22:13.339000000'
ORDER BY insertTime DESC
LIMIT 50;

Tracker использует stateEvents для проверки уже записанных terminal states и подавления дублей.

stateList_State и stateList

stateList_State хранит aggregate states:

taskId
eventStage
states_state
eventTimes_state
imageIds_state

stateList раскрывает их в обычные массивы:

SELECT
  taskId,
  eventStage,
  states,
  eventTimes,
  imageIds
FROM stateList
WHERE eventStage = 'BUILD'
HAVING states[-1] = 'RUNNING';

Это представление удобно для аналитических запросов по последнему известному состоянию стадии. Оно не заменяет stateEvents для точной истории событий.

imagesByNames

imagesByNames хранит расширенные данные образа. Таблица создаётся как MergeTree:

PRIMARY KEY (name, tag, taskId)
ORDER BY (name, tag, taskId, stage)

Важные поля:

ПолеИсточникОписание
namestageImageNameИмя образа.
tagstageImageTagТег образа на стадии.
taskIdtaskIdULID задачи.
stageeventStageСтадия.
stateeventStageStateСостояние.
buildGitURLbuildGitURLGit URL.
buildGitBranchbuildGitBranchGit branch/tag.
buildDockerfilePathbuildDockerfilePathDockerfile path.
buildContextPathbuildContextPathBuild context.
repoTagsrepoTagsТеги результирующего образа.
entrypointsentrypointsTEST commands.
architecturearchitectureTarget architectures.
userGIDuserGIDИспользуется Stager для SIGN gate.

Stager читает build details из imagesByNames для события BUILD/NEW:

SELECT buildGitURL, buildDockerfilePath, buildContextPath, entrypoints,
       buildGitBranch, repoTags, architecture, userGID
FROM imagesByNames
WHERE taskId = '01JBV2S4PGNV87EGC5WKYA0RND'
  AND stage = 'BUILD'
  AND state = 'NEW'
LIMIT 1;

Пользователи

Актуальный createUsers.sql создаёт двух пользователей:

ПользовательПрава
altflowSHOW TABLES, SELECT ON TrackDB.*, INSERT ON TrackDB.imageEvents
altflow_stagerSHOW TABLES, SELECT ON TrackDB.*, INSERT ON TrackDB.imageEvents

Оба пользователя пишут только в imageEvents; прямые вставки в stateEvents, stateList_State и imagesByNames не нужны.