Перейти к основному содержимому
Версия: 7.0

Правила: сессии изменений (NEWSESSION, APPLY)

Правила сессий изменений (NEWSESSION, NESTEDSESSION, APPLY)

  1. Прежде чем вводить NEWSESSION, ассистент ОБЯЗАН решить, какое поведение сессии требуется. Ни один из вариантов ниже не работает внутри транзакции APPLY — в обработчике глобального события или в применяемом действии, — где сессия не создается вовсе: внутреннее действие откладывается и выполняется в текущей сессии, в той же транзакции. Ассистент НЕ ДОЛЖЕН рассчитывать там на независимую фиксацию.

    • изолированная независимая единица -> NEWSESSION
    • изолированная единица, которая также должна видеть отдельные локальные свойства верхней сессии -> NEWSESSION NESTED (...)
    • изолированная единица, которая должна видеть все локальные свойства верхней сессии -> NEWSESSION NESTED LOCAL
    • дочерний диалог или редактор, который должен работать с несохранёнными объектами верхней сессии и возвращать свои изменения в эту верхнюю сессию -> NESTEDSESSION
  2. Для действий, добавленных на формы, есть два основных паттерна:

    • паттерн readonly-формы: форма фактически только для просмотра, поэтому добавленные на неё действия СЛЕДУЕТ по умолчанию выполнять в новой сессии
    • паттерн редактируемой формы: форма имеет редактируемые свойства, поэтому любое добавленное на неё действие, использующее NEWSESSION, ДОЛЖНО либо: APPLY; IF canceled() THEN RETURN; перед NEWSESSION, либо быть полностью независимым от несохранённых изменений в этой форме
  3. Простой NEWSESSION — вариант по умолчанию для изолированной работы, которая не должна случайно применить ожидающие изменения формы вызывающей стороны.

    Типичные паттерны в исходниках:

    • readonly-списочные формы с PROPERTIES(...) NEWSESSION NEW, EDIT, DELETE
    • смена статусов или создание зависимых документов после предшествующего APPLY
    • внешние или интеграционные действия, изолирующие HTTP-вызовы и сохраняющие собственные результаты
    • небольшие немедленные обновления UI с NEWSESSION { APPLY { ... } }
  4. Если внутренняя логика зависит от локального состояния верхней сессии, такого как выделения, отметки или буферы импорта, ассистент ОБЯЗАН явно перенести это состояние через NESTED (...) или NESTED LOCAL в операторе либо объявить само свойство DATA LOCAL NESTED — такое переносится без перечисления в операторе. Под NEWSQL не работает ни то, ни другое: на собственном соединении не переносится ничего, поэтому ассистент НЕ ДОЛЖЕН сочетать NEWSQL с зависимостью от локального состояния верхней сессии.

  5. Успешный APPLY очищает сессию, а с ней по умолчанию и все LOCAL-свойства в ней: после возврата из такого APPLY обычный LOCAL снова пуст. APPLY, который не прошел или был отменен, оставляет сессию как была, вместе с локальными, — поэтому ассистент НЕ ДОЛЖЕН читать LOCAL после APPLY, чтобы отличить успех от неудачи; их различает canceled(). Внутри вложенной сессии очистки нет вовсе: изменения копируются в родительскую сессию, а вложенная остается стоять вместе со своими локальными.

    Вне вложенной сессии значение LOCAL переживает УСПЕШНЫЙ APPLY, когда выполнено ХОТЯ БЫ ОДНО из:

    • LOCAL объявлен как NESTED в момент объявления (LOCAL NESTED name = Type (); или name = DATA LOCAL NESTED Type (...);), ИЛИ
    • APPLY явно сохраняет его через APPLY NESTED (name1, ..., nameN) или APPLY NESTED LOCAL для всех локалов.

    Ассистент НЕ ДОЛЖЕН рассчитывать, что значение обычного LOCAL, вычисленное до УСПЕШНОГО APPLY, останется доступным после него. Сохраняют его два случая: вложенная сессия, где не очищается ничего, и применение, которое не прошло или было отменено, — оно оставляет сессию как была. Если накопленное значение должно жить дольше APPLY — например, буфер импорта, читаемый в пост-apply доработке — ассистент ОБЯЗАН либо объявить его с NESTED, либо перечислить его в APPLY NESTED (...) (или использовать APPLY NESTED LOCAL) в месте вызова.

  6. При использовании NEWSESSION NESTED (...) или NEWSESSION NESTED LOCAL ассистенту СЛЕДУЕТ сохранять те же вложенные локальные свойства на APPLY, если результат должен быть скопирован обратно в верхнюю сессию, например через APPLY NESTED (...) или APPLY NESTED LOCAL.

  7. Ассистент НЕ ДОЛЖЕН заменять NESTEDSESSION простым NEWSESSION для дочерних форм или диалогов, привязанных к родительскому объекту, который может быть ещё не сохранён в текущей сессии формы.

  8. Прежде чем открывать свежую NEWSESSION из действия, запущенного на форме редактирования, ассистенту СЛЕДУЕТ решить, нужно ли сначала сохранить текущие изменения формы.

    Распространённый паттерн: APPLY; IF canceled() THEN RETURN; NEWSESSION { ... }

    Этот паттерн используется перед сменой статусов, генерацией документов и другими изолированными последующими действиями.

  9. После APPLY ассистент ОБЯЗАН проверять canceled() только тогда, когда последующая логика зависит от того, удалось ли сохранение — для раннего выхода, пропуска побочного эффекта или отката отложенной работы.

    APPLY в интерактивном контексте сам показывает пользователю сообщение об ограничении. Ассистент НЕ ДОЛЖЕН добавлять IF canceled() THEN MESSAGE applyMessage() после APPLY в интерактивных действиях только для того, чтобы сообщить об ошибке — это дублирует сообщение, которое уже показала платформа. Явный вывод через applyMessage() или throwException(applyMessage()) нужен только для не интерактивных вызывающих сторон (API-эндпоинты, фоновые интеграции), где никакой диалог не показывается.

    Если APPLY не проходит из-за ограничения, изменения остаются несохранёнными в текущей сессии, и любой последующий APPLY в той же сессии также не пройдёт, пока проблемные данные не исправлены или изменения не отменены (например, через CANCEL).

  10. Ассистенту СЛЕДУЕТ держать блоки NEWSESSION небольшими и целевыми: изолировать одну единицу работы, применить её при необходимости и выйти.

    Ассистент НЕ ДОЛЖЕН вводить NEWSESSION лишь для сокрытия багов видимости сессии. Если изменения верхней сессии должны оставаться видимыми, требуется семантика вложенной сессии.

  11. Тело APPLY может выполниться не один раз. Транзакция применения МОЖЕТ быть автоматически повторена после update conflict, deadlock или таймаута — будет ли, зависит от сбоя и от лимита попыток, — а применяемое действие и синхронные глобальные обработчики находятся внутри того, что повтор выполняет заново.

    Поэтому они ОБЯЗАНЫ выдерживать повтор. Необратимый внешний побочный эффект — отправка письма, вызов HTTP API, печать, запись файла — НЕ ДОЛЖЕН выполняться там: его место после успешного применения, где canceled() говорит, состоялось ли оно.