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
@@ -0,0 +1,91 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.29.0
|
||||
// source: email_log.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const insertEmailLog = `-- name: InsertEmailLog :one
|
||||
INSERT INTO core.email_log (project_id, template, to_email, subject, status, error)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING id, project_id, template, to_email, subject, status, error, created_at
|
||||
`
|
||||
|
||||
type InsertEmailLogParams struct {
|
||||
ProjectID pgtype.UUID `json:"project_id"`
|
||||
Template string `json:"template"`
|
||||
ToEmail string `json:"to_email"`
|
||||
Subject string `json:"subject"`
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertEmailLog(ctx context.Context, arg InsertEmailLogParams) (CoreEmailLog, error) {
|
||||
row := q.db.QueryRow(ctx, insertEmailLog,
|
||||
arg.ProjectID,
|
||||
arg.Template,
|
||||
arg.ToEmail,
|
||||
arg.Subject,
|
||||
arg.Status,
|
||||
arg.Error,
|
||||
)
|
||||
var i CoreEmailLog
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ProjectID,
|
||||
&i.Template,
|
||||
&i.ToEmail,
|
||||
&i.Subject,
|
||||
&i.Status,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listEmailLog = `-- name: ListEmailLog :many
|
||||
SELECT id, project_id, template, to_email, subject, status, error, created_at FROM core.email_log
|
||||
WHERE project_id = $1
|
||||
ORDER BY created_at DESC
|
||||
LIMIT $2
|
||||
`
|
||||
|
||||
type ListEmailLogParams struct {
|
||||
ProjectID pgtype.UUID `json:"project_id"`
|
||||
Limit int32 `json:"limit"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListEmailLog(ctx context.Context, arg ListEmailLogParams) ([]CoreEmailLog, error) {
|
||||
rows, err := q.db.Query(ctx, listEmailLog, arg.ProjectID, arg.Limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []CoreEmailLog
|
||||
for rows.Next() {
|
||||
var i CoreEmailLog
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.ProjectID,
|
||||
&i.Template,
|
||||
&i.ToEmail,
|
||||
&i.Subject,
|
||||
&i.Status,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
@@ -243,6 +243,17 @@ type CoreDocument struct {
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type CoreEmailLog struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
ProjectID pgtype.UUID `json:"project_id"`
|
||||
Template string `json:"template"`
|
||||
ToEmail string `json:"to_email"`
|
||||
Subject string `json:"subject"`
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
}
|
||||
|
||||
type CoreEvent struct {
|
||||
ID int64 `json:"id"`
|
||||
ProjectID uuid.UUID `json:"project_id"`
|
||||
|
||||
@@ -84,6 +84,7 @@ type Querier interface {
|
||||
GetWebhookByID(ctx context.Context, id uuid.UUID) (CoreWebhook, error)
|
||||
GetWebhookDeliveryByID(ctx context.Context, id uuid.UUID) (CoreWebhookDelivery, error)
|
||||
HasFingerprintSeen(ctx context.Context, arg HasFingerprintSeenParams) (bool, error)
|
||||
InsertEmailLog(ctx context.Context, arg InsertEmailLogParams) (CoreEmailLog, error)
|
||||
InsertEvent(ctx context.Context, arg InsertEventParams) (CoreEvent, error)
|
||||
InsertScheduledJobRun(ctx context.Context, arg InsertScheduledJobRunParams) (CoreScheduledJobRun, error)
|
||||
InsertWebhookDelivery(ctx context.Context, arg InsertWebhookDeliveryParams) (CoreWebhookDelivery, error)
|
||||
@@ -100,6 +101,7 @@ type Querier interface {
|
||||
ListDBConnections(ctx context.Context, projectID uuid.UUID) ([]CoreDbConnection, error)
|
||||
ListDocuments(ctx context.Context, arg ListDocumentsParams) ([]CoreDocument, error)
|
||||
ListDueScheduledJobs(ctx context.Context, nextRunAt pgtype.Timestamptz) ([]CoreScheduledJob, error)
|
||||
ListEmailLog(ctx context.Context, arg ListEmailLogParams) ([]CoreEmailLog, error)
|
||||
ListEnabledAlertRules(ctx context.Context) ([]CoreAlertRule, error)
|
||||
ListErrorGroups(ctx context.Context, arg ListErrorGroupsParams) ([]ListErrorGroupsRow, error)
|
||||
ListEvents(ctx context.Context, arg ListEventsParams) ([]ListEventsRow, error)
|
||||
|
||||
Reference in new issue
Block a user