Context deadline exceeded when working with Plaid HTTP API

1.1k Views Asked by At

This is one of my API functions; if I call this function continuously. The api showing loading only. Not getting any response.. then I got 502 error with log

error serving {"error": "context deadline exceeded", "errorVerbose": "context deadline exceeded\ngithub.com/ory/graceful.Graceful.func1\

I am using go-gin

I could not understand what is the issue in my code..

For example, I can call the API 5 times then it showing result. then in the 6th time its loading. its a get function

I could not find the root cause.

My api function is attached:

func (ser *service) GetPlaidUserInstitutionAccounts(ctx context.Context, impartWealthId string) (UserAccount, impart.Error) {

    _, err := dbmodels.Users(dbmodels.UserWhere.ImpartWealthID.EQ(impartWealthId)).One(ctx, ser.db)
    if err != nil {
        impartErr := impart.NewError(impart.ErrBadRequest, "Could not find the user.")
        ser.logger.Error("Could not find the user institution details.", zap.String("User", impartWealthId),
            zap.String("user", impartWealthId))
        return UserAccount{}, impartErr
    }

    userInstitutions, err := dbmodels.UserInstitutions(dbmodels.UserInstitutionWhere.ImpartWealthID.EQ(impartWealthId),
        qm.Load(dbmodels.UserInstitutionRels.ImpartWealth),
        qm.Load(dbmodels.UserInstitutionRels.Institution),
    ).All(ctx, ser.db)

    if len(userInstitutions) == 0 {
        return UserAccount{}, impart.NewError(impart.ErrBadRequest, "No records found.")
    }
    if err != nil {
        impartErr := impart.NewError(impart.ErrBadRequest, "Could not find the user institution details.")
        ser.logger.Error("Could not find the user institution details.", zap.String("User", impartWealthId),
            zap.String("user", impartWealthId))
        return UserAccount{}, impartErr
    }

    configuration := plaid.NewConfiguration()
    cfg, _ := config.GetImpart()
    if cfg != nil {
        configuration.AddDefaultHeader("PLAID-CLIENT-ID", cfg.PlaidClientId)
        configuration.AddDefaultHeader("PLAID-SECRET", cfg.PlaidSecret)

        if cfg.Env == config.Production {
            configuration.UseEnvironment(plaid.Production)
        } else if cfg.Env == config.Preproduction {
            configuration.UseEnvironment(plaid.Development)
        } else {
            configuration.UseEnvironment(plaid.Sandbox)
        }

    }
    client := plaid.NewAPIClient(configuration)

    userData := UserAccount{}
    userData.ImpartWealthID = impartWealthId
    userData.UpdatedAt = time.Now().UTC().Unix()
    userinstitution := make(UserInstitutions, len(userInstitutions))
    finalQuery := ""
    for i, user := range userInstitutions {
        institution := InstitutionToModel(user)
        accountsGetRequest := plaid.NewAccountsGetRequest(user.AccessToken)
        accountsGetResp, response, err := client.PlaidApi.AccountsGet(ctx).AccountsGetRequest(
            *accountsGetRequest,
        ).Execute()

        if response.StatusCode == 400 {
            // defer response.Body.Close()
            bodyBytes, _ := ioutil.ReadAll(response.Body)
            type errorResponse struct {
                ErrorCode string `json:"error_code" `
            }
            newRes := errorResponse{}
            err = json.Unmarshal(bodyBytes, &newRes)
            if err != nil {
                fmt.Println(err)
            }
            if newRes.ErrorCode == "ITEM_LOGIN_REQUIRED" {
                institution.IsAuthenticationError = true
            }
        }
        if err != nil {
            ser.logger.Error("Could not find the user plaid account details.", zap.String("User", impartWealthId),
                zap.String("token", user.AccessToken))
            continue
        }
        accounts := accountsGetResp.GetAccounts()
        userAccounts := make(Accounts, len(accounts))
        query1 := ""
        query := ""
        logwrite := false
        for i, act := range accounts {
            userAccounts[i], query1 = AccountToModel(act, user.UserInstitutionID)
            query = fmt.Sprintf("%s %s", query, query1)
            logwrite = true
        }
        institution.Accounts = userAccounts
        userinstitution[i] = institution
        userData.Institutions = userinstitution

        if logwrite {
            finalQuery = fmt.Sprintf("%s %s", finalQuery, query)
        }
    }
    if finalQuery != "" {
        go func() {
            lastQuery := "INSERT INTO `user_plaid_accounts_log` (`user_institution_id`,`account_id`,`mask`,`name`,`official_name`,`subtype`,`type`,`iso_currency_code`,`unofficial_currency_code`,`available`,`current`,`credit_limit`,`created_at`) VALUES "
            lastQuery = fmt.Sprintf("%s %s", lastQuery, finalQuery)
            lastQuery = strings.Trim(lastQuery, ",")
            lastQuery1 = fmt.Sprintf("%s ;", lastQuery)
            ser.logger.Info("Query", zap.Any("Query", lastQuery1))
            _, err = queries.Raw(lastQuery1).QueryContext(ctx, ser.db)
            if err != nil {
                ser.logger.Error("error attempting to  log in user_plaid_accounts_log ", zap.Any("user_plaid_accounts_log", lastQuery1), zap.Error(err))
            }
        }()
    }
    return userData, nil
}

Here I am getting error in main.go

if err := graceful.Graceful(server.ListenAndServe, server.Shutdown); err != nil {
        logger.Fatal("error serving", zap.Error(err))
    }
0

There are 0 best solutions below