mirror of
https://github.com/Dvorinka/Primora.git
synced 2026-10-28 15:51:23 +00:00
feat: HA scheduler leadership + templated email log
HA scheduler: the job scheduler and alert evaluator hold session-scoped PostgreSQL advisory locks on pinned pool connections — replicas scan for due work exactly once, failover verified live with two replicas. Manual and hook-triggered runs stay available on any replica. Email surface: mailer renders registered templates (invitation); every send is logged to core.email_log with status and error text. New GET /projects/:id/emails endpoint; Members page shows an Email log card. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
45a1621909
commit
f747b33b46
24 files changed
+669
-16
No files matched your search
@@ -83,6 +83,7 @@ func (h *HTTPHandler) Register(router *gin.Engine) {
|
||||
api.GET("/projects/:projectID/inbound-hooks", h.listInboundHooks)
|
||||
api.POST("/projects/:projectID/inbound-hooks", h.createInboundHook)
|
||||
api.DELETE("/projects/:projectID/inbound-hooks/:hookID", h.deleteInboundHook)
|
||||
api.GET("/projects/:projectID/emails", h.listEmailLog)
|
||||
api.GET("/projects/:projectID/events", h.listEvents)
|
||||
api.GET("/projects/:projectID/issues", h.listIssues)
|
||||
api.GET("/projects/:projectID/components", h.listComponents)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -80,6 +81,25 @@ func (h *HTTPHandler) deleteInboundHook(c *gin.Context) {
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func (h *HTTPHandler) listEmailLog(c *gin.Context) {
|
||||
actor, projectID, ok := h.actorAndProject(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var limit int64
|
||||
if raw := c.Query("limit"); raw != "" {
|
||||
if n, err := strconv.ParseInt(raw, 10, 64); err == nil {
|
||||
limit = n
|
||||
}
|
||||
}
|
||||
result, err := h.Platform.ListEmailLog(c.Request.Context(), actor, projectID, limit)
|
||||
if err != nil {
|
||||
h.handleError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": result})
|
||||
}
|
||||
|
||||
// receiveInboundHook is the public ingest endpoint — the URL token is the
|
||||
// credential, so no actor is required.
|
||||
func (h *HTTPHandler) receiveInboundHook(c *gin.Context) {
|
||||
|
||||
Reference in new issue
Block a user