diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index 05295c1f..aa93e4ad 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -19,10 +19,14 @@ import ( marshalFactory "github.com/multiversx/mx-chain-core-go/marshal/factory" logger "github.com/multiversx/mx-chain-logger-go" "github.com/multiversx/mx-chain-logger-go/file" + "github.com/urfave/cli" + "github.com/multiversx/mx-chain-proxy-go/api" "github.com/multiversx/mx-chain-proxy-go/common" "github.com/multiversx/mx-chain-proxy-go/config" "github.com/multiversx/mx-chain-proxy-go/data" + "github.com/multiversx/mx-chain-proxy-go/factory" + "github.com/multiversx/mx-chain-proxy-go/factory/runType" "github.com/multiversx/mx-chain-proxy-go/metrics" "github.com/multiversx/mx-chain-proxy-go/observer" "github.com/multiversx/mx-chain-proxy-go/process" @@ -30,7 +34,6 @@ import ( processFactory "github.com/multiversx/mx-chain-proxy-go/process/factory" "github.com/multiversx/mx-chain-proxy-go/testing" versionsFactory "github.com/multiversx/mx-chain-proxy-go/versions/factory" - "github.com/urfave/cli" ) const ( @@ -160,6 +163,11 @@ VERSION: Name: "start-swagger-ui", Usage: "If set to true, will start a Swagger UI on the root", } + // sovereignConfig defines a flag that specifies if what run type components should use + sovereignConfig = cli.BoolFlag{ + Name: "sovereign-config", + Usage: "If set to true, will use sovereign run type components", + } testServer *testing.TestHttpServer ) @@ -184,6 +192,7 @@ func main() { workingDirectory, memBallast, startSwaggerUI, + sovereignConfig, } app.Authors = []cli.Author{ { @@ -373,6 +382,7 @@ func createVersionsRegistryTestOrProduction( ctx.GlobalString(walletKeyPemFile.Name), ctx.GlobalString(apiConfigDirectory.Name), closableComponents, + ctx.GlobalBool(sovereignConfig.Name), ) } @@ -383,6 +393,7 @@ func createVersionsRegistryTestOrProduction( ctx.GlobalString(walletKeyPemFile.Name), ctx.GlobalString(apiConfigDirectory.Name), closableComponents, + ctx.GlobalBool(sovereignConfig.Name), ) } @@ -393,6 +404,7 @@ func createVersionsRegistry( pemFileLocation string, apiConfigDirectoryPath string, closableComponents *data.ClosableComponentsHandler, + isSovereignConfig bool, ) (data.VersionsRegistryHandler, error) { pubKeyConverter, err := pubkeyConverter.NewBech32PubkeyConverter(cfg.AddressPubkeyConverter.Length, addressHRP) if err != nil { @@ -459,6 +471,16 @@ func createVersionsRegistry( return nil, err } + var runTypeComponents factory.RunTypeComponentsHandler + if isSovereignConfig { + runTypeComponents, err = createManagedRunTypeComponents(runType.NewSovereignRunTypeComponentsFactory()) + } else { + runTypeComponents, err = createManagedRunTypeComponents(runType.NewRunTypeComponentsFactory()) + } + if err != nil { + return nil, err + } + txProc, err := processFactory.CreateTransactionProcessor( bp, pubKeyConverter, @@ -561,6 +583,20 @@ func createVersionsRegistry( return versionsFactory.CreateVersionsRegistry(facadeArgs, apiConfigParser) } +func createManagedRunTypeComponents(factory runType.RunTypeComponentsCreator) (factory.RunTypeComponentsHandler, error) { + managedRunTypeComponents, err := runType.NewManagedRunTypeComponents(factory) + if err != nil { + return nil, err + } + + err = managedRunTypeComponents.Create() + if err != nil { + return nil, err + } + + return managedRunTypeComponents, nil +} + func startWebServer( versionsRegistry data.VersionsRegistryHandler, generalConfig *config.Config, diff --git a/factory/errors.go b/factory/errors.go new file mode 100644 index 00000000..1b899847 --- /dev/null +++ b/factory/errors.go @@ -0,0 +1,8 @@ +package factory + +import ( + "errors" +) + +// ErrNilRunTypeComponents signals that nil run type components were provided +var ErrNilRunTypeComponents = errors.New("nil run type components") diff --git a/factory/interface.go b/factory/interface.go new file mode 100644 index 00000000..ae3435e6 --- /dev/null +++ b/factory/interface.go @@ -0,0 +1,24 @@ +package factory + +// ComponentHandler defines the actions common to all component handlers +type ComponentHandler interface { + Create() error + Close() error + CheckSubcomponents() error + String() string +} + +// RunTypeComponentsHandler defines the run type components handler actions +type RunTypeComponentsHandler interface { + ComponentHandler + RunTypeComponentsHolder +} + +// RunTypeComponentsHolder holds the run type components +type RunTypeComponentsHolder interface { + Create() error + Close() error + CheckSubcomponents() error + String() string + IsInterfaceNil() bool +} diff --git a/factory/runType/interface.go b/factory/runType/interface.go new file mode 100644 index 00000000..d749ae48 --- /dev/null +++ b/factory/runType/interface.go @@ -0,0 +1,7 @@ +package runType + +// RunTypeComponentsCreator is the interface for the runTypeComponentsCreator +type RunTypeComponentsCreator interface { + Create() *runTypeComponents + IsInterfaceNil() bool +} diff --git a/factory/runType/runTypeComponents.go b/factory/runType/runTypeComponents.go new file mode 100644 index 00000000..c960293b --- /dev/null +++ b/factory/runType/runTypeComponents.go @@ -0,0 +1,13 @@ +package runType + +type runTypeComponents struct{} + +// Close does nothing +func (rtc *runTypeComponents) Close() error { + return nil +} + +// IsInterfaceNil returns true if there is no value under the interface +func (rtc *runTypeComponents) IsInterfaceNil() bool { + return rtc == nil +} diff --git a/factory/runType/runTypeComponentsFactory.go b/factory/runType/runTypeComponentsFactory.go new file mode 100644 index 00000000..24ad9f56 --- /dev/null +++ b/factory/runType/runTypeComponentsFactory.go @@ -0,0 +1,18 @@ +package runType + +type runTypeComponentsFactory struct{} + +// NewRunTypeComponentsFactory will return a new instance of run type components factory +func NewRunTypeComponentsFactory() *runTypeComponentsFactory { + return &runTypeComponentsFactory{} +} + +// Create will create the run type components +func (rtcf *runTypeComponentsFactory) Create() *runTypeComponents { + return &runTypeComponents{} +} + +// IsInterfaceNil returns true if there is no value under the interface +func (rtcf *runTypeComponentsFactory) IsInterfaceNil() bool { + return rtcf == nil +} diff --git a/factory/runType/runTypeComponentsHandler.go b/factory/runType/runTypeComponentsHandler.go new file mode 100644 index 00000000..8f74e1a6 --- /dev/null +++ b/factory/runType/runTypeComponentsHandler.go @@ -0,0 +1,83 @@ +package runType + +import ( + "sync" + + "github.com/multiversx/mx-chain-core-go/core/check" + + "github.com/multiversx/mx-chain-proxy-go/factory" +) + +const runTypeComponentsName = "managedRunTypeComponents" + +var _ factory.ComponentHandler = (*managedRunTypeComponents)(nil) +var _ factory.RunTypeComponentsHandler = (*managedRunTypeComponents)(nil) +var _ factory.RunTypeComponentsHolder = (*managedRunTypeComponents)(nil) + +type managedRunTypeComponents struct { + *runTypeComponents + factory RunTypeComponentsCreator + mutRunTypeCoreComponents sync.RWMutex +} + +// NewManagedRunTypeComponents returns a news instance of managed runType core components +func NewManagedRunTypeComponents(rtc RunTypeComponentsCreator) (*managedRunTypeComponents, error) { + if rtc == nil { + return nil, factory.ErrNilRunTypeComponents + } + + return &managedRunTypeComponents{ + runTypeComponents: nil, + factory: rtc, + }, nil +} + +// Create will create the managed components +func (mrtc *managedRunTypeComponents) Create() error { + rtc := mrtc.factory.Create() + + mrtc.mutRunTypeCoreComponents.Lock() + mrtc.runTypeComponents = rtc + mrtc.mutRunTypeCoreComponents.Unlock() + + return nil +} + +// Close will close all underlying subcomponents +func (mrtc *managedRunTypeComponents) Close() error { + mrtc.mutRunTypeCoreComponents.Lock() + defer mrtc.mutRunTypeCoreComponents.Unlock() + + if check.IfNil(mrtc.runTypeComponents) { + return nil + } + + err := mrtc.runTypeComponents.Close() + if err != nil { + return err + } + mrtc.runTypeComponents = nil + + return nil +} + +// CheckSubcomponents verifies all subcomponents +func (mrtc *managedRunTypeComponents) CheckSubcomponents() error { + mrtc.mutRunTypeCoreComponents.RLock() + defer mrtc.mutRunTypeCoreComponents.RUnlock() + + if check.IfNil(mrtc.runTypeComponents) { + return factory.ErrNilRunTypeComponents + } + return nil +} + +// IsInterfaceNil returns true if the interface is nil +func (mrtc *managedRunTypeComponents) IsInterfaceNil() bool { + return mrtc == nil +} + +// String returns the name of the component +func (mrtc *managedRunTypeComponents) String() string { + return runTypeComponentsName +} diff --git a/factory/runType/runTypeComponentsHandler_test.go b/factory/runType/runTypeComponentsHandler_test.go new file mode 100644 index 00000000..b3f1bcfa --- /dev/null +++ b/factory/runType/runTypeComponentsHandler_test.go @@ -0,0 +1,76 @@ +package runType + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/multiversx/mx-chain-proxy-go/factory" +) + +func createComponents() (factory.RunTypeComponentsHandler, error) { + rtcf := NewRunTypeComponentsFactory() + return NewManagedRunTypeComponents(rtcf) +} + +func TestNewManagedRunTypeComponents(t *testing.T) { + t.Parallel() + + t.Run("should error", func(t *testing.T) { + managedRunTypeComponents, err := NewManagedRunTypeComponents(nil) + require.ErrorIs(t, err, factory.ErrNilRunTypeComponents) + require.True(t, managedRunTypeComponents.IsInterfaceNil()) + }) + t.Run("should work", func(t *testing.T) { + rtcf := NewRunTypeComponentsFactory() + managedRunTypeComponents, err := NewManagedRunTypeComponents(rtcf) + require.NoError(t, err) + require.False(t, managedRunTypeComponents.IsInterfaceNil()) + }) +} + +func TestManagedRunTypeComponents_Create(t *testing.T) { + t.Parallel() + + t.Run("should work with getters", func(t *testing.T) { + t.Parallel() + + managedRunTypeComponents, err := createComponents() + require.NoError(t, err) + + err = managedRunTypeComponents.Create() + require.NoError(t, err) + + require.Equal(t, runTypeComponentsName, managedRunTypeComponents.String()) + require.NoError(t, managedRunTypeComponents.Close()) + }) +} + +func TestManagedRunTypeComponents_Close(t *testing.T) { + t.Parallel() + + managedRunTypeComponents, _ := createComponents() + require.NoError(t, managedRunTypeComponents.Close()) + + err := managedRunTypeComponents.Create() + require.NoError(t, err) + + require.NoError(t, managedRunTypeComponents.Close()) +} + +func TestManagedRunTypeComponents_CheckSubcomponents(t *testing.T) { + t.Parallel() + + managedRunTypeComponents, _ := createComponents() + err := managedRunTypeComponents.CheckSubcomponents() + require.Equal(t, factory.ErrNilRunTypeComponents, err) + + err = managedRunTypeComponents.Create() + require.NoError(t, err) + + //TODO check for nil each subcomponent - MX-15371 + err = managedRunTypeComponents.CheckSubcomponents() + require.NoError(t, err) + + require.NoError(t, managedRunTypeComponents.Close()) +} diff --git a/factory/runType/runTypeComponents_test.go b/factory/runType/runTypeComponents_test.go new file mode 100644 index 00000000..07580802 --- /dev/null +++ b/factory/runType/runTypeComponents_test.go @@ -0,0 +1,38 @@ +package runType + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestNewRunTypeComponentsFactory(t *testing.T) { + t.Parallel() + + t.Run("should work", func(t *testing.T) { + rtc := NewRunTypeComponentsFactory() + require.NotNil(t, rtc) + }) +} + +func TestRunTypeComponentsFactory_Create(t *testing.T) { + t.Parallel() + + rtcf := NewRunTypeComponentsFactory() + require.NotNil(t, rtcf) + + rtc := rtcf.Create() + require.NotNil(t, rtc) +} + +func TestRunTypeComponentsFactory_Close(t *testing.T) { + t.Parallel() + + rtcf := NewRunTypeComponentsFactory() + require.NotNil(t, rtcf) + + rtc := rtcf.Create() + require.NotNil(t, rtc) + + require.NoError(t, rtc.Close()) +} diff --git a/factory/runType/sovereignRunTypeComponentsFactory.go b/factory/runType/sovereignRunTypeComponentsFactory.go new file mode 100644 index 00000000..fd5226a5 --- /dev/null +++ b/factory/runType/sovereignRunTypeComponentsFactory.go @@ -0,0 +1,18 @@ +package runType + +type sovereignRunTypeComponentsFactory struct{} + +// NewSovereignRunTypeComponentsFactory will return a new instance of sovereign run type components factory +func NewSovereignRunTypeComponentsFactory() *sovereignRunTypeComponentsFactory { + return &sovereignRunTypeComponentsFactory{} +} + +// Create will create the run type components +func (srtcf *sovereignRunTypeComponentsFactory) Create() *runTypeComponents { + return &runTypeComponents{} +} + +// IsInterfaceNil returns true if there is no value under the interface +func (srtcf *sovereignRunTypeComponentsFactory) IsInterfaceNil() bool { + return srtcf == nil +} diff --git a/factory/runType/sovereignRunTypeComponentsFactory_test.go b/factory/runType/sovereignRunTypeComponentsFactory_test.go new file mode 100644 index 00000000..a3e959b4 --- /dev/null +++ b/factory/runType/sovereignRunTypeComponentsFactory_test.go @@ -0,0 +1,19 @@ +package runType + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSovereignRunTypeComponentsFactory_CreateAndClose(t *testing.T) { + t.Parallel() + + srtcf := NewSovereignRunTypeComponentsFactory() + require.NotNil(t, srtcf) + + srtc := srtcf.Create() + require.NotNil(t, srtc) + + require.NoError(t, srtc.Close()) +}