Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CORE-813] - Add pricefeed config tomls back into the repository #863

Merged
merged 5 commits into from
Dec 11, 2023

Conversation

clemire
Copy link
Contributor

@clemire clemire commented Dec 8, 2023

Changelist

Since the project work for adding a daemon config file will not be ready by the next release, add the pricefeed configuration toml back into the protocol for the next release so that the pricefeed daemon does not lose configurability.

This PR is a manually constructed reversion of this PR.

Test Plan

  • restored missing test cases
  • make localnet-start
  • modified localnet to start with a pricefeed config for only 1 exchange and confirmed that only one exchange was used via log statements

Author/Reviewer Checklist

  • If this PR has changes that result in a different app state given the same prior state and transaction list, manually add the state-breaking label.
  • If the PR has breaking postgres changes to the indexer add the indexer-postgres-breaking label.
  • If this PR isn't state-breaking but has changes that modify behavior in PrepareProposal or ProcessProposal, manually add the label proposal-breaking.
  • If this PR is one of many that implement a specific feature, manually label them all feature:[feature-name].
  • If you wish to for mergify-bot to automatically create a PR to backport your change to a release branch, manually add the label backport/[branch-name].
  • Manually add any of the following labels: refactor, chore, bug.

Copy link

linear bot commented Dec 8, 2023

Copy link
Contributor

coderabbitai bot commented Dec 8, 2023

Walkthrough

The recent changes involve the dynamic configuration of exchange query settings for a protocol. Instead of using a static configuration, the system now reads exchange query configurations from a file. Additionally, there's a new functionality to write a default configuration file if it doesn't exist. This is set up during the initialization phase of the application. The changes also include tests to ensure the new configuration functions work correctly and the necessary imports and constants to support these features.

Changes

File(s) Change Summary
protocol/app/app.go Modified to read exchange query configuration from a file instead of using a static constant.
protocol/cmd/dydxprotocold/cmd/init.go,
protocol/cmd/dydxprotocold/main.go
Added a PostRunE action to the init subcommand to write a default price feed exchange configuration file if it does not exist.
protocol/daemons/configs/default_pricefeed_exchange_config.go,
protocol/daemons/configs/default_pricefeed_exchange_config_test.go
Added functions for generating a default TOML configuration, writing it to a file, and reading the configuration from a file. Introduced new constants and imports to support these functionalities. Also added a new test package with functions to test the generation, writing, and reading of the exchange configuration file.
protocol/daemons/constants/pricefeed.go Added constants related to the price feed configuration file naming.
protocol/x/prices/client/cli/prices_cli_test.go Enhanced tests by adding a call to write the default price feed exchange configuration to a test directory.
protocol/testing/containertest/Dockerfile No logic or functionality modifications.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on X ?


Tips

Chat with CodeRabbit Bot (@coderabbitai)

  • If you reply to a review comment from CodeRabbit, the bot will automatically respond.
  • To engage with CodeRabbit bot directly around the specific lines of code in the PR, mention @coderabbitai in your review comment
  • Note: Review comments are made on code diffs or files, not on the PR overview.
  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Note: For conversation with the bot, please use the review comments on code diffs or files.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 10

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between fe82149 and e9a0e86.
Files ignored due to filter (6)
  • protocol/daemons/configs/test_data/broken_test.toml
  • protocol/daemons/configs/test_data/missingvals_test.toml
  • protocol/daemons/configs/test_data/valid_test.toml
  • protocol/daemons/configs/test_data/wrongvaltype_test.toml
  • protocol/go.mod
  • protocol/go.sum
Files selected for processing (7)
  • protocol/app/app.go (2 hunks)
  • protocol/cmd/dydxprotocold/cmd/init.go (1 hunks)
  • protocol/cmd/dydxprotocold/main.go (1 hunks)
  • protocol/daemons/configs/default_pricefeed_exchange_config.go (1 hunks)
  • protocol/daemons/configs/default_pricefeed_exchange_config_test.go (1 hunks)
  • protocol/daemons/constants/pricefeed.go (1 hunks)
  • protocol/testing/containertest/Dockerfile (1 hunks)
Files skipped from review due to trivial changes (2)
  • protocol/daemons/constants/pricefeed.go
  • protocol/testing/containertest/Dockerfile
Additional comments: 3
protocol/app/app.go (1)
  • 630-634: The changes from lines 630 to 634 correctly implement the logic to read the exchange query configuration from a file, which aligns with the PR's objective to reintroduce pricefeed configuration files and ensure they are properly integrated and tested.
protocol/cmd/dydxprotocold/cmd/init.go (1)
  • 25-25: The WriteDefaultPricefeedExchangeToml function is called without checking if the file already exists. According to the PR's objective and summary, the file should only be written if it does not exist. Ensure that the implementation of WriteDefaultPricefeedExchangeToml includes a check for the file's existence or add such a check before calling the function.
protocol/daemons/configs/default_pricefeed_exchange_config_test.go (1)
  • 112-119: The test TestGenerateDefaultExchangeTomlString correctly asserts that the generated TOML string matches the expected value. This ensures that the default configuration string is generated as intended.

protocol/cmd/dydxprotocold/cmd/init.go Show resolved Hide resolved
Comment on lines +133 to +146
func TestWriteDefaultPricefeedExchangeToml_FileExists(t *testing.T) {
helloWorld := "Hello World"

err := os.Mkdir("config", 0700)
require.NoError(t, err)

tmos.MustWriteFile(filePath, bytes.NewBuffer([]byte(helloWorld)).Bytes(), 0644)
configs.WriteDefaultPricefeedExchangeToml("")

buffer, err := os.ReadFile(filePath)
require.NoError(t, err)

require.Equal(t, helloWorld, string(buffer[:]))
os.RemoveAll("config")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test TestWriteDefaultPricefeedExchangeToml_FileExists checks the behavior when the file already exists. It's good to see that it verifies the file is not overwritten. However, the cleanup process is repeated across tests and could be refactored into a teardown function to adhere to the DRY principle.

+ func teardown() {
+     os.RemoveAll(configDir)
+ }
- os.RemoveAll("config")
+ teardown()

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
func TestWriteDefaultPricefeedExchangeToml_FileExists(t *testing.T) {
helloWorld := "Hello World"
err := os.Mkdir("config", 0700)
require.NoError(t, err)
tmos.MustWriteFile(filePath, bytes.NewBuffer([]byte(helloWorld)).Bytes(), 0644)
configs.WriteDefaultPricefeedExchangeToml("")
buffer, err := os.ReadFile(filePath)
require.NoError(t, err)
require.Equal(t, helloWorld, string(buffer[:]))
os.RemoveAll("config")
func TestWriteDefaultPricefeedExchangeToml_FileExists(t *testing.T) {
helloWorld := "Hello World"
err := os.Mkdir("config", 0700)
require.NoError(t, err)
tmos.MustWriteFile(filePath, bytes.NewBuffer([]byte(helloWorld)).Bytes(), 0644)
configs.WriteDefaultPricefeedExchangeToml("")
buffer, err := os.ReadFile(filePath)
require.NoError(t, err)
require.Equal(t, helloWorld, string(buffer[:]))
teardown()

</details>
<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->

protocol/cmd/dydxprotocold/main.go Show resolved Hide resolved
protocol/app/app.go Show resolved Hide resolved
Comment on lines +149 to +242
func TestReadExchangeStartupConfigFile(t *testing.T) {
pwd, _ := os.Getwd()

tests := map[string]struct {
// parameters
exchangeConfigSourcePath string
doNotWriteFile bool

// expectations
expectedExchangeId types.ExchangeId
expectedIntervalMsExchange uint32
expectedTimeoutMsExchange uint32
expectedMaxQueries uint32
expectedPanic error
}{
"valid": {
exchangeConfigSourcePath: "test_data/valid_test.toml",
expectedExchangeId: binanceId,
expectedIntervalMsExchange: pfconstants.StaticExchangeQueryConfig[binanceId].IntervalMs,
expectedTimeoutMsExchange: pfconstants.StaticExchangeQueryConfig[binanceId].TimeoutMs,
expectedMaxQueries: pfconstants.StaticExchangeQueryConfig[binanceId].MaxQueries,
},
"config file cannot be found": {
exchangeConfigSourcePath: "test_data/notexisting_test.toml",
doNotWriteFile: true,
expectedPanic: fmt.Errorf(
"open %s%s: no such file or directory",
pwd+"/config/",
constants.PricefeedExchangeConfigFileName,
),
},
"config file cannot be unmarshalled": {
exchangeConfigSourcePath: "test_data/broken_test.toml",
expectedPanic: errors.New("(1, 12): was expecting token [[, but got unclosed table array key instead"),
},
"config file has malformed values": {
exchangeConfigSourcePath: "test_data/missingvals_test.toml",
expectedPanic: errors.New(
"One or more query config values are unset or are set to zero for exchange with id: 'BinanceUS'",
),
},
"config file has incorrect values": {
exchangeConfigSourcePath: "test_data/wrongvaltype_test.toml",
expectedPanic: errors.New(
"(3, 1): Can't convert a(string) to uint32",
),
},
}

for name, tc := range tests {
t.Run(name, func(t *testing.T) {
if !tc.doNotWriteFile {
err := os.Mkdir("config", 0700)
require.NoError(t, err)

file, err := os.Open(tc.exchangeConfigSourcePath)
require.NoError(t, err)

config, err := os.Create(filepath.Join("config", constants.PricefeedExchangeConfigFileName))
require.NoError(t, err)
_, err = config.ReadFrom(file)
require.NoError(t, err)
}

if tc.expectedPanic != nil {
require.PanicsWithError(
t,
tc.expectedPanic.Error(),
func() { configs.ReadExchangeQueryConfigFile(pwd) },
)

os.RemoveAll("config")
return
}

exchangeStartupConfigMap := configs.ReadExchangeQueryConfigFile(pwd)

require.Equal(
t,
&types.ExchangeQueryConfig{
ExchangeId: tc.expectedExchangeId,
IntervalMs: tc.expectedIntervalMsExchange,
TimeoutMs: tc.expectedTimeoutMsExchange,
MaxQueries: tc.expectedMaxQueries,
},
exchangeStartupConfigMap[tc.expectedExchangeId],
)

os.RemoveAll("config")
})
}

// In case tests fail and the path was never removed.
os.RemoveAll("config")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test TestReadExchangeStartupConfigFile uses the current working directory to locate the configuration file, which may not be reliable in all environments. Consider using a more robust method to determine the project root or configuration path. Additionally, for better test isolation and to avoid side effects on the actual filesystem, consider using a mock filesystem or ioutil.TempDir to create temporary directories for testing.

- pwd, _ := os.Getwd()
+ tempDir, err := ioutil.TempDir("", "test")
+ require.NoError(t, err)
+ defer os.RemoveAll(tempDir) // cleanup after test

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
func TestReadExchangeStartupConfigFile(t *testing.T) {
pwd, _ := os.Getwd()
tests := map[string]struct {
// parameters
exchangeConfigSourcePath string
doNotWriteFile bool
// expectations
expectedExchangeId types.ExchangeId
expectedIntervalMsExchange uint32
expectedTimeoutMsExchange uint32
expectedMaxQueries uint32
expectedPanic error
}{
"valid": {
exchangeConfigSourcePath: "test_data/valid_test.toml",
expectedExchangeId: binanceId,
expectedIntervalMsExchange: pfconstants.StaticExchangeQueryConfig[binanceId].IntervalMs,
expectedTimeoutMsExchange: pfconstants.StaticExchangeQueryConfig[binanceId].TimeoutMs,
expectedMaxQueries: pfconstants.StaticExchangeQueryConfig[binanceId].MaxQueries,
},
"config file cannot be found": {
exchangeConfigSourcePath: "test_data/notexisting_test.toml",
doNotWriteFile: true,
expectedPanic: fmt.Errorf(
"open %s%s: no such file or directory",
pwd+"/config/",
constants.PricefeedExchangeConfigFileName,
),
},
"config file cannot be unmarshalled": {
exchangeConfigSourcePath: "test_data/broken_test.toml",
expectedPanic: errors.New("(1, 12): was expecting token [[, but got unclosed table array key instead"),
},
"config file has malformed values": {
exchangeConfigSourcePath: "test_data/missingvals_test.toml",
expectedPanic: errors.New(
"One or more query config values are unset or are set to zero for exchange with id: 'BinanceUS'",
),
},
"config file has incorrect values": {
exchangeConfigSourcePath: "test_data/wrongvaltype_test.toml",
expectedPanic: errors.New(
"(3, 1): Can't convert a(string) to uint32",
),
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
if !tc.doNotWriteFile {
err := os.Mkdir("config", 0700)
require.NoError(t, err)
file, err := os.Open(tc.exchangeConfigSourcePath)
require.NoError(t, err)
config, err := os.Create(filepath.Join("config", constants.PricefeedExchangeConfigFileName))
require.NoError(t, err)
_, err = config.ReadFrom(file)
require.NoError(t, err)
}
if tc.expectedPanic != nil {
require.PanicsWithError(
t,
tc.expectedPanic.Error(),
func() { configs.ReadExchangeQueryConfigFile(pwd) },
)
os.RemoveAll("config")
return
}
exchangeStartupConfigMap := configs.ReadExchangeQueryConfigFile(pwd)
require.Equal(
t,
&types.ExchangeQueryConfig{
ExchangeId: tc.expectedExchangeId,
IntervalMs: tc.expectedIntervalMsExchange,
TimeoutMs: tc.expectedTimeoutMsExchange,
MaxQueries: tc.expectedMaxQueries,
},
exchangeStartupConfigMap[tc.expectedExchangeId],
)
os.RemoveAll("config")
})
}
// In case tests fail and the path was never removed.
os.RemoveAll("config")
func TestReadExchangeStartupConfigFile(t *testing.T) {
tempDir, err := ioutil.TempDir("", "test")
require.NoError(t, err)
defer os.RemoveAll(tempDir) // cleanup after test
tests := map[string]struct {
// parameters
exchangeConfigSourcePath string
doNotWriteFile bool
// expectations
expectedExchangeId types.ExchangeId
expectedIntervalMsExchange uint32
expectedTimeoutMsExchange uint32
expectedMaxQueries uint32
expectedPanic error
}{
"valid": {
exchangeConfigSourcePath: "test_data/valid_test.toml",
expectedExchangeId: binanceId,
expectedIntervalMsExchange: pfconstants.StaticExchangeQueryConfig[binanceId].IntervalMs,
expectedTimeoutMsExchange: pfconstants.StaticExchangeQueryConfig[binanceId].TimeoutMs,
expectedMaxQueries: pfconstants.StaticExchangeQueryConfig[binanceId].MaxQueries,
},
"config file cannot be found": {
exchangeConfigSourcePath: "test_data/notexisting_test.toml",
doNotWriteFile: true,
expectedPanic: fmt.Errorf(
"open %s%s: no such file or directory",
tempDir+"/config/",
constants.PricefeedExchangeConfigFileName,
),
},
"config file cannot be unmarshalled": {
exchangeConfigSourcePath: "test_data/broken_test.toml",
expectedPanic: errors.New("(1, 12): was expecting token [[, but got unclosed table array key instead"),
},
"config file has malformed values": {
exchangeConfigSourcePath: "test_data/missingvals_test.toml",
expectedPanic: errors.New(
"One or more query config values are unset or are set to zero for exchange with id: 'BinanceUS'",
),
},
"config file has incorrect values": {
exchangeConfigSourcePath: "test_data/wrongvaltype_test.toml",
expectedPanic: errors.New(
"(3, 1): Can't convert a(string) to uint32",
),
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
if !tc.doNotWriteFile {
err := os.Mkdir(tempDir+"/config", 0700)
require.NoError(t, err)
file, err := os.Open(tc.exchangeConfigSourcePath)
require.NoError(t, err)
config, err := os.Create(filepath.Join(tempDir+"/config", constants.PricefeedExchangeConfigFileName))
require.NoError(t, err)
_, err = config.ReadFrom(file)
require.NoError(t, err)
}
if tc.expectedPanic != nil {
require.PanicsWithError(
t,
tc.expectedPanic.Error(),
func() { configs.ReadExchangeQueryConfigFile(tempDir) },
)
os.RemoveAll(tempDir + "/config")
return
}
exchangeStartupConfigMap := configs.ReadExchangeQueryConfigFile(tempDir)
require.Equal(
t,
&types.ExchangeQueryConfig{
ExchangeId: tc.expectedExchangeId,
IntervalMs: tc.expectedIntervalMsExchange,
TimeoutMs: tc.expectedTimeoutMsExchange,
MaxQueries: tc.expectedMaxQueries,
},
exchangeStartupConfigMap[tc.expectedExchangeId],
)
os.RemoveAll(tempDir + "/config")
})
}
// In case tests fail and the path was never removed.
os.RemoveAll(tempDir)
}

protocol/app/app.go Show resolved Hide resolved
Comment on lines +71 to +114
// ReadExchangeQueryConfigFile gets a mapping of `exchangeIds` to `ExchangeQueryConfigs`
// where `ExchangeQueryConfig` for querying exchanges for market prices comes from parsing a TOML
// file in the config directory.
// NOTE: if the config file is not found for the price-daemon, return the static exchange query
// config.
func ReadExchangeQueryConfigFile(homeDir string) map[types.ExchangeId]*types.ExchangeQueryConfig {
// Read file for exchange query configurations.
tomlFile, err := os.ReadFile(getConfigFilePath(homeDir))
if err != nil {
panic(err)
}

// Unmarshal `tomlFile` into `exchanges` for `exchangeStartupConfigMap`.
exchanges := map[string][]types.ExchangeQueryConfig{}
if err = toml.Unmarshal(tomlFile, &exchanges); err != nil {
panic(err)
}

// Populate configs for exchanges.
exchangeStartupConfigMap := make(map[types.ExchangeId]*types.ExchangeQueryConfig, len(exchanges))
for _, exchange := range exchanges["exchanges"] {
// Zero is an invalid configuration value for all parameters. This could also point to the
// configuration file being setup wrong with one or more exchange parameters unset.
if exchange.IntervalMs == 0 ||
exchange.TimeoutMs == 0 ||
exchange.MaxQueries == 0 {
panic(
fmt.Errorf(
"One or more query config values are unset or are set to zero for exchange with id: '%v'",
exchange.ExchangeId,
),
)
}

// Insert Key-Value pair into `exchangeStartupConfigMap`.
exchangeStartupConfigMap[exchange.ExchangeId] = &types.ExchangeQueryConfig{
ExchangeId: exchange.ExchangeId,
IntervalMs: exchange.IntervalMs,
TimeoutMs: exchange.TimeoutMs,
MaxQueries: exchange.MaxQueries,
}
}

return exchangeStartupConfigMap
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ReadExchangeQueryConfigFile function should not panic when encountering an error. Instead, it should return an error and allow the caller to handle it. This would improve error handling and make the code more robust and maintainable.

- func ReadExchangeQueryConfigFile(homeDir string) map[types.ExchangeId]*types.ExchangeQueryConfig {
+ func ReadExchangeQueryConfigFile(homeDir string) (map[types.ExchangeId]*types.ExchangeQueryConfig, error) {
  ...
-   panic(err)
+   return nil, err
  ...
-   panic(err)
+   return nil, err
  ...
-   panic(
+   return nil, fmt.Errorf(
  ...
-   )
+   )
  ...
-   return exchangeStartupConfigMap
+   return exchangeStartupConfigMap, nil
}

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// ReadExchangeQueryConfigFile gets a mapping of `exchangeIds` to `ExchangeQueryConfigs`
// where `ExchangeQueryConfig` for querying exchanges for market prices comes from parsing a TOML
// file in the config directory.
// NOTE: if the config file is not found for the price-daemon, return the static exchange query
// config.
func ReadExchangeQueryConfigFile(homeDir string) map[types.ExchangeId]*types.ExchangeQueryConfig {
// Read file for exchange query configurations.
tomlFile, err := os.ReadFile(getConfigFilePath(homeDir))
if err != nil {
panic(err)
}
// Unmarshal `tomlFile` into `exchanges` for `exchangeStartupConfigMap`.
exchanges := map[string][]types.ExchangeQueryConfig{}
if err = toml.Unmarshal(tomlFile, &exchanges); err != nil {
panic(err)
}
// Populate configs for exchanges.
exchangeStartupConfigMap := make(map[types.ExchangeId]*types.ExchangeQueryConfig, len(exchanges))
for _, exchange := range exchanges["exchanges"] {
// Zero is an invalid configuration value for all parameters. This could also point to the
// configuration file being setup wrong with one or more exchange parameters unset.
if exchange.IntervalMs == 0 ||
exchange.TimeoutMs == 0 ||
exchange.MaxQueries == 0 {
panic(
fmt.Errorf(
"One or more query config values are unset or are set to zero for exchange with id: '%v'",
exchange.ExchangeId,
),
)
}
// Insert Key-Value pair into `exchangeStartupConfigMap`.
exchangeStartupConfigMap[exchange.ExchangeId] = &types.ExchangeQueryConfig{
ExchangeId: exchange.ExchangeId,
IntervalMs: exchange.IntervalMs,
TimeoutMs: exchange.TimeoutMs,
MaxQueries: exchange.MaxQueries,
}
}
return exchangeStartupConfigMap
// ReadExchangeQueryConfigFile gets a mapping of `exchangeIds` to `ExchangeQueryConfigs`
// where `ExchangeQueryConfig` for querying exchanges for market prices comes from parsing a TOML
// file in the config directory.
// NOTE: if the config file is not found for the price-daemon, return the static exchange query
// config.
func ReadExchangeQueryConfigFile(homeDir string) (map[types.ExchangeId]*types.ExchangeQueryConfig, error) {
// Read file for exchange query configurations.
tomlFile, err := os.ReadFile(getConfigFilePath(homeDir))
if err != nil {
return nil, err
}
// Unmarshal `tomlFile` into `exchanges` for `exchangeStartupConfigMap`.
exchanges := map[string][]types.ExchangeQueryConfig{}
if err = toml.Unmarshal(tomlFile, &exchanges); err != nil {
return nil, err
}
// Populate configs for exchanges.
exchangeStartupConfigMap := make(map[types.ExchangeId]*types.ExchangeQueryConfig, len(exchanges))
for _, exchange := range exchanges["exchanges"] {
// Zero is an invalid configuration value for all parameters. This could also point to the
// configuration file being setup wrong with one or more exchange parameters unset.
if exchange.IntervalMs == 0 ||
exchange.TimeoutMs == 0 ||
exchange.MaxQueries == 0 {
return nil, fmt.Errorf(
"One or more query config values are unset or are set to zero for exchange with id: '%v'",
exchange.ExchangeId,
)
}
// Insert Key-Value pair into `exchangeStartupConfigMap`.
exchangeStartupConfigMap[exchange.ExchangeId] = &types.ExchangeQueryConfig{
ExchangeId: exchange.ExchangeId,
IntervalMs: exchange.IntervalMs,
TimeoutMs: exchange.TimeoutMs,
MaxQueries: exchange.MaxQueries,
}
}
return exchangeStartupConfigMap, nil
}

Copy link
Contributor Author

@clemire clemire Dec 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following two files were previously removed, and were added back in wholesale with the following caveat: the old ExchangeStartupConfig type was renamed to ExchangeQueryConfig, so I replaced Startup with Query everywhere in this file and the corresponding test file.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 1

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between e9a0e86 and 10b212f.
Files ignored due to filter (1)
  • protocol/testing/containertest/config/pricefeed_exchange_config.toml
Files selected for processing (1)
  • protocol/x/prices/client/cli/prices_cli_test.go (2 hunks)
Additional comments: 1
protocol/x/prices/client/cli/prices_cli_test.go (1)
  • 8-9: The addition of imports for configs and filepath aligns with the PR's objective to handle pricefeed configuration files.

Comment on lines +100 to +101
homeDir := filepath.Join(testval.Dir, "simd")
configs.WriteDefaultPricefeedExchangeToml(homeDir) // must manually create config file.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The call to configs.WriteDefaultPricefeedExchangeToml(homeDir) is added to set up the default TOML configuration. However, it appears that the return value, which likely includes an error, is not being checked. It is important to handle potential errors when writing files to ensure that the test setup does not proceed with invalid state.

+ homeDir := filepath.Join(testval.Dir, "simd")
+ err := configs.WriteDefaultPricefeedExchangeToml(homeDir) // must manually create config file.
+ s.Require().NoError(err)

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
homeDir := filepath.Join(testval.Dir, "simd")
configs.WriteDefaultPricefeedExchangeToml(homeDir) // must manually create config file.
homeDir := filepath.Join(testval.Dir, "simd")
err := configs.WriteDefaultPricefeedExchangeToml(homeDir) // must manually create config file.
s.Require().NoError(err)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 3

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 10b212f and 408cd53.
Files ignored due to filter (1)
  • protocol/go.mod
Files selected for processing (1)
  • protocol/daemons/configs/default_pricefeed_exchange_config_test.go (1 hunks)


var (
binanceId = exchange_common.EXCHANGE_ID_BINANCE
filePath = fmt.Sprintf("config/%v", constants.PricefeedExchangeConfigFileName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The filePath variable is still hardcoded, which could be refactored to use constants or a setup function for better maintainability. This is a follow-up on a previous comment that remains valid.

- filePath  = fmt.Sprintf("config/%v", constants.PricefeedExchangeConfigFileName)
+ const configDir = "config"
+ filePath  = fmt.Sprintf("%v/%v", configDir, constants.PricefeedExchangeConfigFileName)

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
filePath = fmt.Sprintf("config/%v", constants.PricefeedExchangeConfigFileName)
const configDir = "config"
filePath = fmt.Sprintf("%v/%v", configDir, constants.PricefeedExchangeConfigFileName)

require.NoError(t, err)

require.Equal(t, tomlString, string(buffer[:]))
os.RemoveAll("config")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cleanup process is repeated across tests and could be refactored into a teardown function to adhere to the DRY principle. This is a follow-up on a previous comment that remains valid.

+ func teardown() {
+     os.RemoveAll(configDir)
+ }
- os.RemoveAll("config")
+ teardown()

Also applies to: 151-151, 242-242, 247-247


Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
os.RemoveAll("config")
func teardown() {
os.RemoveAll(configDir)
}
teardown()

}

func TestReadExchangeStartupConfigFile(t *testing.T) {
pwd, _ := os.Getwd()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test TestReadExchangeStartupConfigFile uses the current working directory to locate the configuration file, which may not be reliable in all environments. Consider using a more robust method to determine the project root or configuration path. Additionally, for better test isolation and to avoid side effects on the actual filesystem, consider using a mock filesystem or ioutil.TempDir to create temporary directories for testing. This is a follow-up on a previous comment that remains valid.

- pwd, _ := os.Getwd()
+ tempDir, err := ioutil.TempDir("", "test")
+ require.NoError(t, err)
+ defer os.RemoveAll(tempDir) // cleanup after test

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
pwd, _ := os.Getwd()
tempDir, err := ioutil.TempDir("", "test")
require.NoError(t, err)
defer os.RemoveAll(tempDir) // cleanup after test

@clemire clemire merged commit 8b0e3ad into main Dec 11, 2023
15 of 16 checks passed
@clemire clemire deleted the crystal/CORE-813-restore-pricefeed-config branch December 11, 2023 21:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

2 participants