Skip to content

Commit

Permalink
Merge pull request #17 from NeedleInAJayStack/fix/403-retry
Browse files Browse the repository at this point in the history
fix: Adds login/retry on a 403 response
  • Loading branch information
NeedleInAJayStack authored May 22, 2023
2 parents 6a42a09 + acf2de6 commit 87a47e5
Showing 1 changed file with 44 additions and 28 deletions.
72 changes: 44 additions & 28 deletions pkg/plugin/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,14 @@ func (datasource *Datasource) query(ctx context.Context, pCtx backend.PluginCont
ops, err := datasource.ops()
if err != nil {
log.DefaultLogger.Error(err.Error())
return backend.ErrDataResponse(backend.StatusBadRequest, fmt.Sprintf("Ops eval failure: %v", err.Error()))
return backend.ErrDataResponse(backend.StatusBadRequest, fmt.Sprintf("Ops failure: %v", err.Error()))
}
grid = ops
case "eval":
eval, err := datasource.eval(model.Eval, variables)
if err != nil {
log.DefaultLogger.Error(err.Error())
return backend.ErrDataResponse(backend.StatusBadRequest, fmt.Sprintf("Axon eval failure: %v", err.Error()))
return backend.ErrDataResponse(backend.StatusBadRequest, fmt.Sprintf("Eval failure: %v", err.Error()))
}
grid = eval
case "hisRead":
Expand Down Expand Up @@ -193,54 +193,69 @@ func (datasource *Datasource) CheckHealth(_ context.Context, req *backend.CheckH
}

func (datasource *Datasource) ops() (haystack.Grid, error) {
result, err := datasource.client.Ops()
// If the error is a 404, try to reconnect and try again
switch error := err.(type) {
case client.HTTPError:
if error.Code == 404 {
datasource.client.Open()
return datasource.withRetry(
func() (haystack.Grid, error) {
return datasource.client.Ops()
} else {
return result, err
}
default:
return result, err
}
},
)
}

func (datasource *Datasource) eval(expr string, variables map[string]string) (haystack.Grid, error) {
for name, val := range variables {
expr = strings.ReplaceAll(expr, name, val)
}
result, err := datasource.client.Eval(expr)
// If the error is a 404, try to reconnect and try again
switch error := err.(type) {
case client.HTTPError:
if error.Code == 404 {
datasource.client.Open()

return datasource.withRetry(
func() (haystack.Grid, error) {
return datasource.client.Eval(expr)
} else {
return result, err
}
default:
return result, err
}
},
)
}

func (datasource *Datasource) hisRead(id string, timeRange backend.TimeRange) (haystack.Grid, error) {
ref := haystack.NewRef(id, "")
start := haystack.NewDateTimeFromGo(timeRange.From.UTC())
end := haystack.NewDateTimeFromGo(timeRange.To.UTC())
return datasource.client.HisReadAbsDateTime(ref, start, end)

return datasource.withRetry(
func() (haystack.Grid, error) {
return datasource.client.HisReadAbsDateTime(ref, start, end)
},
)
}

func (datasource *Datasource) read(filter string, variables map[string]string) (haystack.Grid, error) {
for name, val := range variables {
filter = strings.ReplaceAll(filter, name, val)
}
return datasource.client.Read(filter)

return datasource.withRetry(
func() (haystack.Grid, error) {
return datasource.client.Read(filter)
},
)
}

// withRetry will retry the given operation if it fails with a 403 or 404 error
func (datasource *Datasource) withRetry(
operation func() (haystack.Grid, error),
) (haystack.Grid, error) {
result, err := operation()
// If the error is a 403 or 404, try to reconnect and try again
switch error := err.(type) {
case client.HTTPError:
if error.Code == 404 || error.Code == 403 {
datasource.client.Open()
return operation()
} else {
return result, err
}
default:
return result, err
}
}

// dataFrameFromGrid converts a haystack grid to a Grafana data frame
func dataFrameFromGrid(grid haystack.Grid) (*data.Frame, error) {
fields := []*data.Field{}

Expand Down Expand Up @@ -370,6 +385,7 @@ func dataFrameFromGrid(grid haystack.Grid) (*data.Frame, error) {

type colType int

// colType represents the type of a column in a haystack grid
const (
none colType = iota
dateTime
Expand Down

0 comments on commit 87a47e5

Please sign in to comment.