Public source validation / validate (push) Failing after 3m8s
71 lines
2.5 KiB
Go
71 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/itworx/pulse/internal/agentstore"
|
|
"github.com/itworx/pulse/internal/database"
|
|
"github.com/itworx/pulse/internal/runtimeconfig"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
const (
|
|
// storeConnectTimeout bounds the start-up reachability check. The healthcheck
|
|
// contract wants the first heartbeat written after the database is reachable, so
|
|
// this must stay far below the 45 second staleness threshold.
|
|
storeConnectTimeout = 5 * time.Second
|
|
// agentPoolMaxConns keeps the agent's footprint on the shared database small: it
|
|
// issues one small write per capability per interval and never reads.
|
|
agentPoolMaxConns = 2
|
|
)
|
|
|
|
// errStoreNotLinked is returned by every write while no snapshot store implementation
|
|
// is compiled into this binary. It is deliberately an error on the write path rather
|
|
// than a silent drop: the reader turns a missing snapshot into Unknown, and the agent
|
|
// log states plainly why nothing arrives.
|
|
var errStoreNotLinked = errors.New("no agent snapshot store is linked into this build")
|
|
|
|
// openStore connects to PostgreSQL and returns the narrow Writer the agent publishes
|
|
// through, plus a close function.
|
|
//
|
|
// The agent depends on the agentstore.Writer interface only; the concrete PostgreSQL
|
|
// store owns migration 0016 and the agent_snapshots table.
|
|
func openStore(ctx context.Context, config runtimeconfig.AgentConfig) (agentstore.Writer, func(), error) {
|
|
pool, err := database.NewPool(ctx, database.Config{
|
|
URL: config.DatabaseURL,
|
|
MaxConns: agentPoolMaxConns,
|
|
MinConns: 1,
|
|
})
|
|
if err != nil {
|
|
// Never wrap the URL itself into the error: it carries the database password.
|
|
return nil, nil, errors.New("agent database pool could not be created")
|
|
}
|
|
reachable, cancel := context.WithTimeout(ctx, storeConnectTimeout)
|
|
defer cancel()
|
|
if err := database.Ping(reachable, pool); err != nil {
|
|
pool.Close()
|
|
return nil, nil, fmt.Errorf("agent database is unreachable: %w", err)
|
|
}
|
|
writer, err := newSnapshotWriter(pool)
|
|
if err != nil {
|
|
pool.Close()
|
|
return nil, nil, err
|
|
}
|
|
return writer, pool.Close, nil
|
|
}
|
|
|
|
// newSnapshotWriter builds the store the agent writes through. A nil pool would make
|
|
// every publish fail silently at the driver, so it is refused here instead: the agent
|
|
// must either have a real store or fail to start.
|
|
func newSnapshotWriter(pool *pgxpool.Pool) (agentstore.Writer, error) {
|
|
if pool == nil {
|
|
return nil, errStoreNotLinked
|
|
}
|
|
return agentstore.PostgresStore{Pool: pool}, nil
|
|
}
|
|
|
|
var _ agentstore.Writer = agentstore.PostgresStore{}
|