-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
cockroachdb: add high-availability support #12965
Conversation
Hi there! Thanks for this submission. Please sign the CLA, and we can get this into review. :) |
99c383b
to
89d07f6
Compare
89d07f6
to
86d3887
Compare
Hi @hsimon-hashicorp , is there anything I can help with to get the review process rolling on this PR? |
Hi there @DuskEagle - I'll nudge our engineers about this again. Thanks for your patience. :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor comments/questions, overall it's looking good.
physical/cockroachdb/cockroachdb.go
Outdated
@@ -51,6 +56,11 @@ func NewCockroachDBBackend(conf map[string]string, logger log.Logger) (physical. | |||
return nil, fmt.Errorf("missing connection_url") | |||
} | |||
|
|||
var haEnabled bool | |||
if haEnabledStr, ok := conf["ha_enabled"]; ok && haEnabledStr == "true" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine as is, but since in Go an absent key looked up in a map results in the zero value, and this is a map[string]string, you can just say haEnabled = conf["ha_enabled"] == "true"
if you want to be a bit more succinct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I've made the change.
physical/cockroachdb/cockroachdb.go
Outdated
" UPDATE SET (ha_identity, ha_key, ha_value, valid_until) = ($1, $2, $3, NOW() + $4) " + | ||
" WHERE (t.valid_until < NOW() AND t.ha_key = $2) OR " + | ||
" (t.ha_identity = $1 AND t.ha_key = $2) ", | ||
"delete": "DELETE FROM " + dbHATable + " WHERE ha_identity = $1 AND ha_key = $2", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't hurt to do it this way, and I know you're basing this on the PG storage which does this. But I realized today that we don't need to include ha_identity in this DELETE, since there's a unique index on ha_key. So if you want you could remove that part of the WHERE clause.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point! I've removed that part of the where clause.
"upsert": "INSERT INTO " + dbHATable + " as t (ha_identity, ha_key, ha_value, valid_until)" + | ||
" VALUES ($1, $2, $3, NOW() + $4) " + | ||
" ON CONFLICT (ha_key) DO " + | ||
" UPDATE SET (ha_identity, ha_key, ha_value, valid_until) = ($1, $2, $3, NOW() + $4) " + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know little about CockroachDB, but I thought it was fully compatible with PG. You've been diligent about adapting the PG approach here, but I noticed this one discrepancy: instead of NOW() + $4 * INTERVAL '1 seconds'
you have simply NOW() + $4
. Why's that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's happening here is that $4
is being passed in as a string type, not an integer type. When we attempt to to $4 * INTERVAL '1 seconds'
, we get a conversion error:
ERROR: unsupported binary operator: <string> * <interval> (desired <interval>)
SQLSTATE: 22023
We would have the option of casting $4
to an integer, and then multiplying by an interval: NOW() + $4::int * INTERVAL '1 seconds'
.
However, $4 is already a value in seconds, and so casting to an int just to multiply by 1 second is unnecessary. It's more succinct to just add the string value directly to NOW()
.
86d3887
to
de341b4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for the delay. I've addressed your comments now :).
physical/cockroachdb/cockroachdb.go
Outdated
@@ -51,6 +56,11 @@ func NewCockroachDBBackend(conf map[string]string, logger log.Logger) (physical. | |||
return nil, fmt.Errorf("missing connection_url") | |||
} | |||
|
|||
var haEnabled bool | |||
if haEnabledStr, ok := conf["ha_enabled"]; ok && haEnabledStr == "true" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I've made the change.
physical/cockroachdb/cockroachdb.go
Outdated
" UPDATE SET (ha_identity, ha_key, ha_value, valid_until) = ($1, $2, $3, NOW() + $4) " + | ||
" WHERE (t.valid_until < NOW() AND t.ha_key = $2) OR " + | ||
" (t.ha_identity = $1 AND t.ha_key = $2) ", | ||
"delete": "DELETE FROM " + dbHATable + " WHERE ha_identity = $1 AND ha_key = $2", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point! I've removed that part of the where clause.
"upsert": "INSERT INTO " + dbHATable + " as t (ha_identity, ha_key, ha_value, valid_until)" + | ||
" VALUES ($1, $2, $3, NOW() + $4) " + | ||
" ON CONFLICT (ha_key) DO " + | ||
" UPDATE SET (ha_identity, ha_key, ha_value, valid_until) = ($1, $2, $3, NOW() + $4) " + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's happening here is that $4
is being passed in as a string type, not an integer type. When we attempt to to $4 * INTERVAL '1 seconds'
, we get a conversion error:
ERROR: unsupported binary operator: <string> * <interval> (desired <interval>)
SQLSTATE: 22023
We would have the option of casting $4
to an integer, and then multiplying by an interval: NOW() + $4::int * INTERVAL '1 seconds'
.
However, $4 is already a value in seconds, and so casting to an int just to multiply by 1 second is unnecessary. It's more succinct to just add the string value directly to NOW()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! I have a couple of comments that you can choose to address, or not: I'm willing to merge regardless. Let me know how you'd like to proceed.
|
||
var ( | ||
success = make(chan struct{}) | ||
errors = make(chan error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might want to make this channel buffered. I saw some output from a static analysis tool recently showing that in the PG implementation, there's an issue here when tryToLock attempts to write to the error channel, but Lock has already returned due to stopCh being closed. In addition, you could make that write to the error channel in Lock tolerate blockage by using the optional send syntax.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've taken your suggestions and made the channel buffered and the send non-blocking.
@@ -33,7 +34,15 @@ func prepareCockroachDBTestContainer(t *testing.T) (func(), *Config) { | |||
if tableName == "" { | |||
tableName = defaultTableName | |||
} | |||
return func() {}, &Config{*s, "vault." + tableName} | |||
haTableName := os.Getenv("CR_HA_TABLE") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need Getenv in this test. I know it's present in some of the existing tests, but it's vestigial mostly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed the os.Getenv
calls for the CR_TABLE
and CR_HA_TABLE
environment variables, so the tests will use the default values.
This commit adds high-availability support to the CockroachDB backend. The locking strategy implemented is heavily influenced from the very similar Postgres backend.
de341b4
to
66e3575
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review! I've made the changes you recommend, if they look good to you I'd like to see this merged :).
|
||
var ( | ||
success = make(chan struct{}) | ||
errors = make(chan error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've taken your suggestions and made the channel buffered and the send non-blocking.
@@ -33,7 +34,15 @@ func prepareCockroachDBTestContainer(t *testing.T) (func(), *Config) { | |||
if tableName == "" { | |||
tableName = defaultTableName | |||
} | |||
return func() {}, &Config{*s, "vault." + tableName} | |||
haTableName := os.Getenv("CR_HA_TABLE") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed the os.Getenv
calls for the CR_TABLE
and CR_HA_TABLE
environment variables, so the tests will use the default values.
Not sure why those PG tests are failing in the remote-docker CI tests, but I'm confident it's unrelated to these changes. |
Thanks @DuskEagle ! |
Thank you @ncabatoff ! |
HA support for CockroachDB was added in hashicorp#12965. This commit updates the docs to reflect that support.
HA support for CockroachDB was added in #12965. This commit updates the docs to reflect that support.
This commit adds high-availability support to the CockroachDB backend. The
locking strategy implemented is heavily influenced from the very similar
Postgres backend.