mirror of
https://github.com/datarhei/core.git
synced 2025-10-06 16:37:04 +08:00
Move code into packages
This commit is contained in:
174
cluster/api.go
174
cluster/api.go
@@ -1,15 +1,11 @@
|
|||||||
package cluster
|
package cluster
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
|
"github.com/datarhei/core/v16/cluster/client"
|
||||||
httpapi "github.com/datarhei/core/v16/http/api"
|
httpapi "github.com/datarhei/core/v16/http/api"
|
||||||
"github.com/datarhei/core/v16/http/errorhandler"
|
"github.com/datarhei/core/v16/http/errorhandler"
|
||||||
"github.com/datarhei/core/v16/http/handler/util"
|
"github.com/datarhei/core/v16/http/handler/util"
|
||||||
@@ -17,7 +13,6 @@ import (
|
|||||||
mwlog "github.com/datarhei/core/v16/http/middleware/log"
|
mwlog "github.com/datarhei/core/v16/http/middleware/log"
|
||||||
"github.com/datarhei/core/v16/http/validator"
|
"github.com/datarhei/core/v16/http/validator"
|
||||||
"github.com/datarhei/core/v16/log"
|
"github.com/datarhei/core/v16/log"
|
||||||
"github.com/datarhei/core/v16/restream/app"
|
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
@@ -42,27 +37,6 @@ type APIConfig struct {
|
|||||||
Logger log.Logger
|
Logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type JoinRequest struct {
|
|
||||||
Origin string `json:"origin"`
|
|
||||||
ID string `json:"id"`
|
|
||||||
RaftAddress string `json:"raft_address"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type LeaveRequest struct {
|
|
||||||
Origin string `json:"origin"`
|
|
||||||
ID string `json:"id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AddProcessRequest struct {
|
|
||||||
Origin string `json:"origin"`
|
|
||||||
Config app.Config `json:"config"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RemoveProcessRequest struct {
|
|
||||||
Origin string `json:"origin"`
|
|
||||||
ID string `json:"id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewAPI(config APIConfig) (API, error) {
|
func NewAPI(config APIConfig) (API, error) {
|
||||||
a := &api{
|
a := &api{
|
||||||
id: config.ID,
|
id: config.ID,
|
||||||
@@ -105,7 +79,7 @@ func NewAPI(config APIConfig) (API, error) {
|
|||||||
a.router.Logger.SetOutput(httplog.NewWrapper(a.logger))
|
a.router.Logger.SetOutput(httplog.NewWrapper(a.logger))
|
||||||
|
|
||||||
a.router.POST("/v1/join", func(c echo.Context) error {
|
a.router.POST("/v1/join", func(c echo.Context) error {
|
||||||
r := JoinRequest{}
|
r := client.JoinRequest{}
|
||||||
|
|
||||||
if err := util.ShouldBindJSON(c, &r); err != nil {
|
if err := util.ShouldBindJSON(c, &r); err != nil {
|
||||||
return httpapi.Err(http.StatusBadRequest, "Invalid JSON", "%s", err)
|
return httpapi.Err(http.StatusBadRequest, "Invalid JSON", "%s", err)
|
||||||
@@ -127,7 +101,7 @@ func NewAPI(config APIConfig) (API, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
a.router.POST("/v1/leave", func(c echo.Context) error {
|
a.router.POST("/v1/leave", func(c echo.Context) error {
|
||||||
r := LeaveRequest{}
|
r := client.LeaveRequest{}
|
||||||
|
|
||||||
if err := util.ShouldBindJSON(c, &r); err != nil {
|
if err := util.ShouldBindJSON(c, &r); err != nil {
|
||||||
return httpapi.Err(http.StatusBadRequest, "Invalid JSON", "%s", err)
|
return httpapi.Err(http.StatusBadRequest, "Invalid JSON", "%s", err)
|
||||||
@@ -161,7 +135,7 @@ func NewAPI(config APIConfig) (API, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
a.router.POST("/v1/process", func(c echo.Context) error {
|
a.router.POST("/v1/process", func(c echo.Context) error {
|
||||||
r := AddProcessRequest{}
|
r := client.AddProcessRequest{}
|
||||||
|
|
||||||
if err := util.ShouldBindJSON(c, &r); err != nil {
|
if err := util.ShouldBindJSON(c, &r); err != nil {
|
||||||
return httpapi.Err(http.StatusBadRequest, "Invalid JSON", "%s", err)
|
return httpapi.Err(http.StatusBadRequest, "Invalid JSON", "%s", err)
|
||||||
@@ -183,7 +157,7 @@ func NewAPI(config APIConfig) (API, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
a.router.POST("/v1/process/:id", func(c echo.Context) error {
|
a.router.POST("/v1/process/:id", func(c echo.Context) error {
|
||||||
r := RemoveProcessRequest{}
|
r := client.RemoveProcessRequest{}
|
||||||
|
|
||||||
if err := util.ShouldBindJSON(c, &r); err != nil {
|
if err := util.ShouldBindJSON(c, &r); err != nil {
|
||||||
return httpapi.Err(http.StatusBadRequest, "Invalid JSON", "%s", err)
|
return httpapi.Err(http.StatusBadRequest, "Invalid JSON", "%s", err)
|
||||||
@@ -220,141 +194,3 @@ func (a *api) Start() error {
|
|||||||
func (a *api) Shutdown(ctx context.Context) error {
|
func (a *api) Shutdown(ctx context.Context) error {
|
||||||
return a.router.Shutdown(ctx)
|
return a.router.Shutdown(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
type APIClient struct {
|
|
||||||
Address string
|
|
||||||
Client *http.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *APIClient) CoreAPIAddress() (string, error) {
|
|
||||||
data, err := c.call(http.MethodGet, "/core", "", nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
var address string
|
|
||||||
err = json.Unmarshal(data, &address)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return address, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *APIClient) Join(r JoinRequest) error {
|
|
||||||
data, err := json.Marshal(&r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = c.call(http.MethodPost, "/join", "application/json", bytes.NewReader(data))
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *APIClient) Leave(r LeaveRequest) error {
|
|
||||||
data, err := json.Marshal(&r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = c.call(http.MethodPost, "/leave", "application/json", bytes.NewReader(data))
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *APIClient) AddProcess(r AddProcessRequest) error {
|
|
||||||
data, err := json.Marshal(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = c.call(http.MethodPost, "/process", "application/json", bytes.NewReader(data))
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *APIClient) RemoveProcess(r RemoveProcessRequest) error {
|
|
||||||
data, err := json.Marshal(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = c.call(http.MethodPost, "/process/"+r.ID, "application/json", bytes.NewReader(data))
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *APIClient) Snapshot() (io.ReadCloser, error) {
|
|
||||||
return c.stream(http.MethodGet, "/snapshot", "", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *APIClient) stream(method, path, contentType string, data io.Reader) (io.ReadCloser, error) {
|
|
||||||
if len(c.Address) == 0 {
|
|
||||||
return nil, fmt.Errorf("no address defined")
|
|
||||||
}
|
|
||||||
|
|
||||||
address := "http://" + c.Address + "/v1" + path
|
|
||||||
|
|
||||||
req, err := http.NewRequest(method, address, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if method == "POST" || method == "PUT" {
|
|
||||||
req.Header.Add("Content-Type", contentType)
|
|
||||||
}
|
|
||||||
|
|
||||||
status, body, err := c.request(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if status < 200 || status >= 300 {
|
|
||||||
e := httpapi.Error{}
|
|
||||||
|
|
||||||
defer body.Close()
|
|
||||||
|
|
||||||
x, _ := io.ReadAll(body)
|
|
||||||
|
|
||||||
json.Unmarshal(x, &e)
|
|
||||||
|
|
||||||
return nil, e
|
|
||||||
}
|
|
||||||
|
|
||||||
return body, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *APIClient) call(method, path, contentType string, data io.Reader) ([]byte, error) {
|
|
||||||
body, err := c.stream(method, path, contentType, data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer body.Close()
|
|
||||||
|
|
||||||
x, _ := io.ReadAll(body)
|
|
||||||
|
|
||||||
return x, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *APIClient) request(req *http.Request) (int, io.ReadCloser, error) {
|
|
||||||
if c.Client == nil {
|
|
||||||
tr := &http.Transport{
|
|
||||||
MaxIdleConns: 10,
|
|
||||||
IdleConnTimeout: 30 * time.Second,
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Client = &http.Client{
|
|
||||||
Transport: tr,
|
|
||||||
Timeout: 5 * time.Second,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.Client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return -1, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp.StatusCode, resp.Body, nil
|
|
||||||
}
|
|
||||||
|
172
cluster/client/client.go
Normal file
172
cluster/client/client.go
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
httpapi "github.com/datarhei/core/v16/http/api"
|
||||||
|
"github.com/datarhei/core/v16/restream/app"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JoinRequest struct {
|
||||||
|
Origin string `json:"origin"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
RaftAddress string `json:"raft_address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LeaveRequest struct {
|
||||||
|
Origin string `json:"origin"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AddProcessRequest struct {
|
||||||
|
Origin string `json:"origin"`
|
||||||
|
Config app.Config `json:"config"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RemoveProcessRequest struct {
|
||||||
|
Origin string `json:"origin"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type APIClient struct {
|
||||||
|
Address string
|
||||||
|
Client *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APIClient) CoreAPIAddress() (string, error) {
|
||||||
|
data, err := c.call(http.MethodGet, "/core", "", nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var address string
|
||||||
|
err = json.Unmarshal(data, &address)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return address, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APIClient) Join(r JoinRequest) error {
|
||||||
|
data, err := json.Marshal(&r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.call(http.MethodPost, "/join", "application/json", bytes.NewReader(data))
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APIClient) Leave(r LeaveRequest) error {
|
||||||
|
data, err := json.Marshal(&r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.call(http.MethodPost, "/leave", "application/json", bytes.NewReader(data))
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APIClient) AddProcess(r AddProcessRequest) error {
|
||||||
|
data, err := json.Marshal(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.call(http.MethodPost, "/process", "application/json", bytes.NewReader(data))
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APIClient) RemoveProcess(r RemoveProcessRequest) error {
|
||||||
|
data, err := json.Marshal(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.call(http.MethodPost, "/process/"+r.ID, "application/json", bytes.NewReader(data))
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APIClient) Snapshot() (io.ReadCloser, error) {
|
||||||
|
return c.stream(http.MethodGet, "/snapshot", "", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APIClient) stream(method, path, contentType string, data io.Reader) (io.ReadCloser, error) {
|
||||||
|
if len(c.Address) == 0 {
|
||||||
|
return nil, fmt.Errorf("no address defined")
|
||||||
|
}
|
||||||
|
|
||||||
|
address := "http://" + c.Address + "/v1" + path
|
||||||
|
|
||||||
|
req, err := http.NewRequest(method, address, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if method == "POST" || method == "PUT" {
|
||||||
|
req.Header.Add("Content-Type", contentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
status, body, err := c.request(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if status < 200 || status >= 300 {
|
||||||
|
e := httpapi.Error{}
|
||||||
|
|
||||||
|
defer body.Close()
|
||||||
|
|
||||||
|
x, _ := io.ReadAll(body)
|
||||||
|
|
||||||
|
json.Unmarshal(x, &e)
|
||||||
|
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
|
||||||
|
return body, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APIClient) call(method, path, contentType string, data io.Reader) ([]byte, error) {
|
||||||
|
body, err := c.stream(method, path, contentType, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer body.Close()
|
||||||
|
|
||||||
|
x, _ := io.ReadAll(body)
|
||||||
|
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *APIClient) request(req *http.Request) (int, io.ReadCloser, error) {
|
||||||
|
if c.Client == nil {
|
||||||
|
tr := &http.Transport{
|
||||||
|
MaxIdleConns: 10,
|
||||||
|
IdleConnTimeout: 30 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Client = &http.Client{
|
||||||
|
Transport: tr,
|
||||||
|
Timeout: 5 * time.Second,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := c.Client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return -1, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.StatusCode, resp.Body, nil
|
||||||
|
}
|
@@ -5,7 +5,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
gonet "net"
|
gonet "net"
|
||||||
@@ -16,6 +15,11 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
apiclient "github.com/datarhei/core/v16/cluster/client"
|
||||||
|
"github.com/datarhei/core/v16/cluster/forwarder"
|
||||||
|
raftlogger "github.com/datarhei/core/v16/cluster/logger"
|
||||||
|
"github.com/datarhei/core/v16/cluster/proxy"
|
||||||
|
"github.com/datarhei/core/v16/cluster/store"
|
||||||
"github.com/datarhei/core/v16/log"
|
"github.com/datarhei/core/v16/log"
|
||||||
"github.com/datarhei/core/v16/net"
|
"github.com/datarhei/core/v16/net"
|
||||||
"github.com/datarhei/core/v16/restream/app"
|
"github.com/datarhei/core/v16/restream/app"
|
||||||
@@ -46,8 +50,6 @@ import (
|
|||||||
** all these endpoints will forward the request to the leader.
|
** all these endpoints will forward the request to the leader.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var ErrNodeNotFound = errors.New("node not found")
|
|
||||||
|
|
||||||
type Cluster interface {
|
type Cluster interface {
|
||||||
// Address returns the raft address of this node
|
// Address returns the raft address of this node
|
||||||
Address() string
|
Address() string
|
||||||
@@ -71,7 +73,7 @@ type Cluster interface {
|
|||||||
AddProcess(origin string, config *app.Config) error
|
AddProcess(origin string, config *app.Config) error
|
||||||
RemoveProcess(origin, id string) error
|
RemoveProcess(origin, id string) error
|
||||||
|
|
||||||
ProxyReader() ProxyReader
|
ProxyReader() proxy.ProxyReader
|
||||||
}
|
}
|
||||||
|
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
@@ -113,7 +115,7 @@ type cluster struct {
|
|||||||
|
|
||||||
peers []Peer
|
peers []Peer
|
||||||
|
|
||||||
store Store
|
store store.Store
|
||||||
|
|
||||||
reassertLeaderCh chan chan error
|
reassertLeaderCh chan chan error
|
||||||
cancelLeaderShip context.CancelFunc
|
cancelLeaderShip context.CancelFunc
|
||||||
@@ -124,9 +126,9 @@ type cluster struct {
|
|||||||
shutdownCh chan struct{}
|
shutdownCh chan struct{}
|
||||||
shutdownLock sync.Mutex
|
shutdownLock sync.Mutex
|
||||||
|
|
||||||
forwarder Forwarder
|
forwarder forwarder.Forwarder
|
||||||
api API
|
api API
|
||||||
proxy Proxy
|
proxy proxy.Proxy
|
||||||
|
|
||||||
coreAddress string
|
coreAddress string
|
||||||
|
|
||||||
@@ -135,7 +137,7 @@ type cluster struct {
|
|||||||
isLeader bool
|
isLeader bool
|
||||||
leaderLock sync.Mutex
|
leaderLock sync.Mutex
|
||||||
|
|
||||||
nodes map[string]Node
|
nodes map[string]proxy.Node
|
||||||
nodesLock sync.RWMutex
|
nodesLock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +155,7 @@ func New(config ClusterConfig) (Cluster, error) {
|
|||||||
leaveCh: make(chan struct{}),
|
leaveCh: make(chan struct{}),
|
||||||
shutdownCh: make(chan struct{}),
|
shutdownCh: make(chan struct{}),
|
||||||
|
|
||||||
nodes: map[string]Node{},
|
nodes: map[string]proxy.Node{},
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := url.Parse(config.CoreAPIAddress)
|
u, err := url.Parse(config.CoreAPIAddress)
|
||||||
@@ -173,7 +175,7 @@ func New(config ClusterConfig) (Cluster, error) {
|
|||||||
c.logger = log.New("")
|
c.logger = log.New("")
|
||||||
}
|
}
|
||||||
|
|
||||||
store, err := NewStore()
|
store, err := store.NewStore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -195,7 +197,7 @@ func New(config ClusterConfig) (Cluster, error) {
|
|||||||
|
|
||||||
c.api = api
|
c.api = api
|
||||||
|
|
||||||
proxy, err := NewProxy(ProxyConfig{
|
nodeproxy, err := proxy.NewProxy(proxy.ProxyConfig{
|
||||||
ID: c.id,
|
ID: c.id,
|
||||||
Name: c.name,
|
Name: c.name,
|
||||||
IPLimiter: config.IPLimiter,
|
IPLimiter: config.IPLimiter,
|
||||||
@@ -206,15 +208,15 @@ func New(config ClusterConfig) (Cluster, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
go func(proxy Proxy) {
|
go func(nodeproxy proxy.Proxy) {
|
||||||
proxy.Start()
|
nodeproxy.Start()
|
||||||
}(proxy)
|
}(nodeproxy)
|
||||||
|
|
||||||
c.proxy = proxy
|
c.proxy = nodeproxy
|
||||||
|
|
||||||
go c.trackNodeChanges()
|
go c.trackNodeChanges()
|
||||||
|
|
||||||
if forwarder, err := NewForwarder(ForwarderConfig{
|
if forwarder, err := forwarder.New(forwarder.ForwarderConfig{
|
||||||
ID: c.id,
|
ID: c.id,
|
||||||
Logger: c.logger.WithField("logname", "forwarder"),
|
Logger: c.logger.WithField("logname", "forwarder"),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@@ -299,7 +301,7 @@ func (c *cluster) CoreAPIAddress(raftAddress string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
client := APIClient{
|
client := apiclient.APIClient{
|
||||||
Address: addr,
|
Address: addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,7 +496,7 @@ func (c *cluster) Join(origin, id, raftAddress, peerAddress string) error {
|
|||||||
return fmt.Errorf("peer API doesn't respond: %w", err)
|
return fmt.Errorf("peer API doesn't respond: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
node := NewNode(address)
|
node := proxy.NewNode(address)
|
||||||
err = node.Connect()
|
err = node.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't connect to peer: %w", err)
|
return fmt.Errorf("couldn't connect to peer: %w", err)
|
||||||
@@ -640,7 +642,7 @@ func (c *cluster) trackNodeChanges() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
node := NewNode(address)
|
node := proxy.NewNode(address)
|
||||||
err = node.Connect()
|
err = node.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Warn().WithError(err).WithFields(log.Fields{
|
c.logger.Warn().WithError(err).WithFields(log.Fields{
|
||||||
@@ -745,14 +747,14 @@ func (c *cluster) startRaft(fsm raft.FSM, bootstrap, recover bool, peers []Peer,
|
|||||||
|
|
||||||
c.logger.Debug().Log("address: %s", addr)
|
c.logger.Debug().Log("address: %s", addr)
|
||||||
|
|
||||||
transport, err := raft.NewTCPTransportWithLogger(c.raftAddress, addr, 3, 10*time.Second, NewLogger(c.logger, hclog.Debug).Named("raft-transport"))
|
transport, err := raft.NewTCPTransportWithLogger(c.raftAddress, addr, 3, 10*time.Second, raftlogger.New(c.logger, hclog.Debug).Named("raft-transport"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.raftTransport = transport
|
c.raftTransport = transport
|
||||||
|
|
||||||
snapshotLogger := NewLogger(c.logger, hclog.Debug).Named("raft-snapshot")
|
snapshotLogger := raftlogger.New(c.logger, hclog.Debug).Named("raft-snapshot")
|
||||||
snapshots, err := raft.NewFileSnapshotStoreWithLogger(c.path, 3, snapshotLogger)
|
snapshots, err := raft.NewFileSnapshotStoreWithLogger(c.path, 3, snapshotLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -787,7 +789,7 @@ func (c *cluster) startRaft(fsm raft.FSM, bootstrap, recover bool, peers []Peer,
|
|||||||
|
|
||||||
cfg := raft.DefaultConfig()
|
cfg := raft.DefaultConfig()
|
||||||
cfg.LocalID = raft.ServerID(c.id)
|
cfg.LocalID = raft.ServerID(c.id)
|
||||||
cfg.Logger = NewLogger(c.logger, hclog.Debug).Named("raft")
|
cfg.Logger = raftlogger.New(c.logger, hclog.Debug).Named("raft")
|
||||||
|
|
||||||
hasState, err := raft.HasExistingState(logStore, stableStore, snapshots)
|
hasState, err := raft.HasExistingState(logStore, stableStore, snapshots)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -823,7 +825,7 @@ func (c *cluster) startRaft(fsm raft.FSM, bootstrap, recover bool, peers []Peer,
|
|||||||
c.logger.Debug().Log("raft node bootstrapped")
|
c.logger.Debug().Log("raft node bootstrapped")
|
||||||
} else {
|
} else {
|
||||||
// Recover cluster
|
// Recover cluster
|
||||||
fsm, err := NewStore()
|
fsm, err := store.NewStore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -919,9 +921,9 @@ func (c *cluster) AddProcess(origin string, config *app.Config) error {
|
|||||||
return c.forwarder.AddProcess(origin, config)
|
return c.forwarder.AddProcess(origin, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := &command{
|
cmd := &store.Command{
|
||||||
Operation: opAddProcess,
|
Operation: store.OpAddProcess,
|
||||||
Data: &addProcessCommand{
|
Data: &store.CommandAddProcess{
|
||||||
Config: *config,
|
Config: *config,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -934,9 +936,9 @@ func (c *cluster) RemoveProcess(origin, id string) error {
|
|||||||
return c.forwarder.RemoveProcess(origin, id)
|
return c.forwarder.RemoveProcess(origin, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := &command{
|
cmd := &store.Command{
|
||||||
Operation: opRemoveProcess,
|
Operation: store.OpRemoveProcess,
|
||||||
Data: &removeProcessCommand{
|
Data: &store.CommandRemoveProcess{
|
||||||
ID: id,
|
ID: id,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -944,7 +946,7 @@ func (c *cluster) RemoveProcess(origin, id string) error {
|
|||||||
return c.applyCommand(cmd)
|
return c.applyCommand(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cluster) applyCommand(cmd *command) error {
|
func (c *cluster) applyCommand(cmd *store.Command) error {
|
||||||
b, err := json.Marshal(cmd)
|
b, err := json.Marshal(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -1076,6 +1078,6 @@ func (c *cluster) sentinel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cluster) ProxyReader() ProxyReader {
|
func (c *cluster) ProxyReader() proxy.ProxyReader {
|
||||||
return c.proxy.Reader()
|
return c.proxy.Reader()
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package cluster
|
package forwarder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
apiclient "github.com/datarhei/core/v16/cluster/client"
|
||||||
"github.com/datarhei/core/v16/log"
|
"github.com/datarhei/core/v16/log"
|
||||||
"github.com/datarhei/core/v16/restream/app"
|
"github.com/datarhei/core/v16/restream/app"
|
||||||
)
|
)
|
||||||
@@ -27,7 +28,7 @@ type forwarder struct {
|
|||||||
id string
|
id string
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
|
|
||||||
client APIClient
|
client apiclient.APIClient
|
||||||
|
|
||||||
logger log.Logger
|
logger log.Logger
|
||||||
}
|
}
|
||||||
@@ -37,7 +38,7 @@ type ForwarderConfig struct {
|
|||||||
Logger log.Logger
|
Logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewForwarder(config ForwarderConfig) (Forwarder, error) {
|
func New(config ForwarderConfig) (Forwarder, error) {
|
||||||
f := &forwarder{
|
f := &forwarder{
|
||||||
id: config.ID,
|
id: config.ID,
|
||||||
logger: config.Logger,
|
logger: config.Logger,
|
||||||
@@ -57,7 +58,7 @@ func NewForwarder(config ForwarderConfig) (Forwarder, error) {
|
|||||||
Timeout: 5 * time.Second,
|
Timeout: 5 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
f.client = APIClient{
|
f.client = apiclient.APIClient{
|
||||||
Client: client,
|
Client: client,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ func (f *forwarder) Join(origin, id, raftAddress, peerAddress string) error {
|
|||||||
origin = f.id
|
origin = f.id
|
||||||
}
|
}
|
||||||
|
|
||||||
r := JoinRequest{
|
r := apiclient.JoinRequest{
|
||||||
Origin: origin,
|
Origin: origin,
|
||||||
ID: id,
|
ID: id,
|
||||||
RaftAddress: raftAddress,
|
RaftAddress: raftAddress,
|
||||||
@@ -99,7 +100,7 @@ func (f *forwarder) Join(origin, id, raftAddress, peerAddress string) error {
|
|||||||
f.lock.RUnlock()
|
f.lock.RUnlock()
|
||||||
|
|
||||||
if len(peerAddress) != 0 {
|
if len(peerAddress) != 0 {
|
||||||
client = APIClient{
|
client = apiclient.APIClient{
|
||||||
Address: peerAddress,
|
Address: peerAddress,
|
||||||
Client: f.client.Client,
|
Client: f.client.Client,
|
||||||
}
|
}
|
||||||
@@ -113,7 +114,7 @@ func (f *forwarder) Leave(origin, id string) error {
|
|||||||
origin = f.id
|
origin = f.id
|
||||||
}
|
}
|
||||||
|
|
||||||
r := LeaveRequest{
|
r := apiclient.LeaveRequest{
|
||||||
Origin: origin,
|
Origin: origin,
|
||||||
ID: id,
|
ID: id,
|
||||||
}
|
}
|
||||||
@@ -140,7 +141,7 @@ func (f *forwarder) AddProcess(origin string, config *app.Config) error {
|
|||||||
origin = f.id
|
origin = f.id
|
||||||
}
|
}
|
||||||
|
|
||||||
r := AddProcessRequest{
|
r := apiclient.AddProcessRequest{
|
||||||
Origin: origin,
|
Origin: origin,
|
||||||
Config: *config,
|
Config: *config,
|
||||||
}
|
}
|
||||||
@@ -161,7 +162,7 @@ func (f *forwarder) RemoveProcess(origin, id string) error {
|
|||||||
origin = f.id
|
origin = f.id
|
||||||
}
|
}
|
||||||
|
|
||||||
r := RemoveProcessRequest{
|
r := apiclient.RemoveProcessRequest{
|
||||||
Origin: origin,
|
Origin: origin,
|
||||||
ID: id,
|
ID: id,
|
||||||
}
|
}
|
@@ -8,6 +8,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/datarhei/core/v16/cluster/proxy"
|
||||||
"github.com/datarhei/core/v16/log"
|
"github.com/datarhei/core/v16/log"
|
||||||
"github.com/datarhei/core/v16/restream/app"
|
"github.com/datarhei/core/v16/restream/app"
|
||||||
)
|
)
|
||||||
@@ -471,7 +472,7 @@ func (c *cluster) doRebalance() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// normalizeProcessesAndResources normalizes the CPU and memory consumption of the processes and resources in-place.
|
// normalizeProcessesAndResources normalizes the CPU and memory consumption of the processes and resources in-place.
|
||||||
func normalizeProcessesAndResources(processes []ProcessConfig, resources map[string]NodeResources) {
|
func normalizeProcessesAndResources(processes []proxy.ProcessConfig, resources map[string]proxy.NodeResources) {
|
||||||
maxNCPU := .0
|
maxNCPU := .0
|
||||||
maxMemTotal := .0
|
maxMemTotal := .0
|
||||||
|
|
||||||
@@ -520,7 +521,7 @@ func normalizeProcessesAndResources(processes []ProcessConfig, resources map[str
|
|||||||
|
|
||||||
// synchronize returns a list of operations in order to adjust the "have" list to the "want" list
|
// synchronize returns a list of operations in order to adjust the "have" list to the "want" list
|
||||||
// with taking the available resources on each node into account.
|
// with taking the available resources on each node into account.
|
||||||
func synchronize(want []app.Config, have []ProcessConfig, resources map[string]NodeResources) []interface{} {
|
func synchronize(want []app.Config, have []proxy.ProcessConfig, resources map[string]proxy.NodeResources) []interface{} {
|
||||||
normalizeProcessesAndResources(have, resources)
|
normalizeProcessesAndResources(have, resources)
|
||||||
|
|
||||||
// A map from the process ID to the process config of the processes
|
// A map from the process ID to the process config of the processes
|
||||||
@@ -535,7 +536,7 @@ func synchronize(want []app.Config, have []ProcessConfig, resources map[string]N
|
|||||||
// Now we iterate through the processes we actually have running on the nodes
|
// Now we iterate through the processes we actually have running on the nodes
|
||||||
// and remove them from the wantMap. We also make sure that they are running.
|
// and remove them from the wantMap. We also make sure that they are running.
|
||||||
// If a process is not on the wantMap, it will be deleted from the nodes.
|
// If a process is not on the wantMap, it will be deleted from the nodes.
|
||||||
haveAfterRemove := []ProcessConfig{}
|
haveAfterRemove := []proxy.ProcessConfig{}
|
||||||
|
|
||||||
for _, p := range have {
|
for _, p := range have {
|
||||||
if _, ok := wantMap[p.Config.ID]; !ok {
|
if _, ok := wantMap[p.Config.ID]; !ok {
|
||||||
@@ -664,7 +665,7 @@ type referenceAffinityNodeCount struct {
|
|||||||
count uint64
|
count uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func createReferenceAffinityMap(processes []ProcessConfig) map[string][]referenceAffinityNodeCount {
|
func createReferenceAffinityMap(processes []proxy.ProcessConfig) map[string][]referenceAffinityNodeCount {
|
||||||
referenceAffinityMap := map[string][]referenceAffinityNodeCount{}
|
referenceAffinityMap := map[string][]referenceAffinityNodeCount{}
|
||||||
for _, p := range processes {
|
for _, p := range processes {
|
||||||
if len(p.Config.Reference) == 0 {
|
if len(p.Config.Reference) == 0 {
|
||||||
@@ -709,11 +710,11 @@ func createReferenceAffinityMap(processes []ProcessConfig) map[string][]referenc
|
|||||||
|
|
||||||
// rebalance returns a list of operations that will move running processes away from nodes
|
// rebalance returns a list of operations that will move running processes away from nodes
|
||||||
// that are overloaded.
|
// that are overloaded.
|
||||||
func rebalance(have []ProcessConfig, resources map[string]NodeResources) []interface{} {
|
func rebalance(have []proxy.ProcessConfig, resources map[string]proxy.NodeResources) []interface{} {
|
||||||
normalizeProcessesAndResources(have, resources)
|
normalizeProcessesAndResources(have, resources)
|
||||||
|
|
||||||
// Group the processes by node
|
// Group the processes by node
|
||||||
processNodeMap := map[string][]ProcessConfig{}
|
processNodeMap := map[string][]proxy.ProcessConfig{}
|
||||||
|
|
||||||
for _, p := range have {
|
for _, p := range have {
|
||||||
processNodeMap[p.NodeID] = append(processNodeMap[p.NodeID], p)
|
processNodeMap[p.NodeID] = append(processNodeMap[p.NodeID], p)
|
||||||
|
@@ -3,13 +3,14 @@ package cluster
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/datarhei/core/v16/cluster/proxy"
|
||||||
"github.com/datarhei/core/v16/restream/app"
|
"github.com/datarhei/core/v16/restream/app"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNormalize(t *testing.T) {
|
func TestNormalize(t *testing.T) {
|
||||||
have := []ProcessConfig{
|
have := []proxy.ProcessConfig{
|
||||||
{
|
{
|
||||||
NodeID: "node2",
|
NodeID: "node2",
|
||||||
Order: "start",
|
Order: "start",
|
||||||
@@ -23,7 +24,7 @@ func TestNormalize(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resources := map[string]NodeResources{
|
resources := map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 2,
|
NCPU: 2,
|
||||||
CPU: 7,
|
CPU: 7,
|
||||||
@@ -40,7 +41,7 @@ func TestNormalize(t *testing.T) {
|
|||||||
|
|
||||||
normalizeProcessesAndResources(have, resources)
|
normalizeProcessesAndResources(have, resources)
|
||||||
|
|
||||||
require.Equal(t, []ProcessConfig{
|
require.Equal(t, []proxy.ProcessConfig{
|
||||||
{
|
{
|
||||||
NodeID: "node2",
|
NodeID: "node2",
|
||||||
Order: "start",
|
Order: "start",
|
||||||
@@ -54,7 +55,7 @@ func TestNormalize(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, have)
|
}, have)
|
||||||
|
|
||||||
require.Equal(t, map[string]NodeResources{
|
require.Equal(t, map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 2,
|
NCPU: 2,
|
||||||
CPU: 7,
|
CPU: 7,
|
||||||
@@ -72,7 +73,7 @@ func TestNormalize(t *testing.T) {
|
|||||||
// test idempotency
|
// test idempotency
|
||||||
normalizeProcessesAndResources(have, resources)
|
normalizeProcessesAndResources(have, resources)
|
||||||
|
|
||||||
require.Equal(t, []ProcessConfig{
|
require.Equal(t, []proxy.ProcessConfig{
|
||||||
{
|
{
|
||||||
NodeID: "node2",
|
NodeID: "node2",
|
||||||
Order: "start",
|
Order: "start",
|
||||||
@@ -86,7 +87,7 @@ func TestNormalize(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, have)
|
}, have)
|
||||||
|
|
||||||
require.Equal(t, map[string]NodeResources{
|
require.Equal(t, map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 2,
|
NCPU: 2,
|
||||||
CPU: 7,
|
CPU: 7,
|
||||||
@@ -111,9 +112,9 @@ func TestSynchronizeAdd(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
have := []ProcessConfig{}
|
have := []proxy.ProcessConfig{}
|
||||||
|
|
||||||
resources := map[string]NodeResources{
|
resources := map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 7,
|
CPU: 7,
|
||||||
@@ -145,7 +146,7 @@ func TestSynchronizeAdd(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, stack)
|
}, stack)
|
||||||
|
|
||||||
require.Equal(t, map[string]NodeResources{
|
require.Equal(t, map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 17,
|
CPU: 17,
|
||||||
@@ -181,7 +182,7 @@ func TestSynchronizeAddReferenceAffinity(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
have := []ProcessConfig{
|
have := []proxy.ProcessConfig{
|
||||||
{
|
{
|
||||||
NodeID: "node2",
|
NodeID: "node2",
|
||||||
Order: "start",
|
Order: "start",
|
||||||
@@ -196,7 +197,7 @@ func TestSynchronizeAddReferenceAffinity(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resources := map[string]NodeResources{
|
resources := map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 1,
|
CPU: 1,
|
||||||
@@ -239,9 +240,9 @@ func TestSynchronizeAddLimit(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
have := []ProcessConfig{}
|
have := []proxy.ProcessConfig{}
|
||||||
|
|
||||||
resources := map[string]NodeResources{
|
resources := map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 81,
|
CPU: 81,
|
||||||
@@ -273,7 +274,7 @@ func TestSynchronizeAddLimit(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, stack)
|
}, stack)
|
||||||
|
|
||||||
require.Equal(t, map[string]NodeResources{
|
require.Equal(t, map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 81,
|
CPU: 81,
|
||||||
@@ -302,9 +303,9 @@ func TestSynchronizeAddNoResourcesCPU(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
have := []ProcessConfig{}
|
have := []proxy.ProcessConfig{}
|
||||||
|
|
||||||
resources := map[string]NodeResources{
|
resources := map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 81,
|
CPU: 81,
|
||||||
@@ -342,9 +343,9 @@ func TestSynchronizeAddNoResourcesMemory(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
have := []ProcessConfig{}
|
have := []proxy.ProcessConfig{}
|
||||||
|
|
||||||
resources := map[string]NodeResources{
|
resources := map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 81,
|
CPU: 81,
|
||||||
@@ -380,9 +381,9 @@ func TestSynchronizeAddNoLimits(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
have := []ProcessConfig{}
|
have := []proxy.ProcessConfig{}
|
||||||
|
|
||||||
resources := map[string]NodeResources{
|
resources := map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 81,
|
CPU: 81,
|
||||||
@@ -414,7 +415,7 @@ func TestSynchronizeAddNoLimits(t *testing.T) {
|
|||||||
func TestSynchronizeRemove(t *testing.T) {
|
func TestSynchronizeRemove(t *testing.T) {
|
||||||
want := []app.Config{}
|
want := []app.Config{}
|
||||||
|
|
||||||
have := []ProcessConfig{
|
have := []proxy.ProcessConfig{
|
||||||
{
|
{
|
||||||
NodeID: "node2",
|
NodeID: "node2",
|
||||||
Order: "start",
|
Order: "start",
|
||||||
@@ -428,7 +429,7 @@ func TestSynchronizeRemove(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resources := map[string]NodeResources{
|
resources := map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 7,
|
CPU: 7,
|
||||||
@@ -456,7 +457,7 @@ func TestSynchronizeRemove(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, stack)
|
}, stack)
|
||||||
|
|
||||||
require.Equal(t, map[string]NodeResources{
|
require.Equal(t, map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 7,
|
CPU: 7,
|
||||||
@@ -485,7 +486,7 @@ func TestSynchronizeAddRemove(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
have := []ProcessConfig{
|
have := []proxy.ProcessConfig{
|
||||||
{
|
{
|
||||||
NodeID: "node2",
|
NodeID: "node2",
|
||||||
Order: "start",
|
Order: "start",
|
||||||
@@ -499,7 +500,7 @@ func TestSynchronizeAddRemove(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resources := map[string]NodeResources{
|
resources := map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 7,
|
CPU: 7,
|
||||||
@@ -535,7 +536,7 @@ func TestSynchronizeAddRemove(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, stack)
|
}, stack)
|
||||||
|
|
||||||
require.Equal(t, map[string]NodeResources{
|
require.Equal(t, map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 17,
|
CPU: 17,
|
||||||
@@ -556,7 +557,7 @@ func TestSynchronizeAddRemove(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRebalanceNothingToDo(t *testing.T) {
|
func TestRebalanceNothingToDo(t *testing.T) {
|
||||||
processes := []ProcessConfig{
|
processes := []proxy.ProcessConfig{
|
||||||
{
|
{
|
||||||
NodeID: "node1",
|
NodeID: "node1",
|
||||||
Order: "start",
|
Order: "start",
|
||||||
@@ -581,7 +582,7 @@ func TestRebalanceNothingToDo(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resources := map[string]NodeResources{
|
resources := map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 42,
|
CPU: 42,
|
||||||
@@ -606,7 +607,7 @@ func TestRebalanceNothingToDo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRebalanceOverload(t *testing.T) {
|
func TestRebalanceOverload(t *testing.T) {
|
||||||
processes := []ProcessConfig{
|
processes := []proxy.ProcessConfig{
|
||||||
{
|
{
|
||||||
NodeID: "node1",
|
NodeID: "node1",
|
||||||
Order: "start",
|
Order: "start",
|
||||||
@@ -642,7 +643,7 @@ func TestRebalanceOverload(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resources := map[string]NodeResources{
|
resources := map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 91,
|
CPU: 91,
|
||||||
@@ -675,7 +676,7 @@ func TestRebalanceOverload(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, opStack)
|
}, opStack)
|
||||||
|
|
||||||
require.Equal(t, map[string]NodeResources{
|
require.Equal(t, map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 74,
|
CPU: 74,
|
||||||
@@ -696,7 +697,7 @@ func TestRebalanceOverload(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRebalanceSkip(t *testing.T) {
|
func TestRebalanceSkip(t *testing.T) {
|
||||||
processes := []ProcessConfig{
|
processes := []proxy.ProcessConfig{
|
||||||
{
|
{
|
||||||
NodeID: "node1",
|
NodeID: "node1",
|
||||||
Order: "start",
|
Order: "start",
|
||||||
@@ -732,7 +733,7 @@ func TestRebalanceSkip(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resources := map[string]NodeResources{
|
resources := map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 91,
|
CPU: 91,
|
||||||
@@ -773,7 +774,7 @@ func TestRebalanceSkip(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, opStack)
|
}, opStack)
|
||||||
|
|
||||||
require.Equal(t, map[string]NodeResources{
|
require.Equal(t, map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 91,
|
CPU: 91,
|
||||||
@@ -794,7 +795,7 @@ func TestRebalanceSkip(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRebalanceReferenceAffinity(t *testing.T) {
|
func TestRebalanceReferenceAffinity(t *testing.T) {
|
||||||
processes := []ProcessConfig{
|
processes := []proxy.ProcessConfig{
|
||||||
{
|
{
|
||||||
NodeID: "node1",
|
NodeID: "node1",
|
||||||
Order: "start",
|
Order: "start",
|
||||||
@@ -856,7 +857,7 @@ func TestRebalanceReferenceAffinity(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resources := map[string]NodeResources{
|
resources := map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 90,
|
CPU: 90,
|
||||||
@@ -898,7 +899,7 @@ func TestRebalanceReferenceAffinity(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, opStack)
|
}, opStack)
|
||||||
|
|
||||||
require.Equal(t, map[string]NodeResources{
|
require.Equal(t, map[string]proxy.NodeResources{
|
||||||
"node1": {
|
"node1": {
|
||||||
NCPU: 1,
|
NCPU: 1,
|
||||||
CPU: 89,
|
CPU: 89,
|
||||||
@@ -927,7 +928,7 @@ func TestRebalanceReferenceAffinity(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateReferenceAffinityNodeMap(t *testing.T) {
|
func TestCreateReferenceAffinityNodeMap(t *testing.T) {
|
||||||
processes := []ProcessConfig{
|
processes := []proxy.ProcessConfig{
|
||||||
{
|
{
|
||||||
NodeID: "node1",
|
NodeID: "node1",
|
||||||
Order: "start",
|
Order: "start",
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package cluster
|
package logger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
@@ -19,7 +19,7 @@ type hclogger struct {
|
|||||||
args []interface{}
|
args []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLogger(logger log.Logger, lvl hclog.Level) hclog.Logger {
|
func New(logger log.Logger, lvl hclog.Level) hclog.Logger {
|
||||||
return &hclogger{
|
return &hclogger{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
level: lvl,
|
level: lvl,
|
@@ -1,4 +1,4 @@
|
|||||||
package cluster
|
package proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -375,6 +375,13 @@ func (n *node) IPs() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) ID() string {
|
func (n *node) ID() string {
|
||||||
|
n.peerLock.RLock()
|
||||||
|
defer n.peerLock.RUnlock()
|
||||||
|
|
||||||
|
if n.peer == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
return n.peer.ID()
|
return n.peer.ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +390,7 @@ func (n *node) Files() NodeFiles {
|
|||||||
defer n.stateLock.RUnlock()
|
defer n.stateLock.RUnlock()
|
||||||
|
|
||||||
state := NodeFiles{
|
state := NodeFiles{
|
||||||
ID: n.peer.ID(),
|
ID: n.ID(),
|
||||||
LastUpdate: n.lastUpdate,
|
LastUpdate: n.lastUpdate,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,7 +407,7 @@ func (n *node) State() NodeState {
|
|||||||
defer n.stateLock.RUnlock()
|
defer n.stateLock.RUnlock()
|
||||||
|
|
||||||
state := NodeState{
|
state := NodeState{
|
||||||
ID: n.peer.ID(),
|
ID: n.ID(),
|
||||||
LastContact: n.lastContact,
|
LastContact: n.lastContact,
|
||||||
State: n.state.String(),
|
State: n.state.String(),
|
||||||
Latency: time.Duration(n.latency * float64(time.Second)),
|
Latency: time.Duration(n.latency * float64(time.Second)),
|
||||||
@@ -445,6 +452,10 @@ func (n *node) files() {
|
|||||||
n.peerLock.RLock()
|
n.peerLock.RLock()
|
||||||
defer n.peerLock.RUnlock()
|
defer n.peerLock.RUnlock()
|
||||||
|
|
||||||
|
if n.peer == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
files, err := n.peer.MemFSList("name", "asc")
|
files, err := n.peer.MemFSList("name", "asc")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -461,6 +472,10 @@ func (n *node) files() {
|
|||||||
n.peerLock.RLock()
|
n.peerLock.RLock()
|
||||||
defer n.peerLock.RUnlock()
|
defer n.peerLock.RUnlock()
|
||||||
|
|
||||||
|
if n.peer == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
files, err := n.peer.DiskFSList("name", "asc")
|
files, err := n.peer.DiskFSList("name", "asc")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -480,6 +495,10 @@ func (n *node) files() {
|
|||||||
n.peerLock.RLock()
|
n.peerLock.RLock()
|
||||||
defer n.peerLock.RUnlock()
|
defer n.peerLock.RUnlock()
|
||||||
|
|
||||||
|
if n.peer == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
files, err := n.peer.RTMPChannels()
|
files, err := n.peer.RTMPChannels()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -500,6 +519,10 @@ func (n *node) files() {
|
|||||||
n.peerLock.RLock()
|
n.peerLock.RLock()
|
||||||
defer n.peerLock.RUnlock()
|
defer n.peerLock.RUnlock()
|
||||||
|
|
||||||
|
if n.peer == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
files, err := n.peer.SRTChannels()
|
files, err := n.peer.SRTChannels()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -570,6 +593,10 @@ func (n *node) GetFile(path string) (io.ReadCloser, error) {
|
|||||||
n.peerLock.RLock()
|
n.peerLock.RLock()
|
||||||
defer n.peerLock.RUnlock()
|
defer n.peerLock.RUnlock()
|
||||||
|
|
||||||
|
if n.peer == nil {
|
||||||
|
return nil, fmt.Errorf("not connected")
|
||||||
|
}
|
||||||
|
|
||||||
if prefix == "mem" {
|
if prefix == "mem" {
|
||||||
return n.peer.MemFSGetFile(path)
|
return n.peer.MemFSGetFile(path)
|
||||||
} else if prefix == "disk" {
|
} else if prefix == "disk" {
|
||||||
@@ -580,6 +607,13 @@ func (n *node) GetFile(path string) (io.ReadCloser, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) ProcessList() ([]ProcessConfig, error) {
|
func (n *node) ProcessList() ([]ProcessConfig, error) {
|
||||||
|
n.peerLock.RLock()
|
||||||
|
defer n.peerLock.RUnlock()
|
||||||
|
|
||||||
|
if n.peer == nil {
|
||||||
|
return nil, fmt.Errorf("not connected")
|
||||||
|
}
|
||||||
|
|
||||||
list, err := n.peer.ProcessList(nil, []string{
|
list, err := n.peer.ProcessList(nil, []string{
|
||||||
"state",
|
"state",
|
||||||
"config",
|
"config",
|
||||||
@@ -613,6 +647,13 @@ func (n *node) ProcessList() ([]ProcessConfig, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) ProcessAdd(config *app.Config) error {
|
func (n *node) ProcessAdd(config *app.Config) error {
|
||||||
|
n.peerLock.RLock()
|
||||||
|
defer n.peerLock.RUnlock()
|
||||||
|
|
||||||
|
if n.peer == nil {
|
||||||
|
return fmt.Errorf("not connected")
|
||||||
|
}
|
||||||
|
|
||||||
cfg := httpapi.ProcessConfig{}
|
cfg := httpapi.ProcessConfig{}
|
||||||
cfg.Unmarshal(config)
|
cfg.Unmarshal(config)
|
||||||
|
|
||||||
@@ -620,13 +661,34 @@ func (n *node) ProcessAdd(config *app.Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) ProcessStart(id string) error {
|
func (n *node) ProcessStart(id string) error {
|
||||||
|
n.peerLock.RLock()
|
||||||
|
defer n.peerLock.RUnlock()
|
||||||
|
|
||||||
|
if n.peer == nil {
|
||||||
|
return fmt.Errorf("not connected")
|
||||||
|
}
|
||||||
|
|
||||||
return n.peer.ProcessCommand(id, "start")
|
return n.peer.ProcessCommand(id, "start")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) ProcessStop(id string) error {
|
func (n *node) ProcessStop(id string) error {
|
||||||
|
n.peerLock.RLock()
|
||||||
|
defer n.peerLock.RUnlock()
|
||||||
|
|
||||||
|
if n.peer == nil {
|
||||||
|
return fmt.Errorf("not connected")
|
||||||
|
}
|
||||||
|
|
||||||
return n.peer.ProcessCommand(id, "stop")
|
return n.peer.ProcessCommand(id, "stop")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) ProcessDelete(id string) error {
|
func (n *node) ProcessDelete(id string) error {
|
||||||
|
n.peerLock.RLock()
|
||||||
|
defer n.peerLock.RUnlock()
|
||||||
|
|
||||||
|
if n.peer == nil {
|
||||||
|
return fmt.Errorf("not connected")
|
||||||
|
}
|
||||||
|
|
||||||
return n.peer.ProcessDelete(id)
|
return n.peer.ProcessDelete(id)
|
||||||
}
|
}
|
@@ -1,7 +1,8 @@
|
|||||||
package cluster
|
package proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -156,6 +157,8 @@ type proxy struct {
|
|||||||
logger log.Logger
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ErrNodeNotFound = errors.New("node not found")
|
||||||
|
|
||||||
func NewProxy(config ProxyConfig) (Proxy, error) {
|
func NewProxy(config ProxyConfig) (Proxy, error) {
|
||||||
p := &proxy{
|
p := &proxy{
|
||||||
id: config.ID,
|
id: config.ID,
|
@@ -1,4 +1,4 @@
|
|||||||
package cluster
|
package store
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -21,25 +21,20 @@ type Store interface {
|
|||||||
type operation string
|
type operation string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
opAddProcess operation = "addProcess"
|
OpAddProcess operation = "addProcess"
|
||||||
opRemoveProcess operation = "removeProcess"
|
OpRemoveProcess operation = "removeProcess"
|
||||||
)
|
)
|
||||||
|
|
||||||
type command struct {
|
type Command struct {
|
||||||
Operation operation
|
Operation operation
|
||||||
Data interface{}
|
Data interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type StoreNode struct {
|
type CommandAddProcess struct {
|
||||||
ID string
|
|
||||||
Address string
|
|
||||||
}
|
|
||||||
|
|
||||||
type addProcessCommand struct {
|
|
||||||
app.Config
|
app.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
type removeProcessCommand struct {
|
type CommandRemoveProcess struct {
|
||||||
ID string
|
ID string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +53,7 @@ func NewStore() (Store, error) {
|
|||||||
func (s *store) Apply(log *raft.Log) interface{} {
|
func (s *store) Apply(log *raft.Log) interface{} {
|
||||||
fmt.Printf("a log entry came in (index=%d, term=%d): %s\n", log.Index, log.Term, string(log.Data))
|
fmt.Printf("a log entry came in (index=%d, term=%d): %s\n", log.Index, log.Term, string(log.Data))
|
||||||
|
|
||||||
c := command{}
|
c := Command{}
|
||||||
|
|
||||||
err := json.Unmarshal(log.Data, &c)
|
err := json.Unmarshal(log.Data, &c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -70,17 +65,17 @@ func (s *store) Apply(log *raft.Log) interface{} {
|
|||||||
fmt.Printf("op: %+v\n", c)
|
fmt.Printf("op: %+v\n", c)
|
||||||
|
|
||||||
switch c.Operation {
|
switch c.Operation {
|
||||||
case opAddProcess:
|
case OpAddProcess:
|
||||||
b, _ := json.Marshal(c.Data)
|
b, _ := json.Marshal(c.Data)
|
||||||
cmd := addProcessCommand{}
|
cmd := CommandAddProcess{}
|
||||||
json.Unmarshal(b, &cmd)
|
json.Unmarshal(b, &cmd)
|
||||||
|
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
s.Process[cmd.ID] = cmd.Config
|
s.Process[cmd.ID] = cmd.Config
|
||||||
s.lock.Unlock()
|
s.lock.Unlock()
|
||||||
case opRemoveProcess:
|
case OpRemoveProcess:
|
||||||
b, _ := json.Marshal(c.Data)
|
b, _ := json.Marshal(c.Data)
|
||||||
cmd := removeProcessCommand{}
|
cmd := CommandRemoveProcess{}
|
||||||
json.Unmarshal(b, &cmd)
|
json.Unmarshal(b, &cmd)
|
||||||
|
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
@@ -5,7 +5,7 @@ import (
|
|||||||
gofs "io/fs"
|
gofs "io/fs"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/datarhei/core/v16/cluster"
|
"github.com/datarhei/core/v16/cluster/proxy"
|
||||||
"github.com/datarhei/core/v16/io/fs"
|
"github.com/datarhei/core/v16/io/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -17,10 +17,10 @@ type filesystem struct {
|
|||||||
fs.Filesystem
|
fs.Filesystem
|
||||||
|
|
||||||
name string
|
name string
|
||||||
proxy cluster.ProxyReader
|
proxy proxy.ProxyReader
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClusterFS(name string, fs fs.Filesystem, proxy cluster.ProxyReader) Filesystem {
|
func NewClusterFS(name string, fs fs.Filesystem, proxy proxy.ProxyReader) Filesystem {
|
||||||
if proxy == nil {
|
if proxy == nil {
|
||||||
return fs
|
return fs
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/datarhei/core/v16/cluster"
|
"github.com/datarhei/core/v16/cluster"
|
||||||
|
"github.com/datarhei/core/v16/cluster/proxy"
|
||||||
"github.com/datarhei/core/v16/http/api"
|
"github.com/datarhei/core/v16/http/api"
|
||||||
"github.com/datarhei/core/v16/http/handler/util"
|
"github.com/datarhei/core/v16/http/handler/util"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
@@ -15,7 +16,7 @@ import (
|
|||||||
// The ClusterHandler type provides handler functions for manipulating the cluster config.
|
// The ClusterHandler type provides handler functions for manipulating the cluster config.
|
||||||
type ClusterHandler struct {
|
type ClusterHandler struct {
|
||||||
cluster cluster.Cluster
|
cluster cluster.Cluster
|
||||||
proxy cluster.ProxyReader
|
proxy proxy.ProxyReader
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCluster return a new ClusterHandler type. You have to provide a cluster.
|
// NewCluster return a new ClusterHandler type. You have to provide a cluster.
|
||||||
|
@@ -11,7 +11,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/datarhei/core/v16/cluster"
|
"github.com/datarhei/core/v16/cluster/proxy"
|
||||||
"github.com/datarhei/core/v16/log"
|
"github.com/datarhei/core/v16/log"
|
||||||
"github.com/datarhei/core/v16/session"
|
"github.com/datarhei/core/v16/session"
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ type Config struct {
|
|||||||
// with methods like tls.Config.SetSessionTicketKeys.
|
// with methods like tls.Config.SetSessionTicketKeys.
|
||||||
TLSConfig *tls.Config
|
TLSConfig *tls.Config
|
||||||
|
|
||||||
Proxy cluster.ProxyReader
|
Proxy proxy.ProxyReader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server represents a RTMP server
|
// Server represents a RTMP server
|
||||||
@@ -93,7 +93,7 @@ type server struct {
|
|||||||
channels map[string]*channel
|
channels map[string]*channel
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
|
|
||||||
proxy cluster.ProxyReader
|
proxy proxy.ProxyReader
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new RTMP server according to the given config
|
// New creates a new RTMP server according to the given config
|
||||||
@@ -119,7 +119,7 @@ func New(config Config) (Server, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if s.proxy == nil {
|
if s.proxy == nil {
|
||||||
s.proxy = cluster.NewNullProxyReader()
|
s.proxy = proxy.NewNullProxyReader()
|
||||||
}
|
}
|
||||||
|
|
||||||
s.server = &rtmp.Server{
|
s.server = &rtmp.Server{
|
||||||
|
@@ -10,7 +10,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/datarhei/core/v16/cluster"
|
"github.com/datarhei/core/v16/cluster/proxy"
|
||||||
"github.com/datarhei/core/v16/log"
|
"github.com/datarhei/core/v16/log"
|
||||||
"github.com/datarhei/core/v16/session"
|
"github.com/datarhei/core/v16/session"
|
||||||
srt "github.com/datarhei/gosrt"
|
srt "github.com/datarhei/gosrt"
|
||||||
@@ -40,7 +40,7 @@ type Config struct {
|
|||||||
|
|
||||||
SRTLogTopics []string
|
SRTLogTopics []string
|
||||||
|
|
||||||
Proxy cluster.ProxyReader
|
Proxy proxy.ProxyReader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server represents a SRT server
|
// Server represents a SRT server
|
||||||
@@ -77,7 +77,7 @@ type server struct {
|
|||||||
srtlog map[string]*ring.Ring // Per logtopic a dedicated ring buffer
|
srtlog map[string]*ring.Ring // Per logtopic a dedicated ring buffer
|
||||||
srtlogLock sync.RWMutex
|
srtlogLock sync.RWMutex
|
||||||
|
|
||||||
proxy cluster.ProxyReader
|
proxy proxy.ProxyReader
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(config Config) (Server, error) {
|
func New(config Config) (Server, error) {
|
||||||
@@ -95,7 +95,7 @@ func New(config Config) (Server, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if s.proxy == nil {
|
if s.proxy == nil {
|
||||||
s.proxy = cluster.NewNullProxyReader()
|
s.proxy = proxy.NewNullProxyReader()
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.logger == nil {
|
if s.logger == nil {
|
||||||
|
Reference in New Issue
Block a user