Skip to content

Commit 3c95e78

Browse files
authored
STAC-24015: Fix ES operation status check (#11)
1 parent e2c0716 commit 3c95e78

3 files changed

Lines changed: 31 additions & 68 deletions

File tree

cmd/elasticsearch/restore_test.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,7 @@ func (m *mockESClientForRestore) ConfigureSLMPolicy(_, _, _, _, _, _ string, _,
9393
}
9494

9595
func (m *mockESClientForRestore) GetRestoreStatus(_, _ string) (string, bool, error) {
96-
return "NOT_FOUND", true, nil
97-
}
98-
99-
func (m *mockESClientForRestore) IsRestoreInProgress(_, _ string) (bool, error) {
100-
return false, nil
96+
return "SUCCESS", true, nil
10197
}
10298

10399
// TestRestoreCmd_Unit tests the command structure

internal/clients/elasticsearch/client.go

Lines changed: 30 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,7 @@ import (
1515
// Restore status constants
1616
const (
1717
StatusSuccess = "SUCCESS"
18-
StatusFailed = "FAILED"
1918
StatusInProgress = "IN_PROGRESS"
20-
StatusNotFound = "NOT_FOUND"
21-
StatusPartial = "PARTIAL"
22-
StatusStarted = "STARTED"
23-
StatusInit = "INIT"
2419
)
2520

2621
// Client represents an Elasticsearch client
@@ -362,79 +357,52 @@ func (c *Client) RestoreSnapshot(repository, snapshotName, indicesPattern string
362357
return nil
363358
}
364359

365-
// RestoreStatusResponse represents the response from Elasticsearch restore status API
366-
type RestoreStatusResponse struct {
367-
Snapshots []struct {
368-
Snapshot string `json:"snapshot"`
369-
State string `json:"state"`
370-
Shards struct {
371-
Total int `json:"total"`
372-
Failed int `json:"failed"`
373-
Successful int `json:"successful"`
374-
} `json:"shards_stats"`
375-
} `json:"snapshots"`
360+
// RecoveryInfo represents the recovery status of a shard from _cat/recovery API
361+
type RecoveryInfo struct {
362+
Index string `json:"index"`
363+
Shard string `json:"shard"`
364+
Type string `json:"type"`
365+
Stage string `json:"stage"`
366+
Repository string `json:"repository"`
367+
Snapshot string `json:"snapshot"`
376368
}
377369

378-
// GetRestoreStatus checks the status of a restore operation
370+
// GetRestoreStatus checks the status of a restore operation by examining active shard recoveries.
371+
// When a snapshot is being restored, shards are recovered with type "snapshot".
379372
// Returns: (statusMessage, isComplete, error)
380-
// Status can be: "IN_PROGRESS", "SUCCESS", "FAILED", "NOT_FOUND"
373+
// Status can be: "IN_PROGRESS", "SUCCESS"
381374
func (c *Client) GetRestoreStatus(repository, snapshotName string) (string, bool, error) {
382-
res, err := c.es.Snapshot.Status(
383-
c.es.Snapshot.Status.WithContext(context.Background()),
384-
c.es.Snapshot.Status.WithRepository(repository),
385-
c.es.Snapshot.Status.WithSnapshot(snapshotName),
375+
// Use _cat/recovery API to check for active snapshot recoveries.
376+
// This shows shards that are currently being recovered from a snapshot.
377+
res, err := c.es.Cat.Recovery(
378+
c.es.Cat.Recovery.WithContext(context.Background()),
379+
c.es.Cat.Recovery.WithFormat("json"),
380+
c.es.Cat.Recovery.WithActiveOnly(true),
381+
c.es.Cat.Recovery.WithH("index,shard,type,stage,repository,snapshot"),
386382
)
387383
if err != nil {
388-
return "", false, fmt.Errorf("failed to get restore status: %w", err)
384+
return "", false, fmt.Errorf("failed to get recovery status: %w", err)
389385
}
390386
defer res.Body.Close()
391387

392-
// 404 means no restore is in progress
393-
if res.StatusCode == http.StatusNotFound {
394-
return StatusNotFound, true, nil
395-
}
396-
397388
if res.IsError() {
398389
return "", false, fmt.Errorf("elasticsearch returned error: %s", res.String())
399390
}
400391

401-
var statusResp RestoreStatusResponse
402-
if err := json.NewDecoder(res.Body).Decode(&statusResp); err != nil {
392+
var recoveries []RecoveryInfo
393+
if err := json.NewDecoder(res.Body).Decode(&recoveries); err != nil {
403394
return "", false, fmt.Errorf("failed to decode response: %w", err)
404395
}
405396

406-
// If no snapshots are being restored, it's complete
407-
if len(statusResp.Snapshots) == 0 {
408-
return StatusSuccess, true, nil
409-
}
410-
411-
// Check the state of the snapshot
412-
snapshotStatus := statusResp.Snapshots[0]
413-
state := snapshotStatus.State
414-
415-
switch state {
416-
case StatusSuccess, StatusPartial:
417-
return StatusSuccess, true, nil
418-
case StatusFailed:
419-
return StatusFailed, true, nil
420-
case StatusInProgress, StatusStarted, StatusInit:
421-
return StatusInProgress, false, nil
422-
default:
423-
return state, false, nil
424-
}
425-
}
426-
427-
// IsRestoreInProgress checks if a restore operation is currently in progress
428-
func (c *Client) IsRestoreInProgress(repository, snapshotName string) (bool, error) {
429-
status, isComplete, err := c.GetRestoreStatus(repository, snapshotName)
430-
if err != nil {
431-
return false, err
397+
// Check if any active recovery is from the specified snapshot
398+
for _, recovery := range recoveries {
399+
if recovery.Type == "snapshot" &&
400+
recovery.Repository == repository &&
401+
recovery.Snapshot == snapshotName {
402+
return StatusInProgress, false, nil
403+
}
432404
}
433405

434-
// If status is NOT_FOUND or complete, no restore in progress
435-
if status == "NOT_FOUND" || isComplete {
436-
return false, nil
437-
}
438-
439-
return true, nil
406+
// No active recoveries from this snapshot - restore is complete
407+
return StatusSuccess, true, nil
440408
}

internal/clients/elasticsearch/interface.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ type Interface interface {
88
GetSnapshot(repository, snapshotName string) (*Snapshot, error)
99
RestoreSnapshot(repository, snapshotName, indicesPattern string) error
1010
GetRestoreStatus(repository, snapshotName string) (string, bool, error)
11-
IsRestoreInProgress(repository, snapshotName string) (bool, error)
1211

1312
// Index operations
1413
ListIndices(pattern string) ([]string, error)

0 commit comments

Comments
 (0)