func (c *agentClient) sendAsyncTaskMessage(method string, arguments []interface{}) (value map[string]interface{}, err error) { var response TaskResponse err = c.agentRequest.Send(method, arguments, &response) if err != nil { return value, bosherr.WrapErrorf(err, "Sending '%s' to the agent", method) } agentTaskID, err := response.TaskID() if err != nil { return value, bosherr.WrapError(err, "Getting agent task id") } sendErrors := 0 getTaskRetryable := boshretry.NewRetryable(func() (bool, error) { var response TaskResponse err = c.agentRequest.Send("get_task", []interface{}{agentTaskID}, &response) if err != nil { sendErrors++ shouldRetry := sendErrors <= c.toleratedErrorCount err = bosherr.WrapError(err, "Sending 'get_task' to the agent") msg := fmt.Sprintf("Error occured sending get_task. Error retry %d of %d", sendErrors, c.toleratedErrorCount) c.logger.Debug(c.logTag, msg, err) return shouldRetry, err } sendErrors = 0 c.logger.Debug(c.logTag, "get_task response value: %#v", response.Value) taskState, err := response.TaskState() if err != nil { return false, bosherr.WrapError(err, "Getting task state") } if taskState != "running" { var ok bool value, ok = response.Value.(map[string]interface{}) if !ok { c.logger.Warn(c.logTag, "Unable to parse get_task response value: %#v", response.Value) } return true, nil } return true, bosherr.Errorf("Task %s is still running", method) }) getTaskRetryStrategy := boshretry.NewUnlimitedRetryStrategy(c.getTaskDelay, getTaskRetryable, c.logger) // cannot call getTaskRetryStrategy.Try in the return statement due to gccgo // execution order issues: https://code.google.com/p/go/issues/detail?id=8698&thanks=8698&ts=1410376474 err = getTaskRetryStrategy.Try() return value, err }
func (p *provider) downloadRetryable(source Source) boshretry.Retryable { return boshretry.NewRetryable(func() (bool, error) { downloadedFile, err := p.fs.TempFile("tarballProvider") if err != nil { return true, bosherr.WrapError(err, "Unable to create temporary file") } defer func() { if err = p.fs.RemoveAll(downloadedFile.Name()); err != nil { p.logger.Warn(p.logTag, "Failed to remove downloaded file: %s", err.Error()) } }() response, err := p.httpClient.Get(source.GetURL()) if err != nil { return true, bosherr.WrapError(err, "Unable to download") } defer func() { if err = response.Body.Close(); err != nil { p.logger.Warn(p.logTag, "Failed to close download response body: %s", err.Error()) } }() _, err = io.Copy(downloadedFile, response.Body) if err != nil { return true, bosherr.WrapError(err, "Saving downloaded bits to temporary file") } downloadedSha1, err := p.sha1Calculator.Calculate(downloadedFile.Name()) if err != nil { return true, bosherr.WrapError(err, "Calculating sha1 for downloaded file") } if downloadedSha1 != source.GetSHA1() { return true, bosherr.Errorf("SHA1 of downloaded file '%s' does not match expected SHA1 '%s'", downloadedSha1, source.GetSHA1()) } err = p.cache.Save(downloadedFile.Name(), source) if err != nil { return true, bosherr.WrapError(err, "Saving downloaded file in cache") } return false, nil }) }
func (c *agentClient) GetState() (agentclient.AgentState, error) { var response StateResponse getStateRetryable := boshretry.NewRetryable(func() (bool, error) { err := c.agentRequest.Send("get_state", []interface{}{}, &response) if err != nil { return true, bosherr.WrapError(err, "Sending get_state to the agent") } return false, nil }) attemptRetryStrategy := boshretry.NewAttemptRetryStrategy(c.toleratedErrorCount+1, c.getTaskDelay, getStateRetryable, c.logger) err := attemptRetryStrategy.Try() if err != nil { return agentclient.AgentState{}, bosherr.WrapError(err, "Sending get_state to the agent") } agentState := agentclient.AgentState{ JobState: response.Value.JobState, } return agentState, err }