Skip to content

Commit

Permalink
Resolve error if service migrates (#33)
Browse files Browse the repository at this point in the history
Co-authored-by: Chris Gibson <cgibson@datto.com>
  • Loading branch information
equalsgibson and Chris Gibson authored Feb 26, 2024
1 parent a684e7c commit daa2b02
Showing 1 changed file with 49 additions and 35 deletions.
84 changes: 49 additions & 35 deletions five9/authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package five9

import (
"context"
"errors"
"fmt"
"net/http"
"strings"
Expand Down Expand Up @@ -44,7 +43,39 @@ func (a *authenticationState) requestWithAuthentication(request *http.Request, t
request.URL.Path = strings.ReplaceAll(request.URL.Path, ":userID", string(login.UserID))
request.URL.Path = strings.ReplaceAll(request.URL.Path, ":organizationID", string(login.OrgID))

return a.client.request(request, target)
var latestAttemptErr error
tries := 0
for tries < 3 {
tries++
latestAttemptErr = a.client.request(request, target)
if latestAttemptErr != nil {
if five9Error, ok := latestAttemptErr.(*Error); ok {
if five9Error.StatusCode == http.StatusUnauthorized {
// The login is not registered by other endpoints for a short time.
// I think this has to do with Five9 propagating the session across their data centers.
// We login using the app.five9.com domain but then make subsequent calls to the data center specific domain
time.Sleep(time.Second * 2)

continue
}

// Five9 reply with Status 435 if a service has been migrated. This is not an official status code, so check directly.
if five9Error.StatusCode == int(435) {
// Clear out the login state
a.loginMutex.Lock()
defer a.loginMutex.Unlock()

a.loginResponse = nil

return latestAttemptErr
}
}
}

return nil
}

return latestAttemptErr
}

func (a *authenticationState) getLogin(
Expand Down Expand Up @@ -140,42 +171,25 @@ func (a *authenticationState) endpointGetLoginState(ctx context.Context) (five9t

var target five9types.UserLoginState

tries := 0
for tries < 3 {
tries++

request, err := http.NewRequestWithContext(
ctx,
http.MethodGet,
fmt.Sprintf(
"/%s/%s/:userID/login_state",
a.apiContextPath,
path,
),
http.NoBody,
)
if err != nil {
return "", err
}

if err := a.requestWithAuthentication(request, &target); err != nil {
five9Error, ok := err.(*Error)
if ok && five9Error.StatusCode == http.StatusUnauthorized {
// The login is not registered by other endpoints for a short time.
// I think this has to do with Five9 propagating the session across their data centers.
// We login using the app.five9.com domain but then make subsequent calls to the data center specific domain
time.Sleep(time.Second * 2)

continue
}

return "", err
}
request, err := http.NewRequestWithContext(
ctx,
http.MethodGet,
fmt.Sprintf(
"/%s/%s/:userID/login_state",
a.apiContextPath,
path,
),
http.NoBody,
)
if err != nil {
return "", err
}

return target, nil
if err := a.requestWithAuthentication(request, &target); err != nil {
return "", err
}

return "", errors.New("Five9 login timeout")
return target, nil
}

func (a *authenticationState) endpointStartSession(ctx context.Context) error {
Expand Down

0 comments on commit daa2b02

Please sign in to comment.