v8-runner

Исходники и база

Одна и та же конфигурация живёт в двух видах: в базе, где с ней работают, и в файлах, которые лежат под контролем версий. Эта страница о том, какие бывают исходники, что им соответствует в базе, в каких состояниях они бывают и какие команды переводят из одного состояния в другое.

Какие бывают исходники

Единица работы раннера — набор исходников: один каталог с одним предметом. Предметов три, форматов два, и любой предмет бывает в любом формате.

предметXML платформыпроект EDTпакет
конфигурациякаталог с Configuration.xml (15)проект конфигурации (109).cf
расширениетот же формат, объявлено расширением (32)проект расширения, связан с проектом конфигурации (110).cfe
внешние обработки и отчётыкаталог с несколькими обработкамипроект внешних отчётов и обработок (110).epf, .erf

Пакет — четвёртый вид того же предмета: один файл, который платформа умеет применить к базе или разобрать обратно в файлы (30). Снимок всей базы в .dt к исходникам не относится: в нём данные.

Наборы объявлены в v8project.yaml. Тип набора раннер определяет по содержимому маркерных файлов: каталог можно назвать как угодно, тип задаёт Configuration.xml внутри. Структура объявления и примеры находятся на странице v8project.yaml.

У формата EDT две ступени. Проект правят в EDT, а с базой платформа обменивается только XML-выгрузкой (108). Экспорт проекта в XML раннер держит у себя как кеш: он не лежит под контролем версий и пересчитывается по изменившемуся.

Что лежит в базе

Информационная база держит несколько конфигураций сразу (1). Для каждого набора исходников в ней есть своя пара: то, что правят, и то, с чем работают пользователи (8).

в базечто этокто пишет
основная конфигурациято, что правят в Конфигураторе и куда загружают исходникиотправка, Конфигуратор
конфигурация базы данныхто, по чему построены таблицы и с чем работают сеансы; только для чтения (2)только применение
конфигурации поставщикаэталоны типовых решений, есть у базы на поддержке (9); их может быть несколько, каждая с именем (8)обновление поставщика
расширение и его база данныхта же пара на каждое установленное расширение (41)отправка и применение с именем расширения

Что чему соответствует

Команды ходят по этим стрелкам и ни по каким другим. Отправка и выгрузка работают с основной конфигурацией. До пользователей изменение доходит только после применения.

Шесть направлений между тремя видами одного предмета, и у каждого своя команда:

откуда → кудакоманданужна ли база
исходники → базаpushда
база → исходникиpullда
пакет → базаuploadда
база → пакетdownloadда
исходники → пакетmakeнет для конфигурации и внешних (30)
пакет → исходникиconvertнет (30)

Расширение ходит по тем же стрелкам с указанием ссылки. Отдельных команд обмена для расширений нет: те же push и pull с именем. Свойства установленного экземпляра правит extensions.

Состояния и переходы

Исходники и основная конфигурация меняются независимо: файлы правят в редакторе, конфигурацию — в Конфигураторе. Отсюда четыре состояния снаружи базы и два способа вернуться к согласию.

Состояния выгрузки и основной конфигурации: каталог исходников против основной конфигурации базы.

Петля у «разошлись» — отказ по несовпадению предка. Раннер не выбирает, чья правка важнее: он возвращает к pull, а сводит расхождение система контроля версий.

До первого обмена состояния нет: раннер ещё не знает, как относятся друг к другу каталог и база. status так и говорит. Из этого положения pull идёт всегда, push — только в пустую базу; в непустую без памяти он отказывает и предлагает pull или push --force.

Внутри базы у каждой пары свои состояния. Сохранить изменение в основную конфигурацию и применить его к базе данных — два разных события (3, 6).

Состояния основной конфигурации и конфигурации базы данных: внутри самой базы.

«Есть непринятое» — штатное состояние: ради него разведены push --no-apply и apply, чтобы реструктуризацию можно было отложить до окна обслуживания. Обратный ход — reset: основная конфигурация возвращается к конфигурации базы данных, непринятое пропадает (7). «Обновлено динамически» означает, что новые сеансы получат новую конфигурацию, а работающие останутся на прежней до перезапуска.

Кроме содержимого у ссылки есть собственное состояние: существует ли она с обеих сторон.

состояние ссылкичто это значитчем переходят
есть с обеих сторонобычная работаpush, pull
есть в проекте, нет в базерасширение ещё не заведеноpush my-ext заводит его сам (39)
есть в базе, нет в проектепоставил кто-то другой или пришло с обновлениемpull my-ext после объявления набора исходников
выключеноустановлено, но не действуетextensions set my-ext --active no
больше не нужноуводит данные, которые добавляло (42)push --delete my-ext

Все три состояния называет одна команда. Без ключа она отвечает по памяти и платформу не запускает; с --deep спрашивает поколение и состав расширений, и тогда видно, что база ушла вперёд и что в ней есть непринятое:

$ v8-runner status --deep
origin: File="/srv/ib/demo"

  main      → ЖивоеИмяКонфигурации   3 файла изменено · есть непринятое
  my-ext    → РасширениеВБазе        совпадает
  patch-01  → Patch_01               база ушла вперёд — сперва pull
  —         → Patch_007              есть в базе, нет в проекте

Три памяти о прошлом разе

Целиком выгружать и загружать всегда верно и всегда долго. По изменившемуся — быстро, и для этого нужно знать, что изменилось. Знание складывается из трёх памятей: две ведёт раннер, одну платформа.

памятьотвечает на вопроскто ведётгде лежит
хеши исходниковкакие файлы я тронулраннер считает самlocalPath, по файлу на набор
поколение базыменялась ли базаплатформа отвечает, раннер записывает (13)localPath, с именем инструмента и операции
файл версий ConfigDumpInfo.xmlчто платформе выгружать зановоплатформа (16)localPath; в каталог исходников не попадает

Хеши сравнивают каталог с прошлым разом и дают список файлов для частичной загрузки. Поколение сравнивается только на равенство: совпало — база с прошлого раза не менялась, и выгрузка отвечает «нечего делать» за секунду. Файл версий читает только платформа: по нему она решает, какие объекты перекладывать.

Все три описывают отношение между одним каталогом и одной базой. Поэтому под localPath они лежат по базе: у каждой объявленной базы своя память, и отправка в тестовую не сбивает память о рабочей. Без базы эту память не пересчитать, поэтому она лежит не в workPath: удаление workPath её не задевает. Место для этого в конфигурации уже есть: местный слой v8project.local.yaml задаёт localPath и базы по именам, из которых origin берётся без ключа, а наборы исходников и формат в нём запрещены.

.local/                       # localPath
  infobases/
    origin/                  # база по умолчанию
      generation.json        # поколение, чем получено, после какой операции
      hashes/                # хеши исходников по наборам
      dump-info/
        main/
          ConfigDumpInfo.xml # файл версий набора: у конфигурации и у каждого расширения свой
        my-ext/
          …
    test/
      …

Что делает раннер

Раннер берёт на себя ровно то, чего платформе знать неоткуда: какая база с каким каталогом связана и что в каталоге ваше.

Свой файл версий на пару

Файл версий ConfigDumpInfo.xml хранится только у раннера, в каталог исходников он не попадает. Выгрузка по изменившемуся идёт в пустой промежуточный каталог по копии раннера: платформа пишет туда изменённое и новую опись, раннер переносит в каталог всё, кроме описи, удаления — по двум описям, а новая опись становится его копией. Рядом с копией раннер помнит, какой каталог она описывает: каталог, созданный заново (новый клон), её не подтверждает. Загрузка опись не обновляет: копия отстаёт ровно на загруженное, и следующая выгрузка выгрузит это заново.

файл версийкаталогчто делает раннер
копия своей парытот жеработает по изменившемуся
копии нет или она чужаялюбойвыгрузка полная
копия своей парысоздан занововыгрузка полная

Выгрузить один файл версий, не трогая остального, платформа умеет (21), и раннер этого не делает: новый файл опишет базу такой, какая она сейчас, и заявит, что все её объекты уже лежат в каталоге. Следующая работа по изменившемуся пропустит настоящие изменения.

Проверка до выбора режима

Наличие копии и версия формата в ней читаются до запуска платформы. Копии нет — выгрузка полная, она же её создаст. Версия чужая — тоже полная. Для загрузки та же проверка работает в обратную сторону: формат новее платформы — отказ до запуска с обеими версиями (22).

Ответ описывает случившееся

Платформа может перейти на полную выгрузку сама, и узнать об этом заранее нельзя (18). Поэтому раннер не обещает быстро: ответ называет запрошенный режим и рядом — что вышло на самом деле, с причиной.

Токен хранится с именем инструмента

Рядом с поколением лежит то, чем оно получено. Сравниваются только значения от одного инструмента, чужое считается отсутствием ответа. Токен пустой базы, включая сорок нулей, сохраняется и сравнивается как любой другой токен этого инструмента.

Слить или заменить

Выгрузка из базы, где правили мимо исходников, должна встретиться с тем, что вы успели наработать. Выбор явный:

слить · pullзаменить · pull --force
что происходитвыгрузка ложится поверх; чего в базе нет, остаётся на местекаталог приводится ровно к базе, лишнее исчезает
когда нужнобазу правили мимо исходников, расхождение надо увидеть в системе контроля версийкаталог считается производным от базы и должен ей соответствовать
формат EDTслияния нет ни в одном режиме: EDT сводит изменения интерактивно (109), поэтому выгрузка либо заменяет проект, либо отказывается

Слияние раннер выполняет чужими руками, и это выбор: выгрузка ложится в рабочий каталог обычным изменением, а сводит его система контроля версий, у которой есть история, трёхстороннее слияние и разметка конфликтов. Раннер отвечает за то, чтобы расхождение стало для неё видимым и безопасным.

Подтверждение разрушения

Разрушение — то, чего нельзя вернуть: правки без фиксации в системе контроля версий, файлы вне её учёта, весь каталог, если он под контролем не находится. Изменение зафиксированного файла сюда не относится: оно видно в разнице и откатывается одной командой.

каталог чистыйтерять нечего, команда идёт
есть незафиксированноекоманда отказывается и называет, что именно потеряется
каталог не под контролем версийпотеряться может всё, отказ на тех же правах
попросили явноидёт и перечисляет уничтоженное в ответе

--dry-run показывает это заранее: перечисляет поимённо, что будет перезаписано и что удалено, ничего при этом не трогая.

Поколение до и после

Перед операцией с базой раннер спрашивает поколение и спрашивает его снова после. Если между ними базу правили, ответ называет это, а память о прошлом разе не обновляется: следующая команда снова увидит расхождение.