(ctx context.Context, checkpointing bool, exec *syncExecutor)
| 1247 | } |
| 1248 | |
| 1249 | func (db *DB) verifyAndSyncWithExecutor(ctx context.Context, checkpointing bool, exec *syncExecutor) (syncResult, error) { |
| 1250 | // Use the last synced WAL offset as the logical size for checkpoint decisions. |
| 1251 | // This avoids using file size which may include stale frames with old salt |
| 1252 | // values after a checkpoint. See issue #997. |
| 1253 | origWALSize := exec.state.lastSyncedWALOffset |
| 1254 | if origWALSize == 0 { |
| 1255 | // First sync - use file size as fallback |
| 1256 | var err error |
| 1257 | origWALSize, err = db.walFileSize() |
| 1258 | if err != nil { |
| 1259 | return syncResult{}, fmt.Errorf("stat wal before sync: %w", err) |
| 1260 | } |
| 1261 | } |
| 1262 | |
| 1263 | // Verify our last sync matches the current state of the WAL. |
| 1264 | // This ensures that the last sync position of the real WAL hasn't |
| 1265 | // been overwritten by another process. |
| 1266 | db.setSyncDiagPhase(diagPhaseVerify) |
| 1267 | info, err := db.verifyWithExecutor(ctx, exec) |
| 1268 | if err != nil { |
| 1269 | return syncResult{}, fmt.Errorf("cannot verify wal state: %w", err) |
| 1270 | } |
| 1271 | |
| 1272 | result, err := db.sync(ctx, checkpointing, exec, info) |
| 1273 | if err != nil { |
| 1274 | return syncResult{}, fmt.Errorf("sync: %w", err) |
| 1275 | } |
| 1276 | |
| 1277 | result.origWALSize = origWALSize |
| 1278 | return result, nil |
| 1279 | } |
| 1280 | |
| 1281 | // checkpointIfNeeded performs a checkpoint based on configured thresholds. |
| 1282 | // Checks thresholds in priority order: TruncatePageN → MinCheckpointPageN → CheckpointInterval. |
no test coverage detected