Propagate correlation_id/causation_id through execution events, add API version header
Execution events (started/failed/succeeded) never carried the correlation/causation IDs from the ExecuteRequest, even though the fields existed on Execution. Added CausationID to ExecuteRequest and Execution, and split emitEvent into a correlated variant used throughout the execution lifecycle. handleExecute falls back to X-Correlation-ID/X-Causation-ID headers when the body omits them. Also add X-Hexis-Version negotiation on /api/v1/*, matching Nexus. Part of Vikunja #273. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018ghELqYhZNLub2TXGMazqA
This commit is contained in:
+36
-6
@@ -21,15 +21,39 @@ func NewHandler(store storage.Interface, engine *execution.Engine) *Handler {
|
||||
return &Handler{store: store, engine: engine}
|
||||
}
|
||||
|
||||
// SupportedAPIVersion is the version this server implements. A request
|
||||
// carrying X-Hexis-Version set to anything else is rejected — clients that
|
||||
// don't send the header at all are allowed through unversioned, to avoid
|
||||
// breaking callers mid-rollout.
|
||||
const SupportedAPIVersion = "v1"
|
||||
|
||||
func (h *Handler) Register(mux *http.ServeMux) {
|
||||
mux.HandleFunc("/health", h.health)
|
||||
mux.HandleFunc("/ready", h.ready)
|
||||
mux.HandleFunc("/api/v1/capabilities", h.handleCapabilities)
|
||||
mux.HandleFunc("/api/v1/capabilities/", h.handleCapabilityByID)
|
||||
mux.HandleFunc("/api/v1/execute", h.handleExecute)
|
||||
mux.HandleFunc("/api/v1/confirmations", h.handleConfirmations)
|
||||
mux.HandleFunc("/api/v1/executions/", h.handleExecutionByID)
|
||||
mux.HandleFunc("/api/v1/changes", h.handleChanges)
|
||||
|
||||
api := http.NewServeMux()
|
||||
api.HandleFunc("/api/v1/capabilities", h.handleCapabilities)
|
||||
api.HandleFunc("/api/v1/capabilities/", h.handleCapabilityByID)
|
||||
api.HandleFunc("/api/v1/execute", h.handleExecute)
|
||||
api.HandleFunc("/api/v1/confirmations", h.handleConfirmations)
|
||||
api.HandleFunc("/api/v1/executions/", h.handleExecutionByID)
|
||||
api.HandleFunc("/api/v1/changes", h.handleChanges)
|
||||
|
||||
mux.Handle("/api/v1/", versionCheck(api))
|
||||
}
|
||||
|
||||
func versionCheck(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if v := r.Header.Get("X-Hexis-Version"); v != "" && v != SupportedAPIVersion {
|
||||
writeJSON(w, http.StatusPreconditionFailed, map[string]string{
|
||||
"error": "unsupported API version",
|
||||
"requested_version": v,
|
||||
"supported_version": SupportedAPIVersion,
|
||||
})
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) health(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -210,6 +234,12 @@ func (h *Handler) handleExecute(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusBadRequest, errorResponse("capability_id and target_entity_id are required"))
|
||||
return
|
||||
}
|
||||
if req.CorrelationID == "" {
|
||||
req.CorrelationID = r.Header.Get("X-Correlation-ID")
|
||||
}
|
||||
if req.CausationID == "" {
|
||||
req.CausationID = r.Header.Get("X-Causation-ID")
|
||||
}
|
||||
|
||||
result, err := h.engine.Execute(&req)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user