feat(health): add disk space check to file store health endpoint#700
Conversation
Check available disk space via Statfs during file store health checks. Returns 503 when available space drops below 1 GiB. Includes available and total disk space in the health response message for observability.
|
🤖 Claude Code Review Status: Complete Current Issues: Two minor issues remain from previous review:
New Observations:
Fixed:
|
Benchmark Comparison ReportBaseline: Current: Summary
All benchmark results (sec/op)
Threshold: >10% with p < 0.05 | Generated: 2026-05-19 12:39 UTC |
| return http.StatusInternalServerError, "File Store: Unable to check disk space", err | ||
| } | ||
|
|
||
| availableBytes := stat.Bavail * uint64(stat.Bsize) |
There was a problem hiding this comment.
[Major] Missing overflow protection: stat.Bavail * uint64(stat.Bsize) could overflow on filesystems with large block sizes. Consider checking for overflow or using math/big for very large values.
|
|
||
| s.debugf("[File] Health check succeeded path=%s", s.path) | ||
| return http.StatusOK, "File Store: Healthy", nil | ||
| return http.StatusOK, fmt.Sprintf("File Store: Healthy (%s available of %s)", humanBytes(availableBytes), humanBytes(totalBytes)), nil |
There was a problem hiding this comment.
[Minor] Test update needed: The existing TestFileHealth test at file_test.go:975 expects the old message format "File Store: Healthy" but the implementation now returns "File Store: Healthy ()". The test should be updated to match the new format or use string contains/prefix matching.
✅ FIXED - Test now uses regexp matching at file_test.go:975
| exp++ | ||
| } | ||
|
|
||
| return fmt.Sprintf("%.1f %ciB", float64(b)/float64(div), "KMGTPE"[exp]) |
There was a problem hiding this comment.
[Minor] Potential index out of bounds: humanBytes() accesses "KMGTPE"[exp] without validating exp < 6. While unlikely with uint64, consider adding a bounds check or using a slice lookup with bounds checking for defensive programming.
|
Brings in fff6d3e..origin/main (4 commits since previous merge): - #897 blockassembly columnar->row fallback on Unimplemented - #896 asset on-demand subtree-data admission control + 503/Retry-After - #766 utxo: verify spend ownership in Unspend - #700 health: disk space check Conflict resolutions: - services/blockassembly/Client.go, util/http.go, util/http_test.go: take theirs. Main has the post-Copilot-fix versions of these files from #896 and #897 (parseRetryAfter strict-Atoi, debug log on columnar fallback, extended TestParseRetryAfter cases) — they supersede the pre-fix versions still living on pr-828. - stores/utxo/aerospike/un_spend.go: take ours (native-op call, no SpendingData arg). The ownership check #766 added to the UDF path requires a coordinated update to the BSV-forked aerospike- server's subOpUnspend dispatcher. Until that lands, the native-op path on this branch skips ownership verification. Tracking issue filed.


Summary
Health()method viasyscall.StatfsHealthy response:
File Store: Healthy (245.3 GiB available of 500.0 GiB)Unhealthy response:
File Store: Low disk space (512.0 MiB available of 500.0 GiB)Test plan
/health/readinessincludes disk space info in the file store dependency