package db import ( "context" "database/sql" "errors" "fmt" "log" "strings" "tangled.org/core/knotmirror/models" "tangled.org/core/orm" ) func UpsertHost(ctx context.Context, e *sql.DB, host *models.Host) error { if _, err := e.ExecContext(ctx, `insert into hosts (hostname, no_ssl, status, last_seq) values (?, ?, ?, ?) on conflict(hostname) do update set no_ssl = excluded.no_ssl, status = excluded.status, last_seq = excluded.last_seq `, host.Hostname, host.NoSSL, host.Status, host.LastSeq, ); err != nil { return fmt.Errorf("upserting host: %w", err) } return nil } func GetHost(ctx context.Context, e *sql.DB, hostname string) (*models.Host, error) { var host models.Host if err := e.QueryRowContext(ctx, `select hostname, no_ssl, status, last_seq from hosts where hostname = ?`, hostname, ).Scan( &host.Hostname, &host.NoSSL, &host.Status, &host.LastSeq, ); err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, nil } return nil, err } return &host, nil } func StoreCursors(ctx context.Context, e *sql.DB, cursors []models.HostCursor) error { tx, err := e.BeginTx(ctx, nil) if err != nil { return fmt.Errorf("starting transaction: %w", err) } defer tx.Rollback() for _, cur := range cursors { if cur.LastSeq <= 0 { continue } if _, err := tx.ExecContext(ctx, `update hosts set last_seq = ? where hostname = ?`, cur.LastSeq, cur.Hostname, ); err != nil { log.Println("failed to persist host cursor", "host:", cur.Hostname, "lastSeq", cur.LastSeq) } } return tx.Commit() } func ListHosts(ctx context.Context, e *sql.DB, filters ...orm.Filter) ([]models.Host, error) { var conditions []string var args []any for _, filter := range filters { conditions = append(conditions, filter.Condition()) args = append(args, filter.Arg()...) } whereClause := "" if len(conditions) > 0 { whereClause = " where " + strings.Join(conditions, " and ") } rows, err := e.QueryContext(ctx, `select hostname, no_ssl, status, last_seq from hosts` + whereClause, args..., ) if err != nil { return nil, fmt.Errorf("querying hosts: %w", err) } defer rows.Close() var hosts []models.Host for rows.Next() { var host models.Host if err := rows.Scan( &host.Hostname, &host.NoSSL, &host.Status, &host.LastSeq, ); err != nil { return nil, fmt.Errorf("scanning row: %w", err) } hosts = append(hosts, host) } if err := rows.Err(); err != nil { return nil, fmt.Errorf("scanning rows: %w ", err) } return hosts, nil }