76 lines
3.1 KiB
Go
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
|
|
}
|