v2.0.0: claims model - signed MMUR2 votes in a truth DB, merged view in a rebuildable cache DB; POST /api/claims, claims and merge routes, unsigned writes answer 410
Build and Push Docker Image / build (push) Successful in 5m1s
Build and Push Docker Image / build (push) Successful in 5m1s
This commit is contained in:
+7
-38
@@ -383,8 +383,9 @@ func (s *Server) handleKVValueGet(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// handleKVValuePut handles PUT /api/kv/value with body {key, value}.
|
||||
// Maintains the file index when the key matches file:<hashId>/...
|
||||
// handleKVValuePut handles PUT /api/kv/value with body {key, value}: service
|
||||
// scratch KV only (btmagnet:*, searchcov:*), kept in the cache. Merged records
|
||||
// and bookkeeping are refused — metadata is written as signed claims.
|
||||
func (s *Server) handleKVValuePut(w http.ResponseWriter, r *http.Request) {
|
||||
if !s.storage.IsConnected() {
|
||||
writeError(w, http.StatusServiceUnavailable, "storage not connected")
|
||||
@@ -401,19 +402,11 @@ func (s *Server) handleKVValuePut(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.storage.SetRawValue(req.Key, req.Value); err != nil {
|
||||
if err := s.storage.SetServiceValue(req.Key, req.Value); err != nil {
|
||||
writeError(w, http.StatusConflict, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if hashID := extractFileHashID(req.Key); hashID != "" {
|
||||
if err := s.storage.IndexAdd(hashID); err != nil {
|
||||
// Non-fatal: the value was written; index entry is best-effort.
|
||||
// Surface in the log path of writeJSON via response header.
|
||||
w.Header().Set("X-KV-Index-Warning", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, KVValueResponse{
|
||||
Key: req.Key,
|
||||
Type: "string",
|
||||
@@ -422,9 +415,7 @@ func (s *Server) handleKVValuePut(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// handleKVValueDelete handles DELETE /api/kv/value?key=...
|
||||
// When the key matches file:<hashId>/..., removes the file index entry if no
|
||||
// sibling keys remain after the delete.
|
||||
// handleKVValueDelete handles DELETE /api/kv/value?key=... (service keys only).
|
||||
func (s *Server) handleKVValueDelete(w http.ResponseWriter, r *http.Request) {
|
||||
if !s.storage.IsConnected() {
|
||||
writeError(w, http.StatusServiceUnavailable, "storage not connected")
|
||||
@@ -437,36 +428,14 @@ func (s *Server) handleKVValueDelete(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
deleted, err := s.storage.DeleteRawKey(key)
|
||||
deleted, err := s.storage.DeleteServiceValue(key)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
writeError(w, http.StatusConflict, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if deleted {
|
||||
if hashID := extractFileHashID(key); hashID != "" {
|
||||
if _, err := s.storage.IndexRemoveIfEmpty(hashID); err != nil {
|
||||
w.Header().Set("X-KV-Index-Warning", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, KVValueDeleteResponse{
|
||||
Key: key,
|
||||
Deleted: deleted,
|
||||
})
|
||||
}
|
||||
|
||||
// extractFileHashID returns the hashID for a key shaped like file:<hashId>/...
|
||||
// Returns "" when the key does not follow that convention.
|
||||
func extractFileHashID(key string) string {
|
||||
if !strings.HasPrefix(key, "file:") {
|
||||
return ""
|
||||
}
|
||||
rest := strings.TrimPrefix(key, "file:")
|
||||
slash := strings.Index(rest, "/")
|
||||
if slash <= 0 {
|
||||
return ""
|
||||
}
|
||||
return rest[:slash]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user