feat(server/desktop): ingest desktop account health reports

Add a POST /desktop/accounts/health-reports endpoint that buffers reports in
Redis, dedupes via signature, and publishes change events to a new
desktop.account.health RabbitMQ queue. A sink worker drains the queue, and
the account service overlays runtime health onto database health when serving
desktop accounts. Publish job creation now consults runtime health so a stale
DB row no longer blocks publishing once the desktop client reports it healthy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-27 21:33:36 +08:00
parent 94f185c3a1
commit 051976e4a9
10 changed files with 647 additions and 51 deletions
@@ -23,6 +23,7 @@ func NewDesktopAccountHandler(a *bootstrap.App) *DesktopAccountHandler {
repository.NewDesktopAccountRepository(a.DB),
repository.NewDesktopClientRepository(a.DB),
a.Redis,
a.RabbitMQ,
),
}
}
@@ -65,6 +66,21 @@ func (h *DesktopAccountHandler) Upsert(c *gin.Context) {
response.SuccessWithStatus(c, 201, data)
}
func (h *DesktopAccountHandler) ReportHealth(c *gin.Context) {
var req app.ReportDesktopAccountHealthRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, response.ErrBadRequest(40001, "invalid_params", err.Error()))
return
}
data, err := h.svc.ReportHealth(c.Request.Context(), MustDesktopClient(c.Request.Context()), req)
if err != nil {
response.Error(c, err)
return
}
response.Success(c, data)
}
func (h *DesktopAccountHandler) Patch(c *gin.Context) {
desktopID, err := uuid.Parse(c.Param("id"))
if err != nil {
@@ -48,6 +48,7 @@ func RegisterRoutes(app *bootstrap.App) {
desktopAuth.GET("/content/articles/:id", desktopContentHandler.Article)
desktopAuth.GET("/content/assets/:token", publicAssets.ServeDesktop)
desktopAuth.GET("/publish-tasks", desktopTaskHandler.ListPublish)
desktopAuth.POST("/accounts/health-reports", desktopAccountHandler.ReportHealth)
desktopAuth.POST("/accounts", desktopAccountHandler.Upsert)
desktopAuth.PATCH("/accounts/:id", desktopAccountHandler.Patch)
desktopAuth.DELETE("/accounts/:id", desktopAccountHandler.Delete)