CI / changes (push) Successful in 9s
CI / commitlint (push) Has been skipped
CI / openapi (push) Successful in 26s
CI / web (push) Successful in 33s
CI / go (push) Successful in 2m11s
CI / bird2 (push) Successful in 16s
CI / release (push) Successful in 3m27s
Added PostgreSQL monitoring and maintenance capabilities to the API, including new endpoints for instance-level metrics, maintenance operations, and job scheduling. Updated the HTTP API to support PostgreSQL monitoring routes and integrated a background scheduler for metrics collection. Enhanced the CLI with database commands for maintenance tasks. Updated documentation to reflect these changes.
97 lines
2.4 KiB
Go
97 lines
2.4 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"evobgp/internal/db"
|
|
"evobgp/internal/httpclient"
|
|
"evobgp/internal/jobs"
|
|
"evobgp/internal/observability"
|
|
"evobgp/internal/repository"
|
|
"evobgp/internal/store"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
// NewCDNHTTPClient returns the shared HTTP client for CDN and preview fetches (PERF-02 / ERR-03).
|
|
func NewCDNHTTPClient() *http.Client {
|
|
return httpclient.New(httpclient.DefaultTimeout)
|
|
}
|
|
|
|
// BootstrapWorkers opens the same store.Backend and jobs.Registry as New (without HTTP or bundle keys).
|
|
// Used by standalone worker binaries (scheduler, ingest, …) that share PostgreSQL with the API.
|
|
func BootstrapWorkers(ctx context.Context, opts Options) (store.Backend, *jobs.Registry, *pgxpool.Pool, error) {
|
|
ctx, cancel := context.WithTimeout(ctx, 60*time.Second)
|
|
defer cancel()
|
|
|
|
var backend store.Backend
|
|
var pool *pgxpool.Pool
|
|
|
|
if u := strings.TrimSpace(opts.DatabaseURL); u != "" {
|
|
p, err := db.OpenPostgresPool(ctx, u)
|
|
if err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
pool = p
|
|
pgbe, err := repository.NewPostgres(ctx, p, opts.SeedDemo)
|
|
if err != nil {
|
|
pool.Close()
|
|
return nil, nil, nil, err
|
|
}
|
|
backend = pgbe
|
|
} else {
|
|
mem := store.NewMemory()
|
|
if opts.SeedDemo {
|
|
mem.SeedDemo()
|
|
}
|
|
backend = mem
|
|
}
|
|
|
|
cdnHTTP := NewCDNHTTPClient()
|
|
wk := &jobs.Worker{Store: backend, PgPool: pool, HTTPClient: cdnHTTP}
|
|
reg := jobs.NewRegistry(wk.Process)
|
|
wk.Registry = reg
|
|
if pool != nil {
|
|
audit := repository.NewJobAuditWriter(pool)
|
|
jobMeta := func(j *jobs.Job) map[string]any {
|
|
if j == nil {
|
|
return nil
|
|
}
|
|
st := j.Snapshot()
|
|
meta, _ := st["meta"].(map[string]any)
|
|
return meta
|
|
}
|
|
reg.SetPersistHooks(
|
|
func(j *jobs.Job) {
|
|
if j == nil {
|
|
return
|
|
}
|
|
audit.UpsertQueued(context.Background(), j.TenantID, j.ID, j.Kind, j.IdempotencyKey, j.ModuleID, jobMeta(j))
|
|
},
|
|
func(j *jobs.Job) {
|
|
if j == nil {
|
|
return
|
|
}
|
|
audit.UpsertRunning(context.Background(), j.TenantID, j.ID, j.Kind, j.IdempotencyKey, jobMeta(j))
|
|
},
|
|
func(j *jobs.Job) {
|
|
if j == nil {
|
|
return
|
|
}
|
|
st := j.Snapshot()
|
|
status, _ := st["status"].(string)
|
|
var errMsg *string
|
|
if e, ok := st["error"].(string); ok && e != "" {
|
|
errMsg = &e
|
|
}
|
|
audit.MarkTerminal(context.Background(), j.TenantID, j.ID, status, errMsg, time.Now().UTC())
|
|
},
|
|
)
|
|
}
|
|
observability.RegisterStoreBackend(backend)
|
|
return backend, reg, pool, nil
|
|
}
|