Файловая корзина#

Файловая корзина (корзина удаленных файлов, recycle bin) хранит удаленные файлы в течение заданного срока вместо немедленного уничтожения. Механизм сохраняет сведения об удалении и, пока содержимое файла остается в хранилище, позволяет пользователю с необходимыми правами найти файл, посмотреть дату удаления и удалившего пользователя, а также выгрузить его содержимое.

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

Ключевые возможности#

  • хранение удаленных файлов в течение срока, заданного для файлового хранилища;

  • сохранение сведений о каждом удалении: даты, удалившего пользователя и объекта-источника, к которому прикреплен файл;

  • выгрузка содержимого удаленного файла;

  • окончательное удаление файла;

  • автоматическая очистка корзины по истечении срока хранения;

  • передача в S3 команды на удаление объекта при помещении файла в корзину.

Работа механизма#

Условия работы

Корзина выключена по умолчанию. Чтобы включить ее для файлового хранилища, задайте параметр Срок хранения удаленных файлов (дней) со значением больше нуля.

Для автоматической очистки корзины в менеджере заданий должно быть активно регламентное задание Плановая чистка файловой корзины. Задание регистрируется автоматически во включенном состоянии и запускается ежедневно в 01:00. Дополнительная настройка задания не требуется.

Для работы с журналом и выполнения операций пользователю необходимы соответствующие права доступа.

Порядок работы

После удаления файл помещается в корзину или удаляется окончательно.

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

  2. Система читает настройки файлового хранилища, в котором находится файл. Если срок хранения не задан или не является положительным, запись о файле и его содержимое удаляются сразу. Если задан положительный срок, система помечает файл как удаленный, а содержимое оставляет в хранилище.

  3. Вместе с признаком удаления система фиксирует дату удаления, имя удалившего пользователя, объект-источник и его наименование. Объект-источник — объект системы, к которому прикреплен файл. Эти сведения записываются при первом удалении и далее не меняются. Если объект-источник у файла не задан, система фиксирует только дату удаления и удалившего пользователя.

  4. Удаленный файл исчезает из обычных списков и карточек файлов и отображается в разделе Журнал удаленных файлов. Путь: Приложение «Настройка системы» > Аудит > Журнал удаленных файлов.

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

  6. Регламентное задание ежедневно в 01:00 окончательно удаляет файлы с истекшим сроком хранения. Задание обходит хранилища с положительным сроком хранения и обрабатывает файлы каждого хранилища порциями по 1000 записей.

Для безвозвратного удаления файла из корзины используйте в журнале операцию Удалить окончательно.

Внимание

Место в файловом хранилище освобождается после истечения срока хранения или окончательного удаления. Исключение для S3 описано в разделе Синхронизация с хранилищем S3. Это следует учитывать при выборе срока хранения для хранилищ с большим объемом данных.

Работа в интерфейсе системы#

Настройка файлового хранилища

Параметры файловой корзины задаются на закладке Дополнительные настройки карточки файлового хранилища.

Путь: Приложение «Настройка системы» > Сущности > Файловое хранилище.

Настройка

Тип хранилища

Назначение

Срок хранения удаленных файлов (дней)

все типы

Число дней, в течение которых удаленный файл остается в корзине. Пустое, нулевое или отрицательное значение отключает корзину

Передавать признак удаления в хранилище S3

только S3

Передает в S3 команду на удаление объекта при помещении файла в корзину

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

Работа с удаленными файлами

Работа с удаленными файлами выполняется в разделе Журнал удаленных файлов.

Путь: Аудит > Журнал удаленных файлов.

Журнал отображает только файлы с признаком удаления и заполненной датой удаления. Последние удаленные файлы отображаются первыми.

storage

В журнале отображаются имя файла, файловое хранилище, полный путь, размер файла, владелец, дата создания, тип и наименование объекта-источника, тип прикрепленного файла, дата удаления и удаливший пользователь.

На панели фильтров можно задать файловое хранилище, имя файла, владельца, удалившего пользователя и период удаления. Условия панели можно дополнить с помощью универсального фильтра.

Операция

Доступность

Результат

Выгрузить файл

для активной строки удаленного файла

Скачивает содержимое файла из хранилища. Если содержимого в хранилище нет, система сообщает имя файла и файлового хранилища

Удалить окончательно

для активной строки удаленного файла

После подтверждения безвозвратно удаляет содержимое файла из хранилища и запись Btk_File

Устройство файловой корзины#

При включенной файловой корзине операция delete объекта Btk_File выполняет логическое удаление: устанавливает признак bDeleted = 1, фиксирует дату удаления и сведения об удалившем пользователе. Запись Btk_File сохраняется до окончательного удаления.

Механизм реализован в модуле btk и включается настройкой файлового хранилища. Прикладные модули используют механизм через стандартную операцию delete.

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

Архитектура механизма#

Механизм построен на следующих принципах:

  1. Разделение логического и физического удаления. Операция delete делегирует выполнение в deleteUsingRecycleBin, а физическое удаление выполняет отдельная операция purge.

  2. Централизация политики удаления. Прикладной код вызывает стандартную операцию delete и не определяет способ удаления. По этой причине Btk_AttachVerApi удаляет основной файл версии вложения вызовом Btk_FileApi().delete(...), а не прямым вызовом deleteUsingRecycleBin.

  3. Управление поведением через настройки хранилища. Срок хранения читается из jSettings объекта Btk_FileStorage в момент удаления, поэтому администратор включает корзину отдельно для каждого хранилища.

  4. Хранение метаданных рядом с файлом. Дата удаления, удаливший пользователь и объект-источник записываются в атрибуты dDelete и jDeleteData записи Btk_File.

Дерево компонентов

Btk_FileApi (политика удаления файла)
├── delete(rop)                  — точка входа прикладного кода, делегирует в deleteUsingRecycleBin
├── deleteUsingRecycleBin(rop, gidpSrc, bScheduleBeforeFlush) — маршрутизация: корзина или purge
├── purge(rop)                   — окончательное удаление: физический файл и запись Btk_File
├── purgeBeforeFlush(rop)        — отложенное окончательное удаление на beforeFlush
└── processRecycleBin()          — регламентная очистка корзины по истечении срока хранения
Btk_FileStorageApi (настройки хранилища)
├── getRecycleBinSettings(idpFileStorage) / getRecycleBinSettings(rop)
└── RecycleBinSettings(nRetentionPeriod, bS3Sync)
ru.bitec.app.btk.file.DeletedFileData(sUser, gidSrcObj, sSrcObjHeadline) (метаданные удаления)
├── forSource(gidpSrc)           — сбор данных удаления
├── forFile(idpFile)             — чтение данных из jDeleteData
└── applyToFile(rop)             — запись dDelete и ключей jDeleteData

Компоненты разделяют политику удаления, настройки хранилища и хранение метаданных удаления. Далее описаны данные и настройки, на которых основано это взаимодействие.

Данные и настройки файловой корзины#

Состояние файла

Состояние файла в корзине описывают три атрибута класса Btk_File.

Атрибут

Тип ODM

Заголовок

Назначение

bDeleted

Number

Пометка удаления

признак нахождения файла в корзине

dDelete

Date

Дата удаления

момент помещения файла в корзину

jDeleteData

Jsonb

Информация об удаленном файле

сведения об удалении: пользователь и объект-источник

Значение bDeleted = 1 означает, что файл находится в корзине. Сеттер setbDeleted не выполняет действий с файловым хранилищем.

Метаданные удаления

Ключ

Тип значения

Содержание

sUser

строка

имя удалившего пользователя, Btk_UserApi().getCurrentUserName

gidSrcObj

gid

объект-источник, к которому прикреплен файл

sSrcObjHeadline

строка

заголовок объекта-источника, Btk_Pkg().getHeadLineByGid

Значения gidSrcObj и sSrcObjHeadline остаются пустыми, если файл удаляют без объекта-источника.

Настройки файлового хранилища

Настройки корзины хранятся в ключах jsonb-атрибута jSettings объекта Btk_FileStorage и отображаются на закладке Дополнительные настройки карточки файлового хранилища.

Ключ

Заголовок в интерфейсе

Тип

Область применения

nRecycleBinRetentionDays

Срок хранения удаленных файлов (дней)

число

все типы файловых хранилищ

bNeedS3RecycleBinSync

Передавать признак удаления в хранилище S3

логический

только хранилища типа S3

Пустое, нулевое или отрицательное значение nRecycleBinRetentionDays отключает корзину: стандартная операция delete выполняет окончательное удаление вместо помещения файла в корзину.

Чтение настроек в коде

Btk_FileStorageApi предоставляет две перегрузки getRecycleBinSettings — по идентификатору хранилища и по объекту ApiRop. Обе возвращают case-класс RecycleBinSettings(nRetentionPeriod: NPeriod, bS3Sync: Boolean).

Пример получения настроек для объекта файлового хранилища:

val recycleBinSettings =
  Btk_FileStorageApi().getRecycleBinSettings(rvFileStorage)

Если ключ bNeedS3RecycleBinSync отсутствует, bS3Sync принимает значение false.

Жизненный цикл файла#

Состояния записи Btk_File

Состояние

Признаки

Как достигается

Видимость в формах

Активный

bDeleted пусто или 0, dDelete пусто

создание файла

форма «Файлы» и форма администрирования файловых хранилищ

В корзине

bDeleted = 1, заполнены dDelete и jDeleteData

delete при заданном сроке хранения

журнал удаленных файлов

Удален окончательно

запись Btk_File отсутствует

purge, purgeBeforeFlush, регламент Btk_JobProcessRecycleBin

нигде

Обратный переход из состояния «В корзине» в состояние «Активный» не предусмотрен.

Последовательность обработки удаления#

Помещение файла в корзину

Сценарий выполняется, когда прикладной код удаляет файл, а у хранилища задан положительный срок хранения.

Пример стандартного удаления:

val ropFile = Btk_FileApi().load(idpFile)
Btk_FileApi().delete(ropFile)

Далее механизм выполняет следующие действия:

  1. Прикладной код вызывает Btk_FileApi().delete(rop).

  2. delete делегирует выполнение в deleteUsingRecycleBin(rop) с параметрами по умолчанию.

  3. Метод проверяет признак bDeleted. Значение, отличное от 1, означает, что файл еще не находится в корзине.

  4. Btk_FileStorageApi().load(...) загружает хранилище файла. При пустом idFileStorage используется хранилище по умолчанию idDefault.

  5. getRecycleBinSettings(rvFileStorage) разбирает jSettings и возвращает RecycleBinSettings.

  6. Поскольку срок хранения положительный, метод вычисляет GID источника gidpSrc.nvl(rop.get(_.gidSrc)).

  7. DeletedFileData.forSource(gidvSrc).applyToFile(rop) записывает dDelete и ключи jDeleteData.

  8. setbDeleted(rop, 1.nr) помечает файл как находящийся в корзине.

  9. Запись Btk_File остается в системе до окончательного удаления.

Окончательное удаление при выключенной корзине

Шаги 1–5 совпадают с помещением в корзину, но срок хранения не задан, равен нулю или отрицательный. Далее метод выбирает режим по параметру bScheduleBeforeFlush:

  • при true вызывается purgeBeforeFlush(rop) — вызов окончательного удаления откладывается до beforeFlush;

  • при false вызывается purge(rop) — окончательное удаление записи начинается в текущем вызове.

Окончательное удаление из журнала удаленных файлов

Операция Удалить окончательно доступна для активной строки журнала. Система загружает запись Btk_File по идентификатору и запрашивает подтверждение. После подтверждения вызывается операция purge.

Операция безвозвратно удаляет физический файл из хранилища и запись Btk_File, после чего список журнала обновляется.

Регламентная очистка корзины

  1. По расписанию задание выполняет Btk_FileApi.processRecycleBin().

  2. Система получает файловые хранилища с положительным сроком хранения удаленных файлов.

  3. Для каждого хранилища система вычисляет предельную дату удаления: из текущей даты вычитает настроенный срок хранения.

  4. Отдельный запрос выбирает удаленные файлы текущего хранилища, дата удаления которых меньше предельной.

  5. Файлы обрабатываются порциями по 1000 записей. Для каждого файла вызывается Btk_FileApi().purge(...), после каждой порции выполняется session.flush().

  6. После завершения обработки файлового хранилища выполняется session.commit().

Срок хранения вычисляется приложением при обработке хранилища, поэтому изменение настройки действует и на файлы, помещенные в корзину ранее. Разделение обхода хранилищ и выбора файлов исключает соединение Btk_File с Btk_FileStorage и разбор jSettings в запросе по таблице файлов.

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

Синхронизация с хранилищем S3

Синхронизация с S3 выполняется при одновременном выполнении двух условий:

  • настройка bNeedS3RecycleBinSync активна;

  • тип хранилища равен Btk_FileStorageTypeApi().idS3.

Файл помещается в корзину в стандартном порядке: запись сохраняет bDeleted = 1, dDelete и jDeleteData.

Дополнительно на beforeFlush планируется вызов deleteFile(svFullFileName) по системному имени хранилища. Команда на удаление передается в S3, а метаданные удаления остаются в системе.

При включенной синхронизации содержимое файла может стать недоступно сразу после помещения записи в корзину. Срок хранения удаленных объектов в S3 настраивается отдельно и может быть меньше срока хранения в Global ERP. В этом случае содержимое удаляется из S3 раньше записи Btk_File.

Транзакции и обработка ошибок#

Физическое удаление файла в purge, purgeBeforeFlush и при синхронизации с S3 выполняется через session.scheduleBeforeFlush.

Регламентное задание обрабатывает каждое файловое хранилище в отдельной транзакции. Файлы выбираются порциями по 1000 записей. После обработки порции система вызывает session.flush(), а после завершения всего хранилища — session.commit().

При вызове session.flush() сначала выполняются запланированные действия beforeFlush. Поэтому физические файлы начинают удаляться до фиксации удаления записей Btk_File в конце обработки хранилища.

Исключение AppException при отдельном вызове purge записывается в журнал, увеличивает счетчик ошибок и не останавливает обработку остальных файлов порции. Если AppException возникает за пределами обработки отдельного файла, транзакция хранилища отменяется, после чего задание переходит к следующему хранилищу.

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

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

Особенности и ограничения#

При работе с файловой корзиной учитывайте следующие особенности и ограничения:

  • корзина выключена по умолчанию и начинает использоваться только после задания срока хранения для файлового хранилища;

  • восстановление файла из корзины не предусмотрено — пользователю с необходимыми правами доступны просмотр сведений об удалении, выгрузка содержимого и окончательное удаление;

  • окончательное удаление необратимо и выполняется с помощью операции Удалить окончательно, регламентного задания или повторного удаления файла, уже находящегося в корзине;

  • удаленные файлы доступны в разделе Журнал удаленных файлов и не отображаются в обычных списках и карточках файлов;

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

  • срок хранения отсчитывается от даты удаления файла, а не от даты его создания или изменения;

  • при очистке хранилища по настройкам Btk_FileStorageCleanSetting выполняется purgeBeforeFlush: запись Btk_File и физическое содержимое файла удаляются окончательно, минуя корзину;

  • служебные и производные файлы могут удаляться окончательно с помощью purge или purgeBeforeFlush, минуя корзину;

  • срок хранения задается только на уровне файлового хранилища — отдельные политики по типам файлов или объектам-источникам не предусмотрены;

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