move feature from meta-sort to meta-core
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// KVInfoResponse is the response for GET /api/kv/info
|
||||
type KVInfoResponse struct {
|
||||
Prefix string `json:"prefix"`
|
||||
FileCount int `json:"fileCount"`
|
||||
KeyCount int `json:"keyCount"`
|
||||
TotalSize int64 `json:"totalSize"`
|
||||
MemoryUsage string `json:"memoryUsage"`
|
||||
}
|
||||
|
||||
// KVKeysResponse is the response for GET /api/kv/keys
|
||||
type KVKeysResponse struct {
|
||||
Keys []string `json:"keys"`
|
||||
Cursor string `json:"cursor"`
|
||||
HasMore bool `json:"hasMore"`
|
||||
}
|
||||
|
||||
// KVKeyValueResponse is the response for GET /api/kv/key/{key}
|
||||
type KVKeyValueResponse struct {
|
||||
Key string `json:"key"`
|
||||
Type string `json:"type"`
|
||||
Value map[string]string `json:"value"`
|
||||
}
|
||||
|
||||
// handleKVInfo handles GET /api/kv/info
|
||||
func (s *Server) handleKVInfo(w http.ResponseWriter, r *http.Request) {
|
||||
if !s.storage.IsConnected() {
|
||||
writeError(w, http.StatusServiceUnavailable, "storage not connected")
|
||||
return
|
||||
}
|
||||
|
||||
// Get all hash IDs to count files
|
||||
hashIDs, err := s.storage.GetAllHashIDs()
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Get memory usage
|
||||
memoryUsage, err := s.storage.GetMemoryInfo()
|
||||
if err != nil {
|
||||
memoryUsage = "N/A"
|
||||
}
|
||||
|
||||
// Calculate total size from sizeByte metadata (if available)
|
||||
var totalSize int64
|
||||
for _, hashID := range hashIDs {
|
||||
sizeStr, err := s.storage.GetProperty(hashID, "sizeByte")
|
||||
if err == nil && sizeStr != "" {
|
||||
if size, err := strconv.ParseInt(sizeStr, 10, 64); err == nil {
|
||||
totalSize += size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response := KVInfoResponse{
|
||||
Prefix: "file:",
|
||||
FileCount: len(hashIDs),
|
||||
KeyCount: len(hashIDs),
|
||||
TotalSize: totalSize,
|
||||
MemoryUsage: memoryUsage,
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
// handleKVKeys handles GET /api/kv/keys
|
||||
func (s *Server) handleKVKeys(w http.ResponseWriter, r *http.Request) {
|
||||
if !s.storage.IsConnected() {
|
||||
writeError(w, http.StatusServiceUnavailable, "storage not connected")
|
||||
return
|
||||
}
|
||||
|
||||
// Parse query parameters
|
||||
cursorStr := r.URL.Query().Get("cursor")
|
||||
countStr := r.URL.Query().Get("count")
|
||||
|
||||
cursor := 0
|
||||
if cursorStr != "" {
|
||||
if c, err := strconv.Atoi(cursorStr); err == nil {
|
||||
cursor = c
|
||||
}
|
||||
}
|
||||
|
||||
count := 50
|
||||
if countStr != "" {
|
||||
if c, err := strconv.Atoi(countStr); err == nil && c > 0 {
|
||||
count = c
|
||||
}
|
||||
}
|
||||
|
||||
// Get all hash IDs
|
||||
allHashIDs, err := s.storage.GetAllHashIDs()
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Simple offset-based pagination
|
||||
var keys []string
|
||||
end := cursor + count
|
||||
if end > len(allHashIDs) {
|
||||
end = len(allHashIDs)
|
||||
}
|
||||
|
||||
if cursor < len(allHashIDs) {
|
||||
for _, id := range allHashIDs[cursor:end] {
|
||||
keys = append(keys, "file:"+id)
|
||||
}
|
||||
}
|
||||
|
||||
nextCursor := cursor + len(keys)
|
||||
hasMore := nextCursor < len(allHashIDs)
|
||||
|
||||
response := KVKeysResponse{
|
||||
Keys: keys,
|
||||
Cursor: strconv.Itoa(nextCursor),
|
||||
HasMore: hasMore,
|
||||
}
|
||||
|
||||
if !hasMore {
|
||||
response.Cursor = "0"
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
// handleKVGetKey handles GET /api/kv/key/{key}
|
||||
func (s *Server) handleKVGetKey(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
key := vars["key"]
|
||||
|
||||
if key == "" {
|
||||
writeError(w, http.StatusBadRequest, "key is required")
|
||||
return
|
||||
}
|
||||
|
||||
// URL decode the key (in case it contains encoded characters)
|
||||
decodedKey, err := url.PathUnescape(key)
|
||||
if err != nil {
|
||||
decodedKey = key
|
||||
}
|
||||
|
||||
if !s.storage.IsConnected() {
|
||||
writeError(w, http.StatusServiceUnavailable, "storage not connected")
|
||||
return
|
||||
}
|
||||
|
||||
// Extract hash ID from key (format: file:{hashId})
|
||||
if !strings.HasPrefix(decodedKey, "file:") {
|
||||
writeError(w, http.StatusBadRequest, "invalid key format, expected: file:{hashId}")
|
||||
return
|
||||
}
|
||||
|
||||
hashID := strings.TrimPrefix(decodedKey, "file:")
|
||||
|
||||
// Get metadata for this hash ID
|
||||
metadata, err := s.storage.GetMetadataFlat(hashID)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if metadata == nil {
|
||||
writeError(w, http.StatusNotFound, "key not found")
|
||||
return
|
||||
}
|
||||
|
||||
response := KVKeyValueResponse{
|
||||
Key: decodedKey,
|
||||
Type: "hash",
|
||||
Value: metadata,
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, response)
|
||||
}
|
||||
Reference in New Issue
Block a user