Defaults monitor retries to 3 retries @ 1s for the consul lock command.

This commit is contained in:
James Phillips 2016-01-05 18:34:22 -08:00
parent 4afeddacc8
commit 1d733f4c36
3 changed files with 98 additions and 18 deletions

View File

@ -24,6 +24,14 @@ const (
// lock-delay value of 15 seconds. This only affects locks and not // lock-delay value of 15 seconds. This only affects locks and not
// semaphores. // semaphores.
lockKillGracePeriod = 5 * time.Second lockKillGracePeriod = 5 * time.Second
// defaultMonitorRetry is the number of 500 errors we will tolerate
// before declaring the lock gone.
defaultMonitorRetry = 3
// defaultMonitorRetryTime is the amount of time to wait between
// retries.
defaultMonitorRetryTime = 1 * time.Second
) )
// LockCommand is a Command implementation that is used to setup // LockCommand is a Command implementation that is used to setup
@ -73,7 +81,8 @@ Options:
while monitoring the lock. This allows riding out brief while monitoring the lock. This allows riding out brief
periods of unavailability without causing leader periods of unavailability without causing leader
elections, but increases the amount of time required elections, but increases the amount of time required
to detect a lost lock in some cases. Defaults to 0. to detect a lost lock in some cases. Defaults to 3,
with a 1s wait between retries. Set to 0 to disable.
-verbose Enables verbose output -verbose Enables verbose output
` `
return strings.TrimSpace(helpText) return strings.TrimSpace(helpText)
@ -99,7 +108,7 @@ func (c *LockCommand) run(args []string, lu **LockUnlock) int {
cmdFlags.StringVar(&token, "token", "", "") cmdFlags.StringVar(&token, "token", "", "")
cmdFlags.BoolVar(&passStdin, "pass-stdin", false, "") cmdFlags.BoolVar(&passStdin, "pass-stdin", false, "")
cmdFlags.StringVar(&try, "try", "", "") cmdFlags.StringVar(&try, "try", "", "")
cmdFlags.IntVar(&retry, "monitor-retry", 0, "") cmdFlags.IntVar(&retry, "monitor-retry", defaultMonitorRetry, "")
cmdFlags.BoolVar(&c.verbose, "verbose", false, "") cmdFlags.BoolVar(&c.verbose, "verbose", false, "")
httpAddr := HTTPAddrFlag(cmdFlags) httpAddr := HTTPAddrFlag(cmdFlags)
if err := cmdFlags.Parse(args); err != nil { if err := cmdFlags.Parse(args); err != nil {
@ -271,9 +280,10 @@ func (c *LockCommand) setupLock(client *api.Client, prefix, name string,
c.Ui.Info(fmt.Sprintf("Setting up lock at path: %s", key)) c.Ui.Info(fmt.Sprintf("Setting up lock at path: %s", key))
} }
opts := api.LockOptions{ opts := api.LockOptions{
Key: key, Key: key,
SessionName: name, SessionName: name,
MonitorRetries: retry, MonitorRetries: retry,
MonitorRetryTime: defaultMonitorRetryTime,
} }
if oneshot { if oneshot {
opts.LockTryOnce = true opts.LockTryOnce = true
@ -304,10 +314,11 @@ func (c *LockCommand) setupSemaphore(client *api.Client, limit int, prefix, name
c.Ui.Info(fmt.Sprintf("Setting up semaphore (limit %d) at prefix: %s", limit, prefix)) c.Ui.Info(fmt.Sprintf("Setting up semaphore (limit %d) at prefix: %s", limit, prefix))
} }
opts := api.SemaphoreOptions{ opts := api.SemaphoreOptions{
Prefix: prefix, Prefix: prefix,
Limit: limit, Limit: limit,
SessionName: name, SessionName: name,
MonitorRetries: retry, MonitorRetries: retry,
MonitorRetryTime: defaultMonitorRetryTime,
} }
if oneshot { if oneshot {
opts.SemaphoreTryOnce = true opts.SemaphoreTryOnce = true

View File

@ -121,7 +121,7 @@ func TestLockCommand_Try_Semaphore(t *testing.T) {
} }
} }
func TestLockCommand_MonitorRetry_Lock(t *testing.T) { func TestLockCommand_MonitorRetry_Lock_Default(t *testing.T) {
a1 := testAgent(t) a1 := testAgent(t)
defer a1.Shutdown() defer a1.Shutdown()
waitForLeader(t, a1.httpAddr) waitForLeader(t, a1.httpAddr)
@ -130,7 +130,7 @@ func TestLockCommand_MonitorRetry_Lock(t *testing.T) {
c := &LockCommand{Ui: ui} c := &LockCommand{Ui: ui}
filePath := filepath.Join(a1.dir, "test_touch") filePath := filepath.Join(a1.dir, "test_touch")
touchCmd := fmt.Sprintf("touch '%s'", filePath) touchCmd := fmt.Sprintf("touch '%s'", filePath)
args := []string{"-http-addr=" + a1.httpAddr, "-monitor-retry=3", "test/prefix", touchCmd} args := []string{"-http-addr=" + a1.httpAddr, "test/prefix", touchCmd}
// Run the command. // Run the command.
var lu *LockUnlock var lu *LockUnlock
@ -148,12 +148,13 @@ func TestLockCommand_MonitorRetry_Lock(t *testing.T) {
if !ok { if !ok {
t.Fatalf("bad type") t.Fatalf("bad type")
} }
if opts.MonitorRetries != 3 { if opts.MonitorRetries != defaultMonitorRetry ||
t.Fatalf("bad: %d", opts.MonitorRetries) opts.MonitorRetryTime != defaultMonitorRetryTime {
t.Fatalf("bad: %#v", opts)
} }
} }
func TestLockCommand_MonitorRetry_Semaphore(t *testing.T) { func TestLockCommand_MonitorRetry_Semaphore_Default(t *testing.T) {
a1 := testAgent(t) a1 := testAgent(t)
defer a1.Shutdown() defer a1.Shutdown()
waitForLeader(t, a1.httpAddr) waitForLeader(t, a1.httpAddr)
@ -162,7 +163,7 @@ func TestLockCommand_MonitorRetry_Semaphore(t *testing.T) {
c := &LockCommand{Ui: ui} c := &LockCommand{Ui: ui}
filePath := filepath.Join(a1.dir, "test_touch") filePath := filepath.Join(a1.dir, "test_touch")
touchCmd := fmt.Sprintf("touch '%s'", filePath) touchCmd := fmt.Sprintf("touch '%s'", filePath)
args := []string{"-http-addr=" + a1.httpAddr, "-n=3", "-monitor-retry=3", "test/prefix", touchCmd} args := []string{"-http-addr=" + a1.httpAddr, "-n=3", "test/prefix", touchCmd}
// Run the command. // Run the command.
var lu *LockUnlock var lu *LockUnlock
@ -180,7 +181,74 @@ func TestLockCommand_MonitorRetry_Semaphore(t *testing.T) {
if !ok { if !ok {
t.Fatalf("bad type") t.Fatalf("bad type")
} }
if opts.MonitorRetries != 3 { if opts.MonitorRetries != defaultMonitorRetry ||
t.Fatalf("bad: %d", opts.MonitorRetries) opts.MonitorRetryTime != defaultMonitorRetryTime {
t.Fatalf("bad: %#v", opts)
}
}
func TestLockCommand_MonitorRetry_Lock_Arg(t *testing.T) {
a1 := testAgent(t)
defer a1.Shutdown()
waitForLeader(t, a1.httpAddr)
ui := new(cli.MockUi)
c := &LockCommand{Ui: ui}
filePath := filepath.Join(a1.dir, "test_touch")
touchCmd := fmt.Sprintf("touch '%s'", filePath)
args := []string{"-http-addr=" + a1.httpAddr, "-monitor-retry=9", "test/prefix", touchCmd}
// Run the command.
var lu *LockUnlock
code := c.run(args, &lu)
if code != 0 {
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
}
_, err := ioutil.ReadFile(filePath)
if err != nil {
t.Fatalf("err: %v", err)
}
// Make sure the monitor options were set correctly.
opts, ok := lu.rawOpts.(*api.LockOptions)
if !ok {
t.Fatalf("bad type")
}
if opts.MonitorRetries != 9 ||
opts.MonitorRetryTime != defaultMonitorRetryTime {
t.Fatalf("bad: %#v", opts)
}
}
func TestLockCommand_MonitorRetry_Semaphore_Arg(t *testing.T) {
a1 := testAgent(t)
defer a1.Shutdown()
waitForLeader(t, a1.httpAddr)
ui := new(cli.MockUi)
c := &LockCommand{Ui: ui}
filePath := filepath.Join(a1.dir, "test_touch")
touchCmd := fmt.Sprintf("touch '%s'", filePath)
args := []string{"-http-addr=" + a1.httpAddr, "-n=3", "-monitor-retry=9", "test/prefix", touchCmd}
// Run the command.
var lu *LockUnlock
code := c.run(args, &lu)
if code != 0 {
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
}
_, err := ioutil.ReadFile(filePath)
if err != nil {
t.Fatalf("err: %v", err)
}
// Make sure the monitor options were set correctly.
opts, ok := lu.rawOpts.(*api.SemaphoreOptions)
if !ok {
t.Fatalf("bad type")
}
if opts.MonitorRetries != 9 ||
opts.MonitorRetryTime != defaultMonitorRetryTime {
t.Fatalf("bad: %#v", opts)
} }
} }

View File

@ -70,7 +70,8 @@ The list of available flags are:
* `-monitor-retry` - Retry up to this number of times if Consul returns a 500 error * `-monitor-retry` - Retry up to this number of times if Consul returns a 500 error
while monitoring the lock. This allows riding out brief periods of unavailability while monitoring the lock. This allows riding out brief periods of unavailability
without causing leader elections, but increases the amount of time required without causing leader elections, but increases the amount of time required
to detect a lost lock in some cases. Defaults to 0. to detect a lost lock in some cases. Defaults to 3, with a 1s wait between retries.
Set to 0 to disable.
* `-verbose` - Enables verbose output. * `-verbose` - Enables verbose output.