Skip to content

Commit

Permalink
cleanup, enforce uniqueness of value ids at runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
Harry Rackmil authored and Harry Rackmil committed Jan 15, 2025
1 parent e1ace31 commit 5363606
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 13 deletions.
Empty file added apps/docs/data_provider.md
Empty file.
2 changes: 1 addition & 1 deletion apps/lib/data_provider/configs/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func TestValidConfig(t *testing.T) {
assert.NotNil(t, config3.Config)
}

func TestInvalidTopLevelConfigs(t *testing.T) {
func TestInvalidConfigs(t *testing.T) {
// unexpected field
configStr := `
{
Expand Down
5 changes: 4 additions & 1 deletion apps/lib/data_provider/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ func NewDataProviderRunner(dataProviderConfig types.DataProviderConfig, outputAd
}

func (r *DataProviderRunner) Run() {
dataSources := sources.BuildDataSources(r.config.Sources)
dataSources, err := sources.BuildDataSources(r.config.Sources)
if err != nil {
panic("unable to build data sources: " + err.Error())
}
for _, dataSource := range dataSources {
go dataSource.RunDataSource(r.updatesCh)
}
Expand Down
27 changes: 22 additions & 5 deletions apps/lib/data_provider/sources/data_source_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,19 @@ var dataSourceFactories = map[types.DataSourceId]types.DataSourceFactory{}

// Register a new factory for a specific DataSource type.
func RegisterDataSourceFactory(dataSourceId types.DataSourceId, factory types.DataSourceFactory) {
err := tryRegisterDataSourceFactory(dataSourceId, factory)
if err != nil {
panic(err)
}
}

// exposed for testing
func tryRegisterDataSourceFactory(dataSourceId types.DataSourceId, factory types.DataSourceFactory) error {
if _, exists := dataSourceFactories[dataSourceId]; exists {
panic(fmt.Sprintf("DataSourceFactory already registered for: %s", dataSourceId))
return fmt.Errorf("DataSourceFactory already registered for: %s", dataSourceId)
}
dataSourceFactories[dataSourceId] = factory
return nil
}

// Get a factory by dataSourceId.
Expand All @@ -26,19 +35,27 @@ func GetDataSourceFactory(dataSourceId types.DataSourceId) (types.DataSourceFact
return factory, nil
}

func BuildDataSources(sourceConfigs []types.DataProviderSourceConfig) []types.DataSource {
func BuildDataSources(sourceConfigs []types.DataProviderSourceConfig) ([]types.DataSource, error) {
dataSources := make([]types.DataSource, 0)
valueIds := make(map[types.ValueId]interface{})
for _, source := range sourceConfigs {
_, exists := valueIds[source.Id]
if exists {
return nil, fmt.Errorf("duplicate value id in config: %s", source.Id)
}
valueIds[source.Id] = nil

dataSourceId, err := utils.GetDataSourceId(source.Config)
if err != nil {
panic("unable to get data source id from source config " + string(source.Id) + ": " + err.Error())
return nil, fmt.Errorf("unable to get data source id from source config %s: %v", source.Id, err)
}
factory, err := GetDataSourceFactory(dataSourceId)
if err != nil {
panic(err)
return nil, fmt.Errorf("unable to get data source factory for data source id %s: %v", dataSourceId, err)
}
dataSource := factory.Build(source)
dataSources = append(dataSources, dataSource)

}
return dataSources
return dataSources, nil
}
44 changes: 44 additions & 0 deletions apps/lib/data_provider/sources/data_source_registry_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package sources

import (
"testing"

"github.com/Stork-Oracle/stork-external/apps/lib/data_provider/types"
"github.com/stretchr/testify/assert"
)

type fakeDataSourceFactory struct{}

func (*fakeDataSourceFactory) Build(config types.DataProviderSourceConfig) types.DataSource {
return nil
}

func TestDuplicateDataSourceId(t *testing.T) {
fakeDataSourceId := types.DataSourceId("fake_data_source_1")
err := tryRegisterDataSourceFactory(fakeDataSourceId, nil)
assert.NoError(t, err)
err = tryRegisterDataSourceFactory(fakeDataSourceId, nil)
assert.ErrorContains(t, err, "DataSourceFactory already registered for: fake_data_source_1")
}

func TestDuplicateValueId(t *testing.T) {
fakeDataSourceId := "fake_data_source_2"

RegisterDataSourceFactory(types.DataSourceId(fakeDataSourceId), &fakeDataSourceFactory{})
_, err := BuildDataSources([]types.DataProviderSourceConfig{
{
Id: "fake1",
Config: map[string]interface{}{
"dataSource": fakeDataSourceId,
},
},
{
Id: "fake1",
Config: map[string]interface{}{
"dataSource": fakeDataSourceId,
},
},
})

assert.ErrorContains(t, err, "duplicate value id in config: fake1")
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ func init() {
sources.RegisterDataSourceFactory(RandomDataSourceId, &randomDataSourceFactory{})
}

// assert we're satisfying our interfaces
var _ types.DataSource = (*randomDataSource)(nil)
var _ types.DataSourceFactory = (*randomDataSourceFactory)(nil)

func GetSourceSpecificConfig(sourceConfig types.DataProviderSourceConfig) (RandomConfig, error) {
var config RandomConfig
err := mapstructure.Decode(sourceConfig.Config, &config)
return config, err
}

var _ types.DataSource = (*randomDataSource)(nil)
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ func init() {
sources.RegisterDataSourceFactory(UniswapV2DataSourceId, &uniswapV2DataSourceFactory{})
}

var _ types.DataSource = (*uniswapV2DataSource)(nil)
var _ types.DataSourceFactory = (*uniswapV2DataSourceFactory)(nil)

func GetSourceSpecificConfig(sourceConfig types.DataProviderSourceConfig) (UniswapV2Config, error) {
var config UniswapV2Config
err := mapstructure.Decode(sourceConfig.Config, &config)
return config, err
}

var _ types.DataSource = (*uniswapV2DataSource)(nil)
13 changes: 11 additions & 2 deletions sample.data-provider.config.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
{
"sources": [
{
"id": "MY_RANDOM_VALUE",
"id": "BTCUSD",
"config": {
"dataSource": "random",
"updateFrequency": "1s",
"minValue": 2500,
"minValue": 50000,
"maxValue": 100000
}
},
{
"id": "ETHUSD",
"config": {
"dataSource": "random",
"updateFrequency": "10s",
"minValue": 2000,
"maxValue": 3000
}
}
Expand Down

0 comments on commit 5363606

Please sign in to comment.