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

Remove extra API call when retrieving latest backup and import Statuses #193

Merged
merged 2 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
All notable changes to this project will be documented in this file.
See updating [Changelog example here](https://keepachangelog.com/en/1.0.0/).

## 0.21.0

### Added

* Handling API rate limits to wait or retry calls depending on the current window or remaining limits.

### Fixed

* Removed extra API call when retrieving latest backup and import Statuses.

## 0.8.0

### Added
Expand Down
4 changes: 2 additions & 2 deletions internal/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ type Error struct {
Status *string `json:"status,omitempty"`
}

func (o Error) String() string {
return ToString(o)
func (e Error) String() string {
return ToString(e)
}

func (e *Error) StatusCode() string {
Expand Down
46 changes: 2 additions & 44 deletions internal/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,56 +115,14 @@ func (a *api) waitForTaskToComplete(ctx context.Context, id string) (*Task, erro
a.logger.Println(err)
}))
if err != nil {
return nil, err
return task, err
}

return task, nil
}

func (a *api) WaitForTask(ctx context.Context, id string) (*Task, error) {
var task *Task
notFoundCount := 0
err := retry.Do(
func() error {
var err error
task, err = a.get(ctx, id)
if err != nil {
// An error is a terminal state (any repeated pre-task 404s will have been exhausted by this point)
return nil
}

status := redis.StringValue(task.Status)

if _, ok := processingStates[status]; !ok {
// The task is no longer processing for whatever reason
return nil
}

return fmt.Errorf("task %s not processed yet: %s", id, status)
},
retry.Attempts(math.MaxUint16),
retry.Delay(1*time.Second),
retry.MaxDelay(30*time.Second),
retry.RetryIf(func(err error) bool {
if !retry.IsRecoverable(err) {
return false
}
if _, ok := err.(*taskNotFoundError); ok {
notFoundCount++
if notFoundCount > max404Errors {
return false
}
}
return true
}),
retry.LastErrorOnly(true), retry.Context(ctx), retry.OnRetry(func(_ uint, err error) {
a.logger.Println(err)
}))
if err != nil {
return nil, err
}

return task, nil
return a.waitForTaskToComplete(ctx, id)
}

func (a *api) get(ctx context.Context, id string) (*Task, error) {
Expand Down
88 changes: 16 additions & 72 deletions latest_backups_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,29 +57,6 @@ func TestGetLatestBackup(t *testing.T) {
]
}`,
),
getRequest(
t,
"/tasks/50ec6172-8475-4ef6-8b3c-d61e688d8fe5",
`{
"taskId": "50ec6172-8475-4ef6-8b3c-d61e688d8fe5",
"commandType": "databaseBackupStatusRequest",
"status": "processing-completed",
"description": "Request processing completed successfully and its resources are now being provisioned / de-provisioned.",
"timestamp": "2024-04-15T09:08:07.537915Z",
"response": {
"resourceId": 51051292,
"additionalResourceId": 12,
"resource": {}
},
"links": [
{
"href": "https://api-staging.qa.redislabs.com/v1/tasks/50ec6172-8475-4ef6-8b3c-d61e688d8fe5",
"type": "GET",
"rel": "self"
}
]
}`,
),
))

subject, err := clientFromTestServer(server, "key", "secret")
Expand Down Expand Up @@ -135,29 +112,6 @@ func TestGetFixedLatestBackup(t *testing.T) {
]
}`,
),
getRequest(
t,
"/tasks/ce2cbfea-9b15-4250-a516-f014161a8dd3",
`{
"taskId": "ce2cbfea-9b15-4250-a516-f014161a8dd3",
"commandType": "databaseBackupStatusRequest",
"status": "processing-completed",
"description": "Request processing completed successfully and its resources are now being provisioned / de-provisioned.",
"timestamp": "2024-04-15T09:52:26.101936Z",
"response": {
"resource": {
"status": "success"
}
},
"links": [
{
"href": "https://api-staging.qa.redislabs.com/v1/tasks/ce2cbfea-9b15-4250-a516-f014161a8dd3",
"type": "GET",
"rel": "self"
}
]
}`,
),
))

subject, err := clientFromTestServer(server, "key", "secret")
Expand Down Expand Up @@ -230,36 +184,26 @@ func TestGetAALatestBackup(t *testing.T) {
]
}`,
),
getRequest(
t,
"/tasks/ce2cbfea-9b15-4250-a516-f014161a8dd3",
`{
"taskId": "ce2cbfea-9b15-4250-a516-f014161a8dd3",
"commandType": "databaseBackupStatusRequest",
"status": "processing-error",
"description": "Task request failed during processing. See error information for failure details.",
"timestamp": "2024-04-15T09:52:26.101936Z",
"response": {
"error": {
"type": "DATABASE_BACKUP_DISABLED",
"status": "400 BAD_REQUEST",
"description": "Database backup is disabled"
}
},
"links": [
{
"href": "https://api-staging.qa.redislabs.com/v1/tasks/ce2cbfea-9b15-4250-a516-f014161a8dd3",
"type": "GET",
"rel": "self"
}
]
}`,
),
))

subject, err := clientFromTestServer(server, "key", "secret")
require.NoError(t, err)

_, err = subject.LatestBackup.GetActiveActive(context.TODO(), 12, 34, "eu-west-2")
actual, err := subject.LatestBackup.GetActiveActive(context.TODO(), 12, 34, "eu-west-2")
require.NoError(t, err)

assert.Equal(t, &latest_backups.LatestBackupStatus{
CommandType: redis.String("databaseBackupStatusRequest"),
Description: redis.String("Task request failed during processing. See error information for failure details."),
Status: redis.String("processing-error"),
ID: redis.String("ce2cbfea-9b15-4250-a516-f014161a8dd3"),
Response: &latest_backups.Response{
Error: &latest_backups.Error{
Type: redis.String("DATABASE_BACKUP_DISABLED"),
Description: redis.String("Database backup is disabled"),
Status: redis.String("400 BAD_REQUEST"),
},
},
}, actual)

}
103 changes: 15 additions & 88 deletions latest_imports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,38 +61,27 @@ func TestGetLatestImportTooEarly(t *testing.T) {
]
}`,
),
getRequest(
t,
"/tasks/1dfd6084-21df-40c6-829c-e9b4790e207e",
`{
"taskId": "1dfd6084-21df-40c6-829c-e9b4790e207e",
"commandType": "databaseImportStatusRequest",
"status": "processing-error",
"description": "Task request failed during processing. See error information for failure details.",
"timestamp": "2024-04-15T10:19:07.331898Z",
"response": {
"error": {
"type": "SUBSCRIPTION_NOT_ACTIVE",
"status": "403 FORBIDDEN",
"description": "Cannot preform any actions for subscription that is not in an active state"
}
},
"links": [
{
"href": "https://api-staging.qa.redislabs.com/v1/tasks/1dfd6084-21df-40c6-829c-e9b4790e207e",
"type": "GET",
"rel": "self"
}
]
}`,
),
))

subject, err := clientFromTestServer(server, "key", "secret")
require.NoError(t, err)

_, err = subject.LatestImport.Get(context.TODO(), 12, 34)
actual, err := subject.LatestImport.Get(context.TODO(), 12, 34)
require.NoError(t, err)

assert.Equal(t, &latest_imports.LatestImportStatus{
CommandType: redis.String("databaseImportStatusRequest"),
Description: redis.String("Task request failed during processing. See error information for failure details."),
Status: redis.String("processing-error"),
ID: redis.String("1dfd6084-21df-40c6-829c-e9b4790e207e"),
Response: &latest_imports.Response{
Error: &latest_imports.Error{
Type: redis.String("SUBSCRIPTION_NOT_ACTIVE"),
Description: redis.String("Cannot preform any actions for subscription that is not in an active state"),
Status: redis.String("403 FORBIDDEN"),
},
},
}, actual)
}

func TestGetFixedLatestImport(t *testing.T) {
Expand Down Expand Up @@ -143,31 +132,6 @@ func TestGetFixedLatestImport(t *testing.T) {
]
}`,
),
getRequest(
t,
"/tasks/e9232e43-3781-4263-a38e-f4d150e03475",
`{
"taskId": "e9232e43-3781-4263-a38e-f4d150e03475",
"commandType": "databaseImportStatusRequest",
"status": "processing-completed",
"description": "Request processing completed successfully and its resources are now being provisioned / de-provisioned.",
"timestamp": "2024-04-15T10:44:35.225468Z",
"response": {
"resourceId": 51051302,
"additionalResourceId": 110777,
"resource": {
"status": "importing"
}
},
"links": [
{
"href": "https://api-staging.qa.redislabs.com/v1/tasks/e9232e43-3781-4263-a38e-f4d150e03475",
"type": "GET",
"rel": "self"
}
]
}`,
),
))

subject, err := clientFromTestServer(server, "key", "secret")
Expand Down Expand Up @@ -251,43 +215,6 @@ func TestGetLatestImport(t *testing.T) {
]
}`,
),
getRequest(
t,
"/tasks/e9232e43-3781-4263-a38e-f4d150e03475",
`{
"taskId": "e9232e43-3781-4263-a38e-f4d150e03475",
"commandType": "databaseImportStatusRequest",
"status": "processing-completed",
"description": "Request processing completed successfully and its resources are now being provisioned / de-provisioned.",
"timestamp": "2024-04-15T10:44:35.225468Z",
"response": {
"resourceId": 51051302,
"additionalResourceId": 110777,
"resource": {
"failureReason": "file-corrupted",
"failureReasonParams": [
{
"key": "bytes_configured_bdb_limit",
"value": "1234"
},
{
"key": "bytes_of_expected_dataset",
"value": "5678"
}
],
"lastImportTime": "2024-05-21T10:36:26Z",
"status": "failed"
}
},
"links": [
{
"href": "https://api-staging.qa.redislabs.com/v1/tasks/e9232e43-3781-4263-a38e-f4d150e03475",
"type": "GET",
"rel": "self"
}
]
}`,
),
))

subject, err := clientFromTestServer(server, "key", "secret")
Expand Down
Loading
Loading