You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
3.0 KiB
Go

package server
import (
pb "FRMS/internal/pkg/grpc"
"FRMS/internal/pkg/logging"
"FRMS/internal/pkg/manager"
"time"
"context"
"github.com/spf13/viper"
)
// MaxConnectionAttempts is the max number of tries to allow
// when connecting to a reactor.
const MaxConnectionAttempts = 10
// Manager is an interface requiring a structure that can be started
// and stopped as well as provide timeouts in milliseconds.
type Manager interface {
Start() error // status checks
Stop() error
Timeout() (time.Duration, error) // TO Generator
}
// NewManager returns a manager fulfilling the Manager interface as well as
// any potential errors.
func NewManager(max int) (Manager, error) {
return manager.New(max)
}
// ReactorManager contains a base manager, client, global
// config, and error channel.
// The ReactorManager can be started/stopped as clients connect/disconnect.
// Also serves as handler for gRPC requests from reactors.
// Can be extended to write changes to config.
type ReactorManager struct {
Manager // base manager interface
*Client
Config *viper.Viper // global config to maintain
Err chan error
}
// NewReactorManager takes in a client, config and channel to pass errors on.
// Returns a new reactor manager as well as any errors that occured during
// creation.
// Uses MaxConnectionAttempts which defaults to 10 to prevent
// unnessecary network load and/or timeout lengths.
func NewReactorManager(
cl *Client,
config *viper.Viper,
errCh chan error,
) (*ReactorManager, error) {
m, err := NewManager(MaxConnectionAttempts)
if err != nil {
return &ReactorManager{}, err
}
r := &ReactorManager{
Manager: m,
Client: cl,
Config: config,
Err: errCh,
}
return r, err
}
// Start logs the start and calls start on the embedded manager.
func (r *ReactorManager) Start() error {
logging.Debug(logging.DStart, "RMA %v starting", r.Id)
return r.Manager.Start()
}
// Stop logs the stop and calls stop on the embedded manager.
func (r *ReactorManager) Stop() error {
logging.Debug(logging.DExit, "RMA %v stopping", r.Id)
return r.Manager.Stop()
}
// UpdateClient is used to change the underlying manager client if there
// changes to its data.
//
// BUG(Keegan): Client is not protected by a lock and may lead to races
func (r *ReactorManager) UpdateClient(cl *Client) error {
logging.Debug(logging.DClient, "RMA %v updating client", r.Id)
r.Client = cl
return nil
}
// ReactorStatusHandler implements a gRPC handler that is called by reactors.
// Takes in a context and request which has reactor and device information.
// For now, loops over devices and logs information about their status.
func (r *ReactorManager) ReactorStatusHandler(
ctx context.Context,
req *pb.ReactorStatusPing,
) (*pb.ReactorStatusResponse, error) {
logging.Debug(logging.DClient, "RMA %v recieved ping", r.Id)
for _, dev := range req.GetDevices() {
logging.Debug(
logging.DClient,
"RMA %v device %v is %v",
r.Id,
dev.GetAddr(),
dev.GetStatus().String(),
)
}
2 years ago
return &pb.ReactorStatusResponse{Id: int32(r.Id)}, nil
}