コンテンツへスキップ

原子性と復旧

AtomicFilesystem::write_atomic() は一時ファイルに書き込み、ファイルハンドルをフラッシュして fsync した後、対象パスのファイルと名前を置き換え、親ディレクトリの fsync を試みます。書き込みに失敗した場合は、その処理で作成した一時ファイルを削除します。

書き込み可能なストアインスタンスは、.storh/writers/ にプロセスごとのマーカーを登録し、正常終了時に削除します。ストアを開くときにこれらのマーカーを確認します。すべてのマーカーの所有プロセスが稼働中(またはマーカーがない)なら、定数時間で開けます。所有プロセスが終了したマーカーがあれば、書き込みプロセスがクラッシュしたことを示すため、ストアを開く際にコレクションを走査して孤立した一時ファイルを削除し、古いマーカーを消去します。repair() は常に走査します。

DocStoreの修復では、破損または途中で切れたレコードファイルを.storh/corrupt/に隔離し、残りの有効なレコードからセカンダリインデックスを再構築します。DocStoreの検証では、インデックスファイルと全レコードのスキャン結果も照合するため、正常として扱われる前に、欠落または古くなったインデックスエントリーが報告されます。

追記専用エンジンは、イベントをメモリ上でコミット済みとみなす前に、ログファイルのハンドルをフラッシュしてfsyncします。電源喪失時の耐久性は、基盤となるファイルシステムとマウントオプションがファイルおよびディレクトリの同期を順守するかどうかにも左右されます。

セグメント化ログでは、各行を次の形式で書き込みます。

Text
<byte-length>\t<xxh32>\t<json>\n

読み取り時にはバイト長とチェックサムを検証します。復旧時には各セグメントをスキャンし、最後に完全で有効な行がある位置でファイルを切り詰め、末尾の不完全な書き込みを取り除きます。検証では、有効な派生状態インデックスを独立したセグメント再生の結果と照合するため、外部から変更された状態や古くなった状態が報告されてから、修復によって再構築されます。

キューの検証では、永続化されたすべてのキューイベントをデコードし、現在の保留中、処理中、完了済みの状態、ペイロード、要求順序を独立したログ再生の結果と照合します。修復ではqueue.logから状態を再構築し、末尾の不完全なイベントを切り詰めます。要求と完了の処理では、永続ログとの同期中にキューのロックを保持するため、複数のワーカープロセスが同じ保留中ジョブを取得することはありません。

圧縮では新しいcompact-*セグメントファイルを書き込み、その後マニフェストを更新します。マニフェストの切り替え前にプロセスが終了した場合、再オープン時に参照されていない圧縮出力を削除し、古いマニフェストから処理を続けます。完了した圧縮でも、そこから読み取り中のリーダーが引き続き利用できるよう、古い封印済みセグメントは意図的に残します。