Атомарність і відновлення
AtomicFilesystem::write_atomic() записує дані в тимчасовий файл, виконує flush і fsync для дескриптора цього файлу, перейменовує його на цільовий шлях і намагається виконати fsync батьківського каталогу. Якщо запис не вдається, тимчасовий файл видаляється.
Екземпляри сховища з можливістю запису реєструють маркер для кожного процесу в .storh/writers/ і видаляють його під час коректного завершення роботи. Під час відкриття сховища перевіряються ці маркери: якщо власники всіх маркерів активні (або маркерів немає), відкриття займає сталий час; якщо процес-власник маркера завершився, це означає аварійне завершення запису, тож під час відкриття перевіряється колекція, видаляються осиротілі тимчасові файли та застарілий маркер. repair() завжди виконує таку перевірку.
Під час відновлення DocStore поміщає пошкоджені або обрізані файли записів у карантин .storh/corrupt/ і перебудовує вторинні індекси за рештою коректних записів. Перевірка DocStore також зіставляє файли індексів із повним скануванням записів, щоб виявити відсутні чи застарілі записи індексу, перш ніж вважати їх коректними.
Рушії з журналом лише для додавання виконують flush і fsync для дескрипторів файлів журналу, перш ніж вважати події зафіксованими в пам'яті. Надійність збереження під час втрати живлення все одно залежить від того, чи файлова система й параметри монтування коректно виконують синхронізацію файлів і каталогів.
Сегментований журнал записує кожен рядок у такому форматі:
<byte-length>\t<xxh32>\t<json>\n
Під час читання перевіряються довжина в байтах і контрольна сума. Відновлення сканує кожен сегмент і обрізає файл до останнього повного коректного рядка, видаляючи неповні записи в кінці. Під час перевірки активний похідний індекс стану зіставляється з незалежним відтворенням сегментів, щоб виявити зовнішні зміни або застарілий стан до його відновлення.
Під час перевірки черги декодується кожна довговічна подія, а поточний стан очікуваних завдань, завдань в обробці й виконаних завдань, даних і порядку отримання зіставляється з незалежним відтворенням журналу. Відновлення перебудовує цей стан із queue.log і обрізає неповні події в кінці. Під час отримання завдань і завершення їх обробки утримується блокування черги, доки дані не синхронізуються з довговічним журналом, тож кілька робочих процесів не отримають одне й те саме очікуване завдання.
Під час ущільнення записуються нові файли сегментів compact-*, а потім оновлюється маніфест. Якщо процес завершується до заміни маніфесту, під час повторного відкриття видаляються непов'язані результати ущільнення, а робота триває зі старим маніфестом. Після завершення ущільнення старі закриті сегменти навмисно залишаються, щоб читачі, які вже читають їх потоково, могли продовжити роботу.