diff --git a/README.md b/README.md index 769ae52..6d49d77 100644 --- a/README.md +++ b/README.md @@ -175,13 +175,14 @@ Note the DID filter parameter is `did` here, not `linkDid` like `getManyToMany` - [ ] Account deactivation handling - [x] Graceful shutdown and Firehose reconnect - [x] CI + Dockerfile +- [x] Add health endpoint **Medium term** - [ ] Robust automatic backfill with checkpoint/resume (survive restarts mid-backfill) - [ ] Exponential backoff for getRepo requests - [ ] Backfill progress reporting -- [ ] Metrics and health endpoints +- [ ] Prometheus metrics endpoint **Longer term** diff --git a/internal/api/health.go b/internal/api/health.go new file mode 100644 index 0000000..ec9e7b4 --- /dev/null +++ b/internal/api/health.go @@ -0,0 +1,11 @@ +package api + +import "net/http" + +func (s *Server) Health(w http.ResponseWriter, r *http.Request) { + if err := s.Store.Ping(r.Context()); err != nil { + http.Error(w, "unhealthy", http.StatusServiceUnavailable) + return + } + w.WriteHeader(http.StatusOK) +} diff --git a/internal/api/server.go b/internal/api/server.go index 365513e..4b35eb8 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -12,6 +12,8 @@ type Server struct { func (s *Server) Run(addr string) error { mux := http.NewServeMux() + mux.HandleFunc("GET /health", s.Health) + mux.HandleFunc("GET /xrpc/blue.microcosm.links.getBacklinksCount", s.GetBacklinksCount) mux.HandleFunc("GET /xrpc/blue.microcosm.links.getBacklinkDids", s.GetBacklinkDids) mux.HandleFunc("GET /xrpc/blue.microcosm.links.getBacklinks", s.GetBacklinks) diff --git a/internal/store/store.go b/internal/store/store.go index d672a7c..5a0f9c6 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -1,6 +1,7 @@ package store import ( + "context" "database/sql" "fmt" @@ -60,3 +61,7 @@ func Open(path string) (*Store, error) { return &Store{writeDB: writeDB, readDB: readDB}, nil } + +func (s *Store) Ping(ctx context.Context) error { + return s.readDB.PingContext(ctx) +}