network/pkg/gateway/handlers/cache/list_handler.go
2026-01-20 10:03:55 +02:00

124 lines
2.8 KiB
Go

package cache
import (
"context"
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
olriclib "github.com/olric-data/olric"
)
// ScanHandler handles cache SCAN/LIST requests for listing keys in a distributed map.
// It expects a JSON body with "dmap" (distributed map name) and optionally "match" (regex pattern).
// Returns all keys in the map, or only keys matching the pattern if provided.
//
// Request body:
//
// {
// "dmap": "my-cache",
// "match": "user:*" // Optional: regex pattern to filter keys
// }
//
// Response:
//
// {
// "keys": ["user:123", "user:456"],
// "count": 2,
// "dmap": "my-cache"
// }
func (h *CacheHandlers) ScanHandler(w http.ResponseWriter, r *http.Request) {
if h.olricClient == nil {
writeError(w, http.StatusServiceUnavailable, "Olric cache client not initialized")
return
}
if r.Method != http.MethodPost {
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
return
}
var req ScanRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "invalid json body")
return
}
if strings.TrimSpace(req.DMap) == "" {
writeError(w, http.StatusBadRequest, "dmap is required")
return
}
ctx, cancel := context.WithTimeout(r.Context(), 30*time.Second)
defer cancel()
olricCluster := h.olricClient.GetClient()
dm, err := olricCluster.NewDMap(req.DMap)
if err != nil {
writeError(w, http.StatusInternalServerError, fmt.Sprintf("failed to create DMap: %v", err))
return
}
var iterator olriclib.Iterator
if req.Match != "" {
iterator, err = dm.Scan(ctx, olriclib.Match(req.Match))
} else {
iterator, err = dm.Scan(ctx)
}
if err != nil {
writeError(w, http.StatusInternalServerError, fmt.Sprintf("failed to scan: %v", err))
return
}
defer iterator.Close()
var keys []string
for iterator.Next() {
keys = append(keys, iterator.Key())
}
writeJSON(w, http.StatusOK, map[string]any{
"keys": keys,
"count": len(keys),
"dmap": req.DMap,
})
}
// HealthHandler handles health check requests for the Olric cache service.
// Returns 200 OK if the cache is healthy, or 503 Service Unavailable if not.
//
// Response (success):
//
// {
// "status": "ok",
// "service": "olric"
// }
//
// Response (failure):
//
// {
// "error": "cache health check failed: ..."
// }
func (h *CacheHandlers) HealthHandler(w http.ResponseWriter, r *http.Request) {
if h.olricClient == nil {
writeError(w, http.StatusServiceUnavailable, "Olric cache client not initialized")
return
}
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
defer cancel()
err := h.olricClient.Health(ctx)
if err != nil {
writeError(w, http.StatusServiceUnavailable, fmt.Sprintf("cache health check failed: %v", err))
return
}
writeJSON(w, http.StatusOK, map[string]any{
"status": "ok",
"service": "olric",
})
}