diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index 05295c1f..13ddedb7 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", } + // sovereign defines a flag that specifies if what run type components should use + sovereign = 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, + sovereign, } app.Authors = []cli.Author{ { @@ -372,6 +381,7 @@ func createVersionsRegistryTestOrProduction( statusMetricsHandler, ctx.GlobalString(walletKeyPemFile.Name), ctx.GlobalString(apiConfigDirectory.Name), + ctx.GlobalBool(sovereign.Name), closableComponents, ) } @@ -382,6 +392,7 @@ func createVersionsRegistryTestOrProduction( statusMetricsHandler, ctx.GlobalString(walletKeyPemFile.Name), ctx.GlobalString(apiConfigDirectory.Name), + ctx.GlobalBool(sovereign.Name), closableComponents, ) } @@ -392,6 +403,7 @@ func createVersionsRegistry( statusMetricsHandler data.StatusMetricsProvider, pemFileLocation string, apiConfigDirectoryPath string, + isSovereignConfig bool, closableComponents *data.ClosableComponentsHandler, ) (data.VersionsRegistryHandler, error) { pubKeyConverter, err := pubkeyConverter.NewBech32PubkeyConverter(cfg.AddressPubkeyConverter.Length, addressHRP) @@ -459,12 +471,23 @@ 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, hasher, marshalizer, cfg.GeneralSettings.AllowEntireTxPoolFetch, + runTypeComponents, ) if err != nil { return nil, err @@ -561,6 +584,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/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/errors.go b/factory/runType/errors.go new file mode 100644 index 00000000..657663a3 --- /dev/null +++ b/factory/runType/errors.go @@ -0,0 +1,7 @@ +package runType + +import ( + "errors" +) + +var errNilRunTypeComponents = errors.New("nil run type components") diff --git a/factory/runType/interface.go b/factory/runType/interface.go new file mode 100644 index 00000000..37448d92 --- /dev/null +++ b/factory/runType/interface.go @@ -0,0 +1,7 @@ +package runType + +// RunTypeComponentsCreator is the interface for creating run type components +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..0f2424d0 --- /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, 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 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..cfa94cec --- /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, errNilRunTypeComponents) + require.Nil(t, managedRunTypeComponents) + }) + 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, 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()) +} diff --git a/process/factory/transactionProcessorFactory.go b/process/factory/transactionProcessorFactory.go index 1055c1fd..8f563251 100644 --- a/process/factory/transactionProcessorFactory.go +++ b/process/factory/transactionProcessorFactory.go @@ -4,7 +4,9 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-proxy-go/facade" + "github.com/multiversx/mx-chain-proxy-go/factory" "github.com/multiversx/mx-chain-proxy-go/process" "github.com/multiversx/mx-chain-proxy-go/process/logsevents" "github.com/multiversx/mx-chain-proxy-go/process/txcost" @@ -17,6 +19,7 @@ func CreateTransactionProcessor( hasher hashing.Hasher, marshalizer marshal.Marshalizer, allowEntireTxPoolFetch bool, + runTypeComponents factory.RunTypeComponentsHolder, ) (facade.TransactionProcessor, error) { newTxCostProcessor := func() (process.TransactionCostHandler, error) { return txcost.NewTransactionCostProcessor(