package httpserver import ( "context" "net/http" core "git.yuntuo.hk/k2safe/orbit/model" "git.yuntuo.hk/k2safe/orbit/platform/auth" "git.yuntuo.hk/k2safe/orbit/weave/control" "git.yuntuo.hk/k2safe/orbit/weave/instance" "git.yuntuo.hk/k2safe/orbit/weave/recovery" "git.yuntuo.hk/k2safe/orbit/weave/signal" ) // RegisterWorkflows 只适配协议,实际授权、并发版本、原键回执及审计由事务服务校验。 func RegisterWorkflows(server *http.Server, instances *instance.Service, controls *control.Service, signals *signal.Service, reviews *recovery.Service) { mux := server.Handler.(*http.ServeMux) registerWorkflowHistory(mux, instances, signals) registerWorkflowQuery(mux, instances) registerWorkflowEvents(mux, instances) mux.HandleFunc("POST /v1/workflows", wrap(func(r *http.Request, t auth.Token) (any, int, error) { if _, err := historyQuery(r, false); err != nil { return nil, 0, err } var in instance.StartInput if err := decodeBody(r, &in); err != nil { return nil, 0, err } key, err := idempotencyKey(r) if err != nil { return nil, 0, err } out, err := instances.Start(r.Context(), t, key, in) return out, createdStatus(out.Deduplicated), err })) mux.HandleFunc("GET /v1/workflows/{id}", wrap(func(r *http.Request, t auth.Token) (any, int, error) { if _, err := historyQuery(r, false); err != nil { return nil, 0, err } out, err := instances.Get(r.Context(), t, core.ID(r.PathValue("id"))) return out, 200, err })) mux.HandleFunc("GET /v1/workflows/{id}/steps", wrap(func(r *http.Request, t auth.Token) (any, int, error) { if _, err := historyQuery(r, false); err != nil { return nil, 0, err } out, err := instances.Steps(r.Context(), t, core.ID(r.PathValue("id"))) return out, 200, err })) mux.HandleFunc("GET /v1/workflows/{id}/steps/{key}", wrap(func(r *http.Request, t auth.Token) (any, int, error) { if _, err := historyQuery(r, false); err != nil { return nil, 0, err } out, err := instances.Step(r.Context(), t, core.ID(r.PathValue("id")), r.PathValue("key")) return out, 200, err })) mux.HandleFunc("GET /v1/workflows/{id}/operations", wrap(func(r *http.Request, t auth.Token) (any, int, error) { in, err := historyQuery(r, true) if err != nil { return nil, 0, err } out, err := instances.ListOperations(r.Context(), t, core.ID(r.PathValue("id")), in) return out, 200, err })) mux.HandleFunc("GET /v1/workflows/{id}/operations/{operation}", wrap(func(r *http.Request, t auth.Token) (any, int, error) { if _, err := historyQuery(r, false); err != nil { return nil, 0, err } out, err := instances.GetOperation(r.Context(), t, core.ID(r.PathValue("id")), core.ID(r.PathValue("operation"))) return out, 200, err })) mux.HandleFunc("POST /v1/workflows/{id}/control", workflowMutation(controls.Apply, func(control.Result) int { return 200 })) mux.HandleFunc("POST /v1/workflows/{id}/signals", workflowMutation(signals.Send, func(v signal.Result) int { return createdStatus(v.Deduplicated) })) mux.HandleFunc("GET /v1/workflows/{id}/signals/{signal}", wrap(func(r *http.Request, t auth.Token) (any, int, error) { if _, err := historyQuery(r, false); err != nil { return nil, 0, err } out, err := signals.Get(r.Context(), t, core.ID(r.PathValue("id")), core.ID(r.PathValue("signal"))) return out, 200, err })) mux.HandleFunc("POST /v1/workflows/{id}/recovery/task-review", workflowMutation(reviews.ReviewTask, recoveryStatus)) mux.HandleFunc("POST /v1/workflows/{id}/recovery/step-resolve", workflowMutation(reviews.ResolveStep, recoveryStatus)) mux.HandleFunc("POST /v1/workflows/{id}/recovery/continue", workflowMutation(reviews.Continue, recoveryStatus)) mux.HandleFunc("POST /v1/workflows/{id}/recovery/step-retry", workflowMutation(reviews.RetryStep, recoveryStatus)) mux.HandleFunc("POST /v1/workflows/{id}/recovery/poll-continue", workflowMutation(reviews.ContinuePoll, recoveryStatus)) mux.HandleFunc("POST /v1/workflows/{id}/recovery/wait-rearm", workflowMutation(reviews.RearmWait, recoveryStatus)) } func recoveryStatus(recovery.Result) int { return 200 } func workflowMutation[I, O any](call func(context.Context, auth.Token, core.ID, string, I) (O, error), status func(O) int) http.HandlerFunc { return wrap(func(r *http.Request, t auth.Token) (any, int, error) { if _, err := historyQuery(r, false); err != nil { return nil, 0, err } var in I if err := decodeBody(r, &in); err != nil { return nil, 0, err } key, err := idempotencyKey(r) if err != nil { return nil, 0, err } out, err := call(r.Context(), t, core.ID(r.PathValue("id")), key, in) return out, status(out), err }) }