Files
Assistant/adapters/postgres/capability_repository.go
2026-08-16 15:22:49 +03:00

59 lines
2.6 KiB
Go

package postgres
import (
"context"
"errors"
"fmt"
"git.cin.su/m/Assistant/contracts/capability"
"github.com/jackc/pgx/v5/pgxpool"
)
var ErrCapabilityHealthNotFound = errors.New("capability health not found")
type CapabilityRepository struct{ pool *pgxpool.Pool }
func OpenCapability(ctx context.Context, config ContinuityConfig) (*CapabilityRepository, error) {
dsn := fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s", config.Host, config.Port, config.Database, config.User, config.Password)
pool, err := pgxpool.New(ctx, dsn)
if err != nil {
return nil, err
}
return &CapabilityRepository{pool: pool}, nil
}
func (r *CapabilityRepository) Close() { r.pool.Close() }
func (r *CapabilityRepository) SaveHealth(ctx context.Context, health capability.Health) error {
_, err := r.pool.Exec(ctx, `INSERT INTO capability.health (capability_id, state, reason, revision, semantic_version, observed_at_unix_millis) VALUES ($1,$2,$3,$4,$5,$6) ON CONFLICT (capability_id) DO UPDATE SET state=EXCLUDED.state, reason=EXCLUDED.reason, revision=EXCLUDED.revision, semantic_version=EXCLUDED.semantic_version, observed_at_unix_millis=EXCLUDED.observed_at_unix_millis WHERE capability.health.revision < EXCLUDED.revision`, health.CapabilityID, health.State, health.Reason, health.Revision, health.SemanticVersion, health.ObservedAtUnixMillis)
return err
}
func (r *CapabilityRepository) LoadHealth(ctx context.Context, id capability.CapabilityID) (capability.Health, error) {
var health capability.Health
err := r.pool.QueryRow(ctx, `SELECT capability_id, state, reason, revision, semantic_version, observed_at_unix_millis FROM capability.health WHERE capability_id=$1`, id).Scan(&health.CapabilityID, &health.State, &health.Reason, &health.Revision, &health.SemanticVersion, &health.ObservedAtUnixMillis)
if err != nil {
return capability.Health{}, fmt.Errorf("load capability health: %w", err)
}
return health, nil
}
func (r *CapabilityRepository) RebuildHealthProjection(ctx context.Context) (int64, error) {
tx, err := r.pool.Begin(ctx)
if err != nil {
return 0, err
}
defer tx.Rollback(ctx)
if _, err = tx.Exec(ctx, `DELETE FROM capability.health_projection`); err != nil {
return 0, err
}
result, err := tx.Exec(ctx, `INSERT INTO capability.health_projection (capability_id, state, reason, revision, semantic_version, observed_at_unix_millis) SELECT capability_id, state, reason, revision, semantic_version, observed_at_unix_millis FROM capability.health`)
if err != nil {
return 0, err
}
if err = tx.Commit(ctx); err != nil {
return 0, err
}
return result.RowsAffected(), nil
}