Trying to add _ls and _tree subcalls to item paths..

This commit is contained in:
Kalzu Rekku
2025-09-29 21:14:03 +03:00
parent 32b347f1fd
commit d5a0eb7efe
5 changed files with 387 additions and 59 deletions

View File

@@ -22,8 +22,6 @@ import (
"kvs/utils"
)
// healthHandler returns server health status
func (s *Server) healthHandler(w http.ResponseWriter, r *http.Request) {
mode := s.getMode()
@@ -1099,6 +1097,102 @@ func (s *Server) getSpecificRevisionHandler(w http.ResponseWriter, r *http.Reque
json.NewEncoder(w).Encode(storedValue)
}
// getKeyListHandler handles _ls endpoint for direct children
func (s *Server) getKeyListHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
path := "/" + vars["path"] // Ensure leading slash for consistency
// Parse query params
limitStr := r.URL.Query().Get("limit")
limit := 100 // Default
if limitStr != "" {
if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 1000 {
limit = l
}
}
includeMetadata := r.URL.Query().Get("include_metadata") == "true"
mode := s.getMode()
if mode == "syncing" {
http.Error(w, "Service Unavailable", http.StatusServiceUnavailable)
return
}
keys, err := s.merkleService.GetKeysInPrefix(path, limit)
if err != nil {
s.logger.WithError(err).WithField("path", path).Error("Failed to get keys in prefix")
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
response := KeyListResponse{
Path: path,
Children: make([]struct{ Subkey string; Timestamp int64 }, len(keys)),
Total: len(keys),
}
for i, subkey := range keys {
fullKey := path + subkey
if includeMetadata {
ts, err := s.merkleService.getTimestampForKey(fullKey)
if err == nil {
response.Children[i].Timestamp = ts
}
}
response.Children[i].Subkey = subkey
}
if len(keys) >= limit {
response.Truncated = true
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}
// getKeyTreeHandler handles _tree endpoint for recursive tree
func (s *Server) getKeyTreeHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
path := "/" + vars["path"]
// Parse query params
depthStr := r.URL.Query().Get("depth")
maxDepth := 0 // Unlimited
if depthStr != "" {
if d, err := strconv.Atoi(depthStr); err == nil && d > 0 {
maxDepth = d
}
}
limitStr := r.URL.Query().Get("limit")
limit := 500
if limitStr != "" {
if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 5000 {
limit = l
}
}
includeMetadata := r.URL.Query().Get("include_metadata") == "true"
mode := s.getMode()
if mode == "syncing" {
http.Error(w, "Service Unavailable", http.StatusServiceUnavailable)
return
}
tree, err := s.merkleService.GetTreeForPrefix(path, maxDepth, limit)
if err != nil {
s.logger.WithError(err).WithField("path", path).Error("Failed to build tree")
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(tree)
}
// calculateHash computes SHA256 hash of data
func calculateHash(data []byte) []byte {
h := sha256.New()