Все главы учебника
Содержание учебника
Глава 04 / Бесплатный backend-путь

Перезапуск: что осталось на диске

40 мин чтенияКонтент v0.8.0

Память заканчивается вместе с процессом

До этого этапа id терял смысл после перезапуска: map исчезала. Теперь приложение сохраняет снимок заданий в JSON-файл DataFile. Снимок — представление текущих записей на диске. При запуске New(Config) читает его, восстанавливает завершённые результаты и возвращает незавершённые задания в обработку.

Файл принадлежит одному процессу. Не запускайте два сервера с общим DATA_FILE: этот этап не реализует распределённую блокировку или базу данных. Если путь относительный, он считается от текущей рабочей папки сервера. По умолчанию это jobs.json.

Что прочитать

Вернитесь к ошибкам, JSON и модулю из прошлых этапов. Прочитайте данные и инварианты, особенно части о памяти, устойчивом хранении и границах операции. SQL-примеры помогают сравнить подходы; устанавливать SQL-сервер в этом проекте не требуется. Для дополнительного разбора диска используйте fsync и долговечность.

В Go os.ReadFile читает байты и возвращает ошибку; отсутствие файла при первом запуске отличается от повреждённого существующего файла. json.Unmarshal разбирает байты в структуру. json.Marshal делает обратное. Закрытие файла, запись и подтверждение сохранения имеют разные смыслы; не превращайте ошибку ввода-вывода в успешное принятие задания.

Сохраните переходы

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

При замене снимка избегайте промежуточного файла, который читатель примет за полный JSON. Изучите способ записи, выбранный в каркасе и эталоне: подготовка временного файла и замена основного позволяют отделить подготовку от публикации. Само слово «атомарный» не означает гарантию пережить любую потерю питания. Здесь проверяются перезапуск процесса и ошибки файловых операций; гарантии оборудования, файловой системы и аварии ОС нужно оговаривать отдельно.

После загрузки queued и running снова становятся ожидающими. При восстановлении не прибавляйте попытку только за факт чтения файла. Попытка относится к фактическому запуску обработки. Если в снимке уже был результат done, его не надо пересчитывать. Восстановленное ожидание включает прежние running и queued, поэтому конечный backlog уже принятых заданий может быть больше QueueSize. Обработчики должны его разобрать; новый приём при заполнении получает 429. Метрика queued показывает всё ожидание, а capacity — предел живой очереди.

Проверьте восстановление

go test ./... -run '^TestStage0[1-4]' -count=1
go test -race ./... -run '^TestStage0[1-4]' -count=1

Используйте t.TempDir() в своих тестах, чтобы они не зависели от личного jobs.json. Создайте приложение с файлом в этой папке, дождитесь завершения задания, остановите его и создайте новое приложение с тем же путём. Прочитайте прежний id. Отдельно проверьте повреждённый JSON: запуск должен сообщить ошибку, а не начать с пустой map поверх старых данных.

Проведите ручной опыт с незавершённым заданием и перезапуском. Запишите, на какой точке остановили процесс и какое состояние восстановилось. Не убивайте основной процесс теста; для аварии используйте отдельно запущенный сервер и копию данных.

Почему работа может повториться

Процесс мог вычислить результат и завершиться до сохранения done. После запуска снимок всё ещё показывает running, и задание запускается снова. Это обработка как минимум один раз. Наше преобразование текста не отправляет деньги, письма и внешние запросы: повтор расчёта не добавляет внешний эффект. Для внешнего эффекта понадобятся отдельный договор и защита от дублей.

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

Когда идти дальше

Покажите восстановление результата и незавершённой записи. Объясните окно возможного повтора и ограничения одного процесса. Затем добавим повтор запроса и повтор попытки.

Самопроверка этапа

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

Что выполнено

Для завершения отметьте все критерии и добавьте объяснение.