feat(delivery): stream task updates with SSE

This commit is contained in:
mac
2026-07-28 09:55:04 +08:00
parent 7b4b9d2ee7
commit 5a260c443f
5 changed files with 168 additions and 4 deletions
+51
View File
@@ -2,7 +2,9 @@ package handler
import (
"crypto/subtle"
"encoding/json"
"errors"
"fmt"
"net/http"
"strconv"
"strings"
@@ -167,6 +169,55 @@ func (h *DeliveryHandler) Get(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"task": task, "events": events})
}
func (h *DeliveryHandler) Stream(c *gin.Context) {
claims, ok := CurrentClaims(c)
if !ok {
c.JSON(http.StatusUnauthorized, gin.H{"error": "missing current user"})
return
}
taskID := c.Param("id")
task, events, err := h.service.GetTask(c.Request.Context(), taskID, claims.UserID, claims.IsAdmin)
if errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "task not found"})
return
}
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
updates, cancel := h.service.SubscribeTask(taskID)
defer cancel()
c.Header("Content-Type", "text/event-stream")
c.Header("Cache-Control", "no-cache")
c.Header("Connection", "keep-alive")
c.Header("X-Accel-Buffering", "no")
c.Status(http.StatusOK)
writeSSE(c.Writer, "snapshot", service.DeliveryTaskSnapshot{Task: task, Events: events})
c.Writer.Flush()
for {
select {
case <-c.Request.Context().Done():
return
case snapshot, ok := <-updates:
if !ok {
return
}
writeSSE(c.Writer, "snapshot", snapshot)
c.Writer.Flush()
}
}
}
func writeSSE(w http.ResponseWriter, event string, payload any) {
raw, err := json.Marshal(payload)
if err != nil {
return
}
_, _ = fmt.Fprintf(w, "event: %s\ndata: %s\n\n", event, raw)
}
// Cancel 取消交付任务
// @Summary 取消交付任务
// @Description 取消一个正在执行或等待中的交付任务