Что такое источник данных и как он подключается. Подключение — это заполненная админом модель источника: тип, адрес, учётные данные и scope. Дальше платформа проходит аутентификацию, прячет секреты в крипто-ядро, проверяет связку через Test Connection и начинает выборку только по объектам в scope. Дальше источник проходит свой жизненный цикл — пауза, отключение, удаление. Экран подключения живёт в Admin Panel.
connector_type
Тип источника — Jira, Confluence, GitLab, Slack и другие. Выбирает
коннектор
из реестра; его манифест и задаёт, какие поля и какого вида
учётные данные просит форма.
base URL
Адрес инстанса источника — куда коннектор шлёт
запросы.
connector_type. Подробности —
ниже.
Вход в источник раскладывается на два независимых вопроса: под кем платформа ходит в источник и чем это доказывает. Оси ортогональны и комбинируются — сервисная учётка предъявляет свой токен.
Токены и пароли сервисных учёток платформа хранит
зашифрованными — оригинал нужен обратимо (с ним коннектор
ходит в источник), поэтому это шифрование, не хэш. Ключ и алгоритм —
не самодельные: ту же связку (AES-256-GCM), что шифрует пароль SMTP
в модуле Email, даёт крипто-ядро Auth. Harvester своего хранилища
секретов не заводит — кладёт секрет в поле
sources.credential_enc и обращается к ядру за
расшифровкой в момент запроса к источнику.
Перед первой выборкой связку проверяют по шагам — чтобы при ошибке
сразу было видно, где именно она: в адресе, в кредах или в правах.
Это тот же приём проверки доступности, что у провайдеров моделей и у
Email (is_available()): не «работает / не работает», а
понятная диагностика. Шаги «креды» и «права» — это
метод check_connection()
коннектора; шаг доступности URL — общий слой, одинаковый для любого
типа, не дело коннектора.
base URL отвечает. Нет — адрес неверен
или источник недоступен по сети.
Та же проба работает на два триггера.
По требованию — админ
жмёт при подключении и правке, со всеми тремя шагами.
По
расписанию — платформа сама гоняет лёгкую версию (шаги 1–2: связь
и валидность кред) между синхронизациями, отдельно от тяжёлого
прогона. На провале выборки: проба
роняет источник в
health-состояние (error)
и поднимает уведомление тем же каналом, что и провал прогона
(видимость).
Триггеры и итог пробы видны в блоке «Проверка соединения»
карточки источника.
Scope — это режим, а не перечень, набитый руками. Как только
креды приняты
(Test Connection,
шаг 2), коннектор строит каталог объектов источника — проекты,
пространства, каналы — своим
методом list_catalog(), и админ выбирает из живого списка на экране подключения. Без
опечаток и угадывания ключей.
Scope хранится как политика — режим плюс списки, не замороженный снимок: конкретные объекты платформа сверяет с каталогом на каждой синхронизации, иначе появившиеся и удалённые пространства разошлись бы с настройкой. Оговорка про права: чтобы собрать каталог, учётке нужно листать инстанс, даже когда выборка потом сужена. Scope — часть модели источника и граница, внутри которой работает выборка.
Как коннектор
достаёт данные из источника и крутит один цикл: метод листинга отдаёт
страницу, коннектор передаёт её на вход
конвейера и
идёт за следующей по курсору. Сбой отдельного запроса — таймаут или
429 от источника — цикл не рвёт: повтор с backoff держит
reliability.
cursor
Источник отдаёт данные страницами; курсор — закладка на следующую.
Коннектор листает до конца, не пытаясь забрать всё одним
запросом.
fetch(since)
Граница «забирать только изменённое после». При полном импорте
since = epoch, при инкременте — момент прошлой
синхронизации.
Конкуренция — между источниками: их прогоны независимы и идут параллельно (per-source). Внутри одного источника листинг последователен — курсор не даёт забежать вперёд, — но обработка объектов порядко-независима.
Те же API источника отдают и пользователей с правами доступа — но это отдельная тема: как identity и ACL переезжают в платформу, держит acl-identity.
Подключённый источник живёт дольше одного прогона: его ставят на паузу, отключают, удаляют. За кнопками экрана стоят состояния и правила. аутентификация делит на «под кем» и «чем».
Resume.
Оси независимы: active-источник бывает и idle, и syncing, а error говорит про последний прогон, не про намерение админа. Бейджи на экранах Admin Panel · Источники и Admin Panel · Синхронизация — отрисовка этих осей, не отдельная истина.
Во время прогона источник под замком. Пока он в
syncing, операции над ним недоступны — правка
конфигурации, пауза, отключение, удаление и повторный запуск: один
источник — один активный прогон
(single-flight per-source). Единственный доступный рычаг — Cancel.
Cancel безопасен и потому отката не требует. Прогон
останавливается на ближайшем чекпоинте, уже обработанное лежит
консистентно —
Load идемпотентен
по source_id + source_type + source_entity_id,
полусобранного состояния не
возникает. Откат к снимку был бы вреден и не нужен: данные
самосогласуются идемпотентным upsert, Incremental и Reconciliation.
Pause при этом глушит расписание, а не замораживает живой прогон. Resume с чекпоинта лечит крах воркера в коротком окне, с бюджетом свежести; прогон, отменённый или приостановленный надолго, терминален — следующий стартует свежим, а не доедает стухшую выборку.
Pause и Disconnect обратимы и данных не трогают; судьбу собранного решает только Delete. Чистка «конфигурация + данные» — явный жёсткий снос, в отличие от мягкого архивирования записи, исчезнувшей в самом источнике (она хранится для аудита). Сущность, которую питает ещё и другой источник, при этом не пропадает — отцепляется лишь вклад удаляемого; межисточниковую склейку и её границу держит data-model → Knowledge Store.