diff --git a/server/api/min_resolved_ts.go b/server/api/min_resolved_ts.go index c367aabdd1f..9501bf39951 100644 --- a/server/api/min_resolved_ts.go +++ b/server/api/min_resolved_ts.go @@ -16,7 +16,9 @@ package api import ( "net/http" + "strconv" + "github.com/gorilla/mux" "github.com/tikv/pd/pkg/typeutil" "github.com/tikv/pd/server" "github.com/unrolled/render" @@ -41,6 +43,30 @@ type minResolvedTS struct { PersistInterval typeutil.Duration `json:"persist_interval,omitempty"` } +// @Tags min_store_resolved_ts +// @Summary Get store-level min resolved ts. +// @Produce json +// @Success 200 {array} minResolvedTS +// @Failure 400 {string} string "The input is invalid." +// @Failure 500 {string} string "PD server failed to proceed the request." +// @Router /min-resolved-ts/{store_id} [get] +func (h *minResolvedTSHandler) GetStoreMinResolvedTS(w http.ResponseWriter, r *http.Request) { + c := h.svr.GetRaftCluster() + idStr := mux.Vars(r)["store_id"] + storeID, err := strconv.ParseUint(idStr, 10, 64) + if err != nil { + h.rd.JSON(w, http.StatusBadRequest, err.Error()) + return + } + value := c.GetStoreMinResolvedTS(storeID) + persistInterval := c.GetOpts().GetPDServerConfig().MinResolvedTSPersistenceInterval + h.rd.JSON(w, http.StatusOK, minResolvedTS{ + MinResolvedTS: value, + PersistInterval: persistInterval, + IsRealTime: persistInterval.Duration != 0, + }) +} + // @Tags min_resolved_ts // @Summary Get cluster-level min resolved ts. // @Produce json diff --git a/server/api/router.go b/server/api/router.go index e6188b35e41..eb87ef05bc2 100644 --- a/server/api/router.go +++ b/server/api/router.go @@ -351,6 +351,7 @@ func createRouter(prefix string, svr *server.Server) *mux.Router { // min resolved ts API minResolvedTSHandler := newMinResolvedTSHandler(svr, rd) registerFunc(clusterRouter, "/min-resolved-ts", minResolvedTSHandler.GetMinResolvedTS, setMethods(http.MethodGet), setAuditBackend(prometheus)) + registerFunc(clusterRouter, "/min-resolved-ts/{store_id}", minResolvedTSHandler.GetStoreMinResolvedTS, setMethods(http.MethodGet), setAuditBackend(prometheus)) // unsafe admin operation API unsafeOperationHandler := newUnsafeOperationHandler(svr, rd) diff --git a/server/cluster/cluster.go b/server/cluster/cluster.go index 2a1c8ac637d..c5bc385675d 100644 --- a/server/cluster/cluster.go +++ b/server/cluster/cluster.go @@ -2308,6 +2308,16 @@ func (c *RaftCluster) GetMinResolvedTS() uint64 { return c.minResolvedTS } +// GetStoreMinResolvedTS returns the min resolved ts of the store. +func (c *RaftCluster) GetStoreMinResolvedTS(storeID uint64) uint64 { + c.RLock() + defer c.RUnlock() + if !c.isInitialized() || !core.IsAvailableForMinResolvedTS(c.GetStore(storeID)) { + return math.MaxUint64 + } + return c.GetStore(storeID).GetMinResolvedTS() +} + // GetExternalTS returns the external timestamp. func (c *RaftCluster) GetExternalTS() uint64 { c.RLock()