From daa2b026e5a0d0742b6ec03dc7a70503dfe49d41 Mon Sep 17 00:00:00 2001 From: Chris Gibson <71530511+equalsgibson@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:29:09 +0000 Subject: [PATCH] Resolve error if service migrates (#33) Co-authored-by: Chris Gibson --- five9/authentication.go | 84 ++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/five9/authentication.go b/five9/authentication.go index 173f110..0c941a1 100644 --- a/five9/authentication.go +++ b/five9/authentication.go @@ -2,7 +2,6 @@ package five9 import ( "context" - "errors" "fmt" "net/http" "strings" @@ -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( @@ -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 {