-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
Bug fix for stale reads on server startup, take #2 #3154
Changes from 3 commits
72af7b9
44f5086
b3b2e9d
f658231
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -163,3 +163,42 @@ func TestRPC_blockingQuery(t *testing.T) { | |
} | ||
} | ||
} | ||
|
||
func TestReadyForConsistentReads(t *testing.T) { | ||
dir, s := testServerWithConfig(t, func(c *Config) { | ||
c.RPCHoldTimeout = 2 * time.Millisecond | ||
}) | ||
defer os.RemoveAll(dir) | ||
defer s.Shutdown() | ||
|
||
testrpc.WaitForLeader(t, s.RPC, "dc1") | ||
|
||
if !s.isReadyForConsistentReads() { | ||
t.Fatal("Server should be ready for consistent reads") | ||
} | ||
|
||
s.resetConsistentReadReady() | ||
|
||
if err := s.consistentRead(); err.Error() != "Not ready to serve consistent reads" { | ||
t.Fatal("Server should NOT be ready for consistent reads") | ||
} | ||
|
||
setConsistentFunc := func() { | ||
time.Sleep(2 * time.Millisecond) | ||
s.setConsistentReadReady() | ||
} | ||
|
||
go setConsistentFunc() | ||
|
||
//set some time to wait for the goroutine above to finish | ||
waitUntil := time.Now().Add(time.Millisecond * 5) | ||
err := s.consistentRead() | ||
for time.Now().Before(waitUntil) && err != nil { | ||
err = s.consistentRead() | ||
} | ||
|
||
if err != nil { | ||
t.Fatal("Expected server to be ready for consistent reads ") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be good to print the error in here. |
||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ import ( | |
"reflect" | ||
"strconv" | ||
"sync" | ||
"sync/atomic" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should get moved up after |
||
"time" | ||
|
||
"github.com/hashicorp/consul/acl" | ||
|
@@ -141,6 +142,9 @@ type Server struct { | |
// updated | ||
reconcileCh chan serf.Member | ||
|
||
// used to track when the server is ready to serve consistent reads, updated atomically | ||
readyForConsistentReads int32 | ||
|
||
// router is used to map out Consul servers in the WAN and in Consul | ||
// Enterprise user-defined areas. | ||
router *servers.Router | ||
|
@@ -1002,6 +1006,21 @@ func (s *Server) GetWANCoordinate() (*coordinate.Coordinate, error) { | |
return s.serfWAN.GetCoordinate() | ||
} | ||
|
||
// Atomically sets a readiness state flag when leadership is obtained, to indicate that server is past its barrier write | ||
func (s *Server) setConsistentReadReady() { | ||
atomic.StoreInt32(&s.readyForConsistentReads, 1) | ||
} | ||
|
||
// Atomically reset readiness state flag on leadership revoke | ||
func (s *Server) resetConsistentReadReady() { | ||
atomic.StoreInt32(&s.readyForConsistentReads, 0) | ||
} | ||
|
||
// Returns true if this server is ready to serve consistent reads | ||
func (s *Server) isReadyForConsistentReads() bool { | ||
return atomic.LoadInt32(&s.readyForConsistentReads) > 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this didn't end up as a counter I'd do |
||
} | ||
|
||
// peersInfoContent is used to help operators understand what happened to the | ||
// peers.json file. This is written to a file called peers.info in the same | ||
// location. | ||
|
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 could move the check from line 182 here to make sure we get that error initially.