server add gives another machine this llmgw, a certificate, the configuration and store address, lets it into the store through Patroni, and starts it; --vip keeps a floating address on the leader with keepalived, following a new /leader endpoint. Nodes learn every control plane from the leader and notice a dead one by HTTP/2 ping instead of after the kernel's fifteen minutes. The setup, console, node and init screens are drawn full screen in one frame: title bar, sidebar, bordered panel, key bar, dialogs. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
45 lines
1.3 KiB
Go
45 lines
1.3 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"time"
|
|
)
|
|
|
|
// ControlPlane is one control plane agents may dial.
|
|
type ControlPlane struct {
|
|
// URL is what an agent dials: https://10.0.0.150:7443.
|
|
URL string
|
|
Name string
|
|
AddedAt time.Time
|
|
}
|
|
|
|
// ControlPlanes lists them, oldest first: the first is the one agents try
|
|
// first.
|
|
func (s *DB) ControlPlanes(ctx context.Context) ([]ControlPlane, error) {
|
|
return queryAll(ctx, s.db, `SELECT url, name, added_at FROM control_planes ORDER BY added_at, url`, nil,
|
|
func(rows *sql.Rows) (ControlPlane, error) {
|
|
var c ControlPlane
|
|
var at int64
|
|
err := rows.Scan(&c.URL, &c.Name, &at)
|
|
c.AddedAt = fromMillis(at)
|
|
return c, err
|
|
})
|
|
}
|
|
|
|
// PutControlPlane records one, keeping when it was first added.
|
|
func (s *DB) PutControlPlane(ctx context.Context, c ControlPlane) error {
|
|
if c.AddedAt.IsZero() {
|
|
c.AddedAt = time.Now()
|
|
}
|
|
_, err := s.db.ExecContext(ctx, `INSERT INTO control_planes (url, name, added_at) VALUES (?, ?, ?)
|
|
ON CONFLICT (url) DO UPDATE SET name = excluded.name`, c.URL, c.Name, millis(c.AddedAt))
|
|
return err
|
|
}
|
|
|
|
// RemoveControlPlane forgets one.
|
|
func (s *DB) RemoveControlPlane(ctx context.Context, url string) error {
|
|
_, err := s.db.ExecContext(ctx, `DELETE FROM control_planes WHERE url = ?`, url)
|
|
return err
|
|
}
|