refactor: move http api to a new transport layer
This commit is contained in:
parent
476c4b056f
commit
0448f66ab2
41 changed files with 822 additions and 390 deletions
|
|
@ -4,23 +4,24 @@ import (
|
|||
"context"
|
||||
"sync"
|
||||
|
||||
"git.wzray.com/homelab/hivemind/internal/app"
|
||||
"git.wzray.com/homelab/hivemind/internal/config"
|
||||
"git.wzray.com/homelab/hivemind/internal/roles"
|
||||
"git.wzray.com/homelab/hivemind/internal/state"
|
||||
"git.wzray.com/homelab/hivemind/internal/transport"
|
||||
"git.wzray.com/homelab/hivemind/internal/transport/master"
|
||||
"git.wzray.com/homelab/hivemind/internal/types"
|
||||
"git.wzray.com/homelab/hivemind/internal/web/client"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type Role struct {
|
||||
state *state.RuntimeState
|
||||
state *app.State
|
||||
config config.MasterConfig
|
||||
tasksGroup sync.WaitGroup
|
||||
observer *observer
|
||||
roles.BaseRole
|
||||
}
|
||||
|
||||
func New(state *state.RuntimeState, config config.MasterConfig) *Role {
|
||||
func New(state *app.State, config config.MasterConfig) *Role {
|
||||
return &Role{
|
||||
state: state,
|
||||
config: config,
|
||||
|
|
@ -50,13 +51,34 @@ func (r *Role) OnShutdown() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *Role) notify(path types.Path, v any) {
|
||||
for _, n := range r.state.Registry.ByRole(types.MasterRole) {
|
||||
addr := n.Endpoint
|
||||
r.tasksGroup.Go(func() {
|
||||
client.Post[any](addr, path, v)
|
||||
})
|
||||
}
|
||||
func (c *Role) RegisterHandlers(r transport.Registrator) {
|
||||
master.Register(r, c)
|
||||
}
|
||||
|
||||
func (r *Role) Heartbeat(node types.Node) (types.Nodes, error) {
|
||||
return r.onKeepAlive(node, true)
|
||||
}
|
||||
|
||||
func (r *Role) Join(node types.Node) (types.Nodes, error) {
|
||||
return r.onJoin(node, true)
|
||||
}
|
||||
|
||||
func (r *Role) Leave(node types.Node) error {
|
||||
_, err := r.onLeave(node, true)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Role) EventHeartbeat(node types.Node) (types.Nodes, error) {
|
||||
return r.onKeepAlive(node, false)
|
||||
}
|
||||
|
||||
func (r *Role) EventJoin(node types.Node) (types.Nodes, error) {
|
||||
return r.onJoin(node, false)
|
||||
}
|
||||
|
||||
func (r *Role) EventLeave(node types.Node) error {
|
||||
_, err := r.onLeave(node, false)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Role) onJoin(node types.Node, notify bool) (map[string]types.Node, error) {
|
||||
|
|
@ -65,7 +87,7 @@ func (r *Role) onJoin(node types.Node, notify bool) (map[string]types.Node, erro
|
|||
}
|
||||
|
||||
if notify {
|
||||
r.notify(types.PathMasterEventJoin, node)
|
||||
propagate(r, noReturn(r.state.Clients.Master.EventJoin), node)
|
||||
}
|
||||
|
||||
return r.state.Registry.AllNodes(), nil
|
||||
|
|
@ -77,7 +99,7 @@ func (r *Role) onLeave(node types.Node, notify bool) (bool, error) {
|
|||
}
|
||||
|
||||
if notify {
|
||||
r.notify(types.PathMasterEventLeave, node)
|
||||
propagate(r, r.state.Clients.Master.EventLeave, node)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
|
|
@ -94,7 +116,7 @@ func (r *Role) onKeepAlive(node types.Node, notify bool) (map[string]types.Node,
|
|||
}
|
||||
|
||||
if notify {
|
||||
r.notify(types.PathMasterEventKeepalive, node)
|
||||
propagate(r, noReturn(r.state.Clients.Master.EventHeartbeat), node)
|
||||
}
|
||||
|
||||
return r.state.Registry.AllNodes(), nil
|
||||
|
|
@ -106,11 +128,18 @@ func eventFunc[R any](fn func(types.Node, bool) (R, error), notify bool) func(ty
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Role) RegisterHandlers(r types.Registrator) {
|
||||
r.Register(types.PostEndpoint(types.PathMasterKeepalive, eventFunc(c.onKeepAlive, true)))
|
||||
r.Register(types.PostEndpoint(types.PathMasterEventKeepalive, eventFunc(c.onKeepAlive, false)))
|
||||
r.Register(types.PostEndpoint(types.PathMasterJoin, eventFunc(c.onJoin, true)))
|
||||
r.Register(types.PostEndpoint(types.PathMasterLeave, eventFunc(c.onLeave, true)))
|
||||
r.Register(types.PostEndpoint(types.PathMasterEventJoin, eventFunc(c.onJoin, false)))
|
||||
r.Register(types.PostEndpoint(types.PathMasterEventLeave, eventFunc(c.onLeave, false)))
|
||||
func noReturn[T, V any](fn func(string, T) (V, error)) func(string, T) error {
|
||||
return func(s string, t T) error {
|
||||
_, err := fn(s, t)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func propagate[T any](r *Role, handler func(string, T) error, v T) {
|
||||
for _, n := range r.state.Registry.ByRole(types.MasterRole) {
|
||||
addr := n.Endpoint
|
||||
r.tasksGroup.Go(func() {
|
||||
handler(addr, v)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,15 +5,14 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"git.wzray.com/homelab/hivemind/internal/app"
|
||||
"git.wzray.com/homelab/hivemind/internal/registry"
|
||||
"git.wzray.com/homelab/hivemind/internal/state"
|
||||
"git.wzray.com/homelab/hivemind/internal/types"
|
||||
"git.wzray.com/homelab/hivemind/internal/web/client"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type observer struct {
|
||||
state *state.RuntimeState
|
||||
state *app.State
|
||||
interval int
|
||||
backoff int
|
||||
backoffCount int
|
||||
|
|
@ -23,7 +22,7 @@ type observer struct {
|
|||
}
|
||||
|
||||
func newObserver(
|
||||
state *state.RuntimeState,
|
||||
state *app.State,
|
||||
interval int,
|
||||
backoff int,
|
||||
backoffCount int,
|
||||
|
|
@ -63,7 +62,7 @@ func (o *observer) pollNodes(ctx context.Context, onLeave func(types.Node) error
|
|||
delay := time.Duration(o.backoff)
|
||||
alive := false
|
||||
for i := o.backoffCount - 1; i >= 0; i-- {
|
||||
_, err := client.Get[any](n.Endpoint, types.PathNodeHealthcheck)
|
||||
_, err := o.state.Clients.Node.Healthcheck(n.Endpoint)
|
||||
|
||||
if err == nil {
|
||||
logger.Debug().Msg("node is alive")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue