func (s *registrationServiceImpl) CreateInternalAgent(agentName string) (*InternalAgent, error) {
	agent := NewInternalAgent(agentName, s.initFlow, s.invokeFlow)
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if s.state != registrationServiceOn {
		return nil, ErrRegistrationServiceOff
	}
	if s.countAgentsUnsafe() >= MaxAgentsAllowed {
		return nil, ErrTooManyExtensions
	}
	if _, found := s.externalAgents.FindByName(agentName); found {
		return nil, ErrAgentNameCollision
	}
	if err := s.internalAgents.Insert(agent); err != nil {
		return nil, err
	}
	return agent, nil
}
CreateInternalAgent creates agent in agent collection
package core
import (
	"errors"
	"os"
	"sync"
	"go.amzn.com/lambda/appctx"
	"go.amzn.com/lambda/core/statejson"
	"github.com/google/uuid"
)
type registrationServiceState int
const (
	registrationServiceOn registrationServiceState = iota
	registrationServiceOff
)
const MaxAgentsAllowed = 10
type Event string
const (
	InvokeEvent Event = "INVOKE"
	ShutdownEvent Event = "SHUTDOWN"
)
var ErrRegistrationServiceOff = errors.New("ErrRegistrationServiceOff")
var ErrTooManyExtensions = errors.New("ErrTooManyExtensions")
type AgentInfoErrorType string
const (
	PermissionDenied  AgentInfoErrorType = "PermissionDenied"
	TooManyExtensions AgentInfoErrorType = "TooManyExtensions"
	UnknownError      AgentInfoErrorType = "UnknownError"
)
func MapErrorToAgentInfoErrorType(err error) AgentInfoErrorType {
	if os.IsPermission(err) {
		return PermissionDenied
	}
	if err == ErrTooManyExtensions {
		return TooManyExtensions
	}
	return UnknownError
}
type AgentInfo struct {
	Name          string
	State         string
	Subscriptions []string
	ErrorType     string
}
type FunctionMetadata struct {
	FunctionName    string
	FunctionVersion string
	Handler         string
}
type RegistrationService interface {
	CreateExternalAgent(agentName string) (*ExternalAgent, error)
	CreateInternalAgent(agentName string) (*InternalAgent, error)
	PreregisterRuntime(r *Runtime) error
	SetFunctionMetadata(metadata FunctionMetadata)
	GetFunctionMetadata() FunctionMetadata
	GetRuntime() *Runtime
	GetRegisteredAgentsSize() uint16
	FindExternalAgentByName(agentName string) (*ExternalAgent, bool)
	FindInternalAgentByName(agentName string) (*InternalAgent, bool)
	FindExternalAgentByID(agentID uuid.UUID) (*ExternalAgent, bool)
	FindInternalAgentByID(agentID uuid.UUID) (*InternalAgent, bool)
	TurnOff()
	InitFlow() InitFlowSynchronization
	GetInternalStateDescriptor(appCtx appctx.ApplicationContext) func() statejson.InternalStateDescription
	GetExternalAgents() []*ExternalAgent
	GetSubscribedExternalAgents(eventType Event) []*ExternalAgent
	GetSubscribedInternalAgents(eventType Event) []*InternalAgent
	CountAgents() int
	Clear()
	AgentsInfo() []AgentInfo
}
type registrationServiceImpl struct {
	runtime          *Runtime
	internalAgents   InternalAgentsMap
	externalAgents   ExternalAgentsMap
	state            registrationServiceState
	mutex            *sync.Mutex
	initFlow         InitFlowSynchronization
	invokeFlow       InvokeFlowSynchronization
	functionMetadata FunctionMetadata
}
func (s *registrationServiceImpl) Clear() {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	s.runtime = nil
	s.internalAgents.Clear()
	s.externalAgents.Clear()
	s.state = registrationServiceOn
}
func (s *registrationServiceImpl) InitFlow() InitFlowSynchronization {
	return s.initFlow
}
func (s *registrationServiceImpl) GetInternalStateDescriptor(appCtx appctx.ApplicationContext) func() statejson.InternalStateDescription {
	return func() statejson.InternalStateDescription {
		return s.getInternalStateDescription(appCtx)
	}
}
func (s *registrationServiceImpl) getInternalStateDescription(appCtx appctx.ApplicationContext) statejson.InternalStateDescription {
	isd := statejson.InternalStateDescription{
		Extensions: []statejson.ExtensionDescription{},
	}
	if s.runtime != nil {
		rtdesc := s.runtime.GetRuntimeDescription()
		isd.Runtime = &rtdesc
	}
	s.mutex.Lock()
	defer s.mutex.Unlock()
	s.internalAgents.Visit(func(agent *InternalAgent) {
		isd.Extensions = append(isd.Extensions, agent.GetAgentDescription())
	})
	s.externalAgents.Visit(func(agent *ExternalAgent) {
		isd.Extensions = append(isd.Extensions, agent.GetAgentDescription())
	})
	if fatalerror, found := appctx.LoadFirstFatalError(appCtx); found {
		isd.FirstFatalError = string(fatalerror)
	}
	return isd
}
func (s *registrationServiceImpl) CountAgents() int {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return s.countAgentsUnsafe()
}
func (s *registrationServiceImpl) countAgentsUnsafe() int {
	res := 0
	s.externalAgents.Visit(func(a *ExternalAgent) {
		res++
	})
	s.internalAgents.Visit(func(a *InternalAgent) {
		res++
	})
	return res
}
func (s *registrationServiceImpl) GetExternalAgents() []*ExternalAgent {
	agents := []*ExternalAgent{}
	s.externalAgents.Visit(func(a *ExternalAgent) {
		agents = append(agents, a)
	})
	return agents
}
func (s *registrationServiceImpl) GetInternalAgents() []*InternalAgent {
	agents := []*InternalAgent{}
	s.internalAgents.Visit(func(a *InternalAgent) {
		agents = append(agents, a)
	})
	return agents
}
func (s *registrationServiceImpl) GetSubscribedExternalAgents(eventType Event) []*ExternalAgent {
	agents := []*ExternalAgent{}
	s.externalAgents.Visit(func(a *ExternalAgent) {
		if a.IsSubscribed(eventType) {
			agents = append(agents, a)
		}
	})
	return agents
}
func (s *registrationServiceImpl) GetSubscribedInternalAgents(eventType Event) []*InternalAgent {
	agents := []*InternalAgent{}
	s.internalAgents.Visit(func(a *InternalAgent) {
		if a.IsSubscribed(eventType) {
			agents = append(agents, a)
		}
	})
	return agents
}
func (s *registrationServiceImpl) CreateExternalAgent(agentName string) (*ExternalAgent, error) {
	agent := NewExternalAgent(agentName, s.initFlow, s.invokeFlow)
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if s.state != registrationServiceOn {
		return nil, ErrRegistrationServiceOff
	}
	if _, found := s.internalAgents.FindByName(agentName); found {
		return nil, ErrAgentNameCollision
	}
	if err := s.externalAgents.Insert(agent); err != nil {
		return nil, err
	}
	return agent, nil
}