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

Add redis sentinel support #161

Closed
wants to merge 2 commits into from

Conversation

cyrinux
Copy link

@cyrinux cyrinux commented Dec 11, 2023

Hi,

This PR do the following things:

  • Bump go-redis to v9
  • Support redis sentinel support

Thanks for the project.

@cyrinux cyrinux force-pushed the feat/support-redis-sentinel branch 3 times, most recently from 632ced9 to deb938c Compare December 11, 2023 15:20
@cyrinux cyrinux changed the title feat: add redis sentinel support feat: add redis sentinel support 5WIP) Dec 11, 2023
@cyrinux cyrinux changed the title feat: add redis sentinel support 5WIP) feat: add redis sentinel support (WIP) Dec 11, 2023
@cyrinux cyrinux force-pushed the feat/support-redis-sentinel branch 2 times, most recently from 0139e4d to 0a0db31 Compare December 11, 2023 15:30
@cyrinux cyrinux changed the title feat: add redis sentinel support (WIP) feat: add redis sentinel support Dec 11, 2023
@bsardo bsardo changed the title feat: add redis sentinel support Add redis sentinel support Dec 11, 2023
@cyrinux cyrinux force-pushed the feat/support-redis-sentinel branch 4 times, most recently from 518074e to 88d9616 Compare December 12, 2023 10:04
@cyrinux
Copy link
Author

cyrinux commented Dec 12, 2023

It should pass the tests now 😃

@cyrinux cyrinux force-pushed the feat/support-redis-sentinel branch from 88d9616 to b418372 Compare December 12, 2023 12:38
@cyrinux cyrinux force-pushed the feat/support-redis-sentinel branch from b418372 to 366fd2d Compare December 12, 2023 12:55
Copy link
Contributor

@sebmil-daily sebmil-daily left a comment

Choose a reason for hiding this comment

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

Validated in test environment

README.md Outdated Show resolved Hide resolved
README.md Outdated
| port | integer | Redis server port |
| host | string | Redis server URI (redis standalone mode) |
| port | integer | Redis server port (redis standalone mode) |
| hosts |string array | Redis server sentinel URI (redis sentinel mode)|
Copy link
Contributor

Choose a reason for hiding this comment

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

Both the name hosts and the description in the third column suggests that host and hosts have the same format but, the SentinelAddrs field is a list of host:port strings.

19 // FailoverOptions are used to configure a failover client and should
20 // be passed to NewFailoverClient.
21 type FailoverOptions struct {
22     // The master name.
23     MasterName string
24     // A seed list of host:port addresses of sentinel nodes.
25     SentinelAddrs []string
26
/newgo/pkg/mod/github.com/redis/go-redis/v9@v9.3.0/sentinel.go

Should we modify the description to mention the formatting difference with host? Or add a separate array called ports?

246   | Configuration field | Type | Description |                             
247   | --- | --- | --- |                                                      
248   | host | string | Redis server URI (redis standalone mode) |             
249   | port | integer | Redis server port (redis standalone mode) |           
250   | hosts |string array | Redis server sentinel URI (redis sentinel mode)| 
    + | ports |integer array | Redis server sentinel port (redis sentinel mode)| 
251   | mastername | string | Redis master sentinel name (redis sentinel mode)|
README.md

I lean more towards modifiying the description to explain the difference and even rename this variable. I'm not great at naming. sentinel_hosts_ports maybe?

246   | Configuration field | Type | Description |                             
247   | --- | --- | --- |                                                      
248   | host | string | Redis server URI (redis standalone mode) |             
249   | port | integer | Redis server port (redis standalone mode) |           
250 - | hosts |string array | Redis server sentinel URI (redis sentinel mode)| 
    + | sentinel_hosts_ports | string array | Redis server sentinel host:port list (redis sentinel mode)| 
251   | mastername | string | Redis master sentinel name (redis sentinel mode)|
README.md

Thoughts?

Copy link
Author

Choose a reason for hiding this comment

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

I will go for sentinel_hosts_ports and sentinel_mastername so. I'm agree with that.

I tried to do breaking change and want to keep host and port for redis mode. And in general in others backends, its common to use hosts that take a list of host:port.

config/backends.go Outdated Show resolved Hide resolved
@@ -149,6 +149,8 @@ func TestNewBaseBackend(t *testing.T) {
desc: "Redis",
inConfig: config.Backend{Type: config.BackendRedis},
expectedLogEntries: []logEntry{
{msg: "Error creating Redis backend: At least one Host[s] is required.", lvl: logrus.FatalLevel},
{msg: "Creating Redis backend", lvl: logrus.InfoLevel},
{msg: "Error creating Redis backend: ", lvl: logrus.FatalLevel},
Copy link
Contributor

Choose a reason for hiding this comment

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

In practice, logrus.FatalLevel stops execution. Under this scenario, we would only see the first entry in the logs:

148         {
149             desc:     "Redis",
150             inConfig: config.Backend{Type: config.BackendRedis},
151             expectedLogEntries: []logEntry{
152                 {msg: "Error creating Redis backend: At least one Host[s] is required.", lvl: logrus.FatalLevel},
153 -               {msg: "Creating Redis backend", lvl: logrus.InfoLevel},
154 -               {msg: "Error creating Redis backend: ", lvl: logrus.FatalLevel},
155             },
156         },
backends/config/config_test.go

Copy link
Author

Choose a reason for hiding this comment

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

I thought the same but without those three items the test fail.

Copy link
Contributor

@sebmil-daily sebmil-daily Dec 13, 2023

Choose a reason for hiding this comment

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

It's because the test function disables the logrus exit functions, so we can have as many log.Fatalf calls without interrupting the test:

func TestNewBaseBackend(t *testing.T) {
	// logrus entries will be recorded to this `hook` object so we can compare and assert them
	hook := logrusTest.NewGlobal()
	defer func() { logrus.StandardLogger().ExitFunc = nil }()
	logrus.StandardLogger().ExitFunc = func(int) {}

Copy link
Author

Choose a reason for hiding this comment

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

Good catch, thanks @sebmil-daily

@@ -1202,6 +1202,7 @@ func getExpectedDefaultConfig() Configuration {
DefaultTTL: utils.CASSANDRA_DEFAULT_TTL_SECONDS,
},
Redis: Redis{
Hosts: []string{},
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need this. The test is able to pass without it.

Copy link
Author

Choose a reason for hiding this comment

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

I beat a lot to find what was wrong before I explicit declare this here.
Without, it fail because the array is nil.

@cyrinux cyrinux force-pushed the feat/support-redis-sentinel branch from dfd0ac3 to b9f0ed2 Compare December 13, 2023 07:33
@cyrinux cyrinux force-pushed the feat/support-redis-sentinel branch from b9f0ed2 to 6cbdc16 Compare December 13, 2023 07:52
@bsardo
Copy link
Collaborator

bsardo commented Dec 13, 2023

Hi @cyrinux, if you don't mind, going forward could you please avoid force pushes and instead just add additional commits when making updates? It saves us review time since we can then just review the delta. Thanks!

@cyrinux
Copy link
Author

cyrinux commented Dec 13, 2023

Hi @cyrinux, if you don't mind, going forward could you please avoid force pushes and instead just add additional commits when making updates? It saves us review time since we can then just review the delta. Thanks!

Sure, I understand no problems. I don't touch anymore now. Waiting for you now 😉

Copy link
Contributor

@guscarreon guscarreon left a comment

Choose a reason for hiding this comment

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

There's still an error in a test case, hence the validation didn't pass. Can we please fix?
Otherwise, it's looking pretty good.

log.Infof("config.backend.redis.port: %d", cfg.Port)
if cfg.Host != "" && len(cfg.SentinelHostsPorts) > 0 {
log.Infof("config.backend.redis.sentinel_hosts_ports: %s. Note that redis 'host' will be ignore if 'sentinel_hosts_ports' is define", cfg.SentinelHostsPorts)
log.Infof("config.backend.redis.sentinel_mastername: %s.", cfg.SentinelMasterName)
Copy link
Contributor

Choose a reason for hiding this comment

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

@cyrinux thank you for your addresing our feedback. When we want to configure Redis in Sentinel mode, is SentinelMasterName a required field? In other words, if len(cfg.SentinelHostsPorts) > 0 is true, do we also need cfg.SentinelMasterName to not be empty?

If we do, then I believe an extra cfg.SentinelMasterName != "" check should be added in case len(cfg.SentinelHostsPorts) > 0 is found to be true and log.Infof() or error out accordingly.

Thoughts?

@sebmil-daily
Copy link
Contributor

sebmil-daily commented Dec 15, 2023

Hey @guscarreon , considering those points:

  • we have several duplicates in the configuration options between redis standalone and redis sentinel
  • even with the sentinel prefix, we are adding a lot of complexity in the redis backend configuration
  • it's not clear for the user which ones are mandatory in each case
  • there are more sentinel-specific options that we don't yet support
  • most of the redis backend code base is only for configuration and initialization

I suggest we cancel this PR for now and we'll come back with a new one that will introduce redis-sentinel as a whole new backend. It will ensure we are not creating any risk with the current redis (standalone) backend and it'll be more clear both for the users and for future development to have a separated configuration structure and validation.

What do you think?

(@cyrinux and me are working in the same company and we already agreed on this)

@guscarreon
Copy link
Contributor

I suggest we cancel this PR for now and we'll come back with a new one that will introduce redis-sentinel as a whole new backend

I agree. Let's close this PR now and will keep an eye for your upcoming Redis entinel adapter PR.

@cyrinux cyrinux closed this Dec 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants