feat: schedule persistent archive jobs with console management
This commit is contained in:
108
internal/transport/httpserver/archive_jobs.go
Normal file
108
internal/transport/httpserver/archive_jobs.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package httpserver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.yuntuo.hk/k2safe/orbit/internal/fault"
|
||||
"git.yuntuo.hk/k2safe/orbit/internal/retention"
|
||||
core "git.yuntuo.hk/k2safe/orbit/model"
|
||||
"git.yuntuo.hk/k2safe/orbit/platform/auth"
|
||||
)
|
||||
|
||||
// RegisterConsoleArchiveJobs 注册周期归档管理;只接受管理员会话,目标目录由部署配置固定。
|
||||
func RegisterConsoleArchiveJobs(server *http.Server, consoleAuth RetentionConsoleAuth, store retention.SchedulerStore, storage core.ID) {
|
||||
if server == nil || consoleAuth == nil || store == nil {
|
||||
return
|
||||
}
|
||||
mux, ok := server.Handler.(*http.ServeMux)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
parent := mux
|
||||
mux = http.NewServeMux()
|
||||
for _, method := range []string{"GET", "PUT", "POST"} {
|
||||
parent.Handle(method+" /console/archive/", http.NewCrossOriginProtection().Handler(mux))
|
||||
}
|
||||
check := func(w http.ResponseWriter, r *http.Request) (auth.Token, bool) {
|
||||
t, ok := consoleCookieToken(r)
|
||||
if !ok || consoleAuth.ValidateSession(r.Context(), t) != nil {
|
||||
writeError(w, "", fault.Unauthorized)
|
||||
return auth.Token{}, false
|
||||
}
|
||||
return t, true
|
||||
}
|
||||
key := func(w http.ResponseWriter, r *http.Request) (string, bool) {
|
||||
keys := r.Header.Values("Idempotency-Key")
|
||||
if len(keys) != 1 {
|
||||
writeError(w, "", fault.Invalid("exactly one Idempotency-Key is required"))
|
||||
return "", false
|
||||
}
|
||||
return keys[0], true
|
||||
}
|
||||
mux.HandleFunc("GET /console/archive/plans", func(w http.ResponseWriter, r *http.Request) {
|
||||
t, ok := check(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
items, err := store.ListArchivePlans(r.Context(), t)
|
||||
if err != nil {
|
||||
writeError(w, "", err)
|
||||
return
|
||||
}
|
||||
writeConsoleJSON(w, 200, map[string]any{"data": map[string]any{"items": items, "executor_configured": storage != "", "storage_id": string(storage)}})
|
||||
})
|
||||
mux.HandleFunc("PUT /console/archive/plans/{kind}", func(w http.ResponseWriter, r *http.Request) {
|
||||
t, ok := check(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
k, ok := key(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var in retention.PlanInput
|
||||
if err := decodeBody(r, &in); err != nil {
|
||||
writeError(w, "", err)
|
||||
return
|
||||
}
|
||||
out, err := store.SaveArchivePlan(r.Context(), t, k, r.PathValue("kind"), storage, in)
|
||||
if err != nil {
|
||||
writeError(w, "", err)
|
||||
return
|
||||
}
|
||||
writeConsoleJSON(w, 200, map[string]any{"data": out})
|
||||
})
|
||||
mux.HandleFunc("GET /console/archive/jobs", func(w http.ResponseWriter, r *http.Request) {
|
||||
t, ok := check(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
out, err := store.ListArchiveJobs(r.Context(), t, r.URL.Query().Get("before"))
|
||||
if err != nil {
|
||||
writeError(w, "", err)
|
||||
return
|
||||
}
|
||||
writeConsoleJSON(w, 200, map[string]any{"data": out})
|
||||
})
|
||||
mux.HandleFunc("POST /console/archive/jobs/{id}/actions", func(w http.ResponseWriter, r *http.Request) {
|
||||
t, ok := check(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
k, ok := key(w, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var in retention.JobActionInput
|
||||
if err := decodeBody(r, &in); err != nil {
|
||||
writeError(w, "", err)
|
||||
return
|
||||
}
|
||||
out, err := store.ActArchiveJob(r.Context(), t, core.ID(r.PathValue("id")), k, in)
|
||||
if err != nil {
|
||||
writeError(w, "", err)
|
||||
return
|
||||
}
|
||||
writeConsoleJSON(w, 200, map[string]any{"data": out})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user