Четыре дня зависшего обновления конфигурации: порядок блоков в Rights.rights
Администрирование - Роли и права
В статье «Claude Code + EDT на БП КОРП: три месяца, 328 коммитов и 40 правил» эта история заняла три абзаца. Здесь она целиком: с хронологией, бисектом, тремя причинами и скриптом проверки. Контур тот же: БП КОРП 3.0 на платформе 8.5, проект в EDT, серверная тестовая база на MSSQL, код и правки файлов делает ИИ-агент (Claude Code), обновление тестовой базы запускает он же.
Симптом: не ошибка, а тишина
Загрузка конфигурации в базу начинается и не заканчивается. Процесс конфигуратора держит ядро на 100 %, память замирает на одном значении, к SQL Server нет ни одного запроса. В логе пусто, окна с ошибкой нет. Через пять часов картина та же, что через пять минут.
Хуже всего то, что поведение не зависит от способа загрузки. Агент конфигуратора, через которого EDT обновляет базу, пакетный /LoadConfigFromFiles -listFile и полная загрузка из файлов висели одинаково. Валидация EDT при этом все время была чистой: get_project_errors не показывал ничего нового.
Хронология
17 сентября агент выполнял аудит прав. Задача обычная: есть список ролей и объектов, к которым ролям нужен доступ (группы меню разделов, обработки, HTTP-сервисы обмена). Агент открыл файлы Rights.rights и дописал новые блоки <object> в конец, перед закрывающим тегом </Rights>. С точки зрения XML все корректно, с точки зрения EDT тоже. Обновление тестовой базы после этого висело 15 часов.
18-го пошли перебирать способы загрузки, считая, что сломан инкремент EDT. Три попытки, три зависания. 19-го полная выгрузка из EDT шла 3,5 часа и тоже ничем не кончилась. Потом роли откатили, и тот же пакет без них загрузился за 5 минут.
| Что делали | Результат |
|---|---|
| обновление из EDT (инкремент), 17.09 | висит 15 часов |
| агент конфигуратора EDT, 18.09 | висит |
/LoadConfigFromFiles -listFile, 18.09 |
висит |
| полная загрузка из файлов, 18.09 | висит |
| полная выгрузка из EDT, 19.09 | 3,5 часа без результата |
| тот же пакет, роли откачены | 5 минут |
роли упорядочены по UUID, с правами на Enum.* |
висит, 19 минут без записи в базу |
те же роли без Enum.* |
минуты |
вечер 19.09: 15 ролей, 74 права, по UUID, без Enum.* |
загрузилось штатно |
Как нашли: бисект по пакету
Первый вопрос при таком зависании: что именно в пакете. EDT при инкрементальном обновлении складывает список файлов во временную папку, его можно открыть и посмотреть:
%TEMP%\1cedt\ssh-*\0\xml-inc-*\load.lst
В нашем пакете были файлы Roles/*/Ext/Rights.xml. Дальше бисект: откатить файлы ролей к предыдущему коммиту, повторить обновление. Прошло за 5 минут, значит, дело в ролях. Сравнение наших ролей с типовыми дало первую причину. Когда порядок исправили, загрузка все равно висела, и следующий шаг бисекта отделил права на обработку от прав на перечисление. Так нашлась вторая.
Причина 1: блоки идут по возрастанию UUID
EDT сериализует блоки <object> роли не в порядке добавления и не по алфавиту, а по возрастанию UUID объекта. Конфигуратор при загрузке на этот порядок полагается. Блок не на своем месте загрузку не роняет, а вешает.
Откуда берется UUID:
- у объекта (справочник, документ, обработка, подсистема) из атрибута
uuidв его.mdo; - у реквизита, табличной части, команды, измерения, метода HTTP-сервиса из
.mdoвладельца, из тега этого члена; - у стандартного реквизита своего UUID в
.mdoнет, в файле роли он идет сразу за владельцем.
Блок выглядит так (фрагмент реальной роли, имя заменено):
<object>
<name>Catalog.ПРЕФ_Сады</name>
<right>
<name>Read</name>
<value>true</value>
</right>
<right>
<name>View</name>
<value>true</value>
</right>
<right>
<name>InputByString</name>
<value>true</value>
</right>
</object>
Обратите внимание, что в этом фрагменте нет ни одного намека на порядок. UUID в файле роли не пишется, его надо брать из .mdo. Поэтому ни глаз, ни XML-валидатор, ни проверки EDT нарушения не видят.
После исправления мы сплошь проверили все роли конфигурации, тогда их было 861. Порядок по UUID выдержан у всех, нарушали его только наши, дописанные в конец.
Причина 2: права на перечисления
На шаге бисекта роли уже стояли в правильном порядке, а загрузка все равно висела. В них оставались права Read и View на одно из наших перечислений. Те же роли без строк Enum.* загрузились за минуты.
Мы посмотрели, как с этим в типовой: из 861 роли конфигурации права на перечисления не дает ни одна. Перечисления читаются без прав. Поэтому правило теперь простое: Enum.* в ролях не указывать.
Грабля 3: право на HTTP-сервис ставится на метод
Эта не вешала загрузку, а тихо теряла права. В аудите 17.09 право Use было выдано на HTTP-сервис целиком:
<object>
<name>HTTPService.ПРЕФ_ОбменДанными</name>
...
EDT такой блок принимает молча, платформа при загрузке молча выбрасывает. 20 сентября после обновления типовой проект перечитали из базы, и обратный импорт эти блоки удалил: у двух наших ролей обмена «пропали» права. Во всех типовых ролях право стоит на уровне метода шаблона:
HTTPService.ПРЕФ_ОбменДанными.URLTemplate.Синхронизация.Method.POST
Правильный план прав для сервиса: по строке на каждый метод каждого шаблона.
Как править права, чтобы не повторилось
Предпочтительно через API EDT. В EDT MCP у modify_metadata есть параметр rights (fqn=Role.X rights=[{object, right}]), и он вставляет блок в правильную позицию. У него есть известные отказы: View на перечисление и вложенные подсистемы (Subsystem.A.Subsystem.B). Падает с Comparable.compareTo или «Node not found», причем часть прав к этому моменту уже применена. Права на вложенные подсистемы при этом нужны и грузятся нормально, если блок стоит по UUID.
Файлом только скриптом со вставкой по позиции. Скрипт находит UUID нового объекта и ставит блок перед первым существующим блоком с большим UUID. Если такого нет, ставит в конец, и тогда это и правда его место. Обезличенный фрагмент:
u = uuid_of(name) # UUID объекта или члена из .mdo владельца
pos = None
for m in objs: # существующие блоки <object> роли
try:
mu = uuid_of(m.group(1))
except (KeyError, FileNotFoundError):
continue # объект неизвестного вида: не ориентир
if mu > u:
pos = m.start()
break
if pos is None:
pos = t.rindex('</Rights>')
t = t[:pos] + block(name, rights) + t[pos:]
Еще три детали, на которых легко споткнуться.
Права внутри блока тоже идут в порядке платформы: Read, Insert, Update, Delete, Posting, UndoPosting, Use, View, затем интерактивные. Скрипт сортирует их по списку, а не пишет в порядке из плана. Если блок для объекта уже есть, недостающие права дописываются в него, второй блок не создается.
Файлы ролей в проекте с концами строк CRLF. Скрипт читает и пишет с newline='' и возвращает исходный перевод строки, иначе в diff уезжает весь файл.
Права перечислений скрипт пропускает сам, с сообщением в выводе. Планы прав лежат рядом в JSON, чтобы их можно было переприменить после обновления типовой.
Чего делать нельзя никогда: t.replace('</Rights>', block + '</Rights>') и любое другое «дописать в конец». Именно так агент и сделал 17 сентября. Он не нарушил ни одного правила, которое у него тогда было. После этой истории запрет записан в правила проекта отдельной строкой.
Как проверить до обновления
Проверочный скрипт check_rights_order.py лежит в репозитории claude-code-1c-edt в папке scripts. Он ищет три вещи: нарушение порядка блоков по UUID, права на Enum.* и права на HTTP-сервис без URLTemplate.
python check_rights_order.py <путь к src EDT-проекта> [Роль1 Роль2 ...]
Без списка ролей проверяются все. На нашей конфигурации 885 ролей проходят примерно за 80 секунд, на повторном прогоне с прогретым диском быстрее, результат сейчас: 0 замечаний. Ядро проверки короткое:
previous = None
for name in names:
key = project.uuid(name)
if previous and key < previous[1]:
problems.append('порядок нарушен: %s стоит после %s' % (name, previous[0]))
previous = (name, key)
Код возврата 1, если что-то найдено, поэтому скрипт можно ставить в pre-commit или в шаг CI перед сборкой пакета. При коммите разумно передавать только роли, которые есть в изменениях: проверка тогда занимает секунды.
Чеклист: обновление висит
- Есть ли в пакете
Roles/*/Ext/Rights.xml? Смотретьload.lstв%TEMP%\1cedt\ssh-*\0\xml-inc-*\. - Если есть: откатить файлы ролей к прошлому коммиту и повторить. Прошло за минуты, значит, дело в ролях.
- Прогнать
check_rights_order.pyпо измененным ролям. - Убрать права на
Enum.*, права на HTTP-сервис перенести на методы. - Вернуть права через
modify_metadataили скрипт со вставкой по UUID, снова проверить, обновить базу отдельным пакетом. - Только если роли ни при чем: инкремент EDT, блокировка базы агентом, реструктуризация на сервере. Это уже другая история.
Главное, что я вынес из этих четырех дней: у платформы есть требования к файлам, которые нигде не описаны и которые EDT не проверяет. Их видно только по тому, как устроены типовые файлы. Поэтому при любой правке XML мимо конструктора первый вопрос не «валиден ли файл», а «так ли выглядит то же самое у типовых». Если вы ловили похожие зависания на других типах файлов (формы, CommandInterface.cmi, схемы СКД), напишите в комментариях, что это было и как нашли. Хочу собрать такие случаи в один список проверок.
Вступайте в нашу телеграмм-группу Инфостарт
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.