@@ -24,6 +24,8 @@ const (
2424 DefaultPollTXIDInterval = 1 * time .Millisecond
2525 DefaultPollTXIDTimeout = 5 * time .Second
2626
27+ DefaultMaxLag = 10 * time .Second
28+
2729 DefaultCookieExpiry = 5 * time .Minute
2830)
2931
@@ -61,6 +63,9 @@ type ProxyServer struct {
6163 PollTXIDInterval time.Duration
6264 PollTXIDTimeout time.Duration
6365
66+ // Maximum allowable lag before the health endpoint returns an error code.
67+ MaxLag time.Duration
68+
6469 // Time before cookie expires on client.
6570 CookieExpiry time.Duration
6671
@@ -74,6 +79,7 @@ func NewProxyServer(store *litefs.Store) *ProxyServer {
7479
7580 PollTXIDInterval : DefaultPollTXIDInterval ,
7681 PollTXIDTimeout : DefaultPollTXIDTimeout ,
82+ MaxLag : DefaultMaxLag ,
7783 CookieExpiry : DefaultCookieExpiry ,
7884 }
7985
@@ -167,6 +173,12 @@ func (s *ProxyServer) serveHTTP(w http.ResponseWriter, r *http.Request) {
167173 return
168174 }
169175
176+ // Handle health check endpoint.
177+ if r .Method == http .MethodGet && r .URL .Path == "/litefs/healthz" {
178+ s .serveGetHealthz (w , r )
179+ return
180+ }
181+
170182 switch r .Method {
171183 case http .MethodGet :
172184 s .serveRead (w , r )
@@ -177,6 +189,18 @@ func (s *ProxyServer) serveHTTP(w http.ResponseWriter, r *http.Request) {
177189 }
178190}
179191
192+ func (s * ProxyServer ) serveGetHealthz (w http.ResponseWriter , r * http.Request ) {
193+ lag := s .store .Lag ()
194+ if s .MaxLag > 0 && lag > s .MaxLag {
195+ s .logf ("proxy: %s %s: current replication lag of %s exceeds maximum threshold of %s" , r .Method , r .URL .Path , lag , s .MaxLag )
196+ http .Error (w , "Replication lag exceeded" , http .StatusServiceUnavailable )
197+ return
198+ }
199+
200+ w .WriteHeader (http .StatusOK )
201+ _ , _ = w .Write ([]byte ("OK\n " ))
202+ }
203+
180204func (s * ProxyServer ) serveRead (w http.ResponseWriter , r * http.Request ) {
181205 // Determine the last write TXID seen by
182206 var txid ltx.TXID
0 commit comments