Files
go-sip/internal/rpc/approved_control.go
T

76 lines
3.1 KiB
Go

package rpc
import (
"context"
"errors"
"strings"
agentpb "git.ipao.vip/rogee/go-sip/gen/agent"
"git.ipao.vip/rogee/go-sip/internal/agent"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// ApplyApprovedTaskControl applies a task-scoped control only for the active
// Dispatcher session. It deliberately has no external control command ID or
// revision CAS; repeated deliveries execute the control again.
func (s *Server) ApplyApprovedTaskControl(ctx context.Context, req *agentpb.ApplyApprovedTaskControlRequest) (*agentpb.ApplyApprovedTaskControlResponse, error) {
if s == nil || ctx == nil || req == nil || req.Meta == nil {
return nil, status.Error(codes.InvalidArgument, "approved task control requires a context and session metadata")
}
if err := s.authorize(ctx, req.Meta); err != nil {
return nil, err
}
dispatcherID, err := s.sessions.ApprovedDispatcher(req.Meta, s.now())
if err != nil {
return nil, err
}
if req.DispatcherId != dispatcherID {
return nil, status.Error(codes.PermissionDenied, "Dispatcher does not own the active Agent session")
}
if s.mode != "mock" && s.mode != "nonprod-real" {
return nil, status.Error(codes.FailedPrecondition, "approved task control requires an approved call mode")
}
if req.TenantId <= 0 || strings.TrimSpace(req.TaskId) == "" {
return nil, status.Error(codes.InvalidArgument, "approved task control identity is incomplete")
}
var action string
switch req.Action {
case agentpb.ControlAction_CONTROL_ACTION_PAUSE:
action = "pause"
case agentpb.ControlAction_CONTROL_ACTION_STOP:
action = "stop"
case agentpb.ControlAction_CONTROL_ACTION_RESUME:
action = "resume"
default:
return nil, status.Error(codes.InvalidArgument, "approved task control action is invalid")
}
var policy string
switch req.ActiveCallPolicy {
case agentpb.ActiveCallPolicy_ACTIVE_CALL_POLICY_HANGUP:
policy = "hangup"
case agentpb.ActiveCallPolicy_ACTIVE_CALL_POLICY_DRAIN:
policy = "drain"
case agentpb.ActiveCallPolicy_ACTIVE_CALL_POLICY_UNSPECIFIED:
default:
return nil, status.Error(codes.InvalidArgument, "approved task control policy is invalid")
}
if (action == "resume" && policy != "") || (action != "resume" && policy == "") {
return nil, status.Error(codes.InvalidArgument, "approved task control policy does not match action")
}
if s.approvedTaskCalls == nil {
return nil, status.Error(codes.FailedPrecondition, "Agent task-control adapter is unavailable")
}
if err := s.approvedTaskCalls.Apply(ctx, agent.TaskIdentity{DispatcherID: dispatcherID, TenantID: req.TenantId, TaskID: req.TaskId}, action, policy); err != nil {
switch {
case errors.Is(err, context.DeadlineExceeded):
return nil, status.Error(codes.DeadlineExceeded, "Agent task control timed out before calls ended")
case errors.Is(err, context.Canceled):
return nil, status.Error(codes.Canceled, "Agent task control interrupted before calls ended")
default:
return nil, status.Error(codes.FailedPrecondition, "Agent task control was not applied")
}
}
return &agentpb.ApplyApprovedTaskControlResponse{Accepted: true}, nil
}