Giter Club home page Giter Club logo

Comments (2)

holtkamp avatar holtkamp commented on July 19, 2024

It seems that in some cases, the TooManyRequestsException is not thrown properly. I "think" this is a problem at the MoneyBird API side, but wanted to report it here to be able to discuss it. The stack trace:

In Connection.php line 423:
                                                               
  [Picqer\Financials\Moneybird\Exceptions\ApiException (429)]  
  Error 429: <html>                                            
  <head><title>429 Too Many Requests</title></head>            
  <body bgcolor="white">                                       
  <center><h1>429 Too Many Requests</h1></center>              
  <hr><center>nginx</center>                                   
  </body>                                                      
  </html>                                                      
                                                               

Exception trace:
 Picqer\Financials\Moneybird\Connection->parseExceptionForErrorMessages() at /app/vendor/picqer/moneybird-php-client/src/Picqer/Financials/Moneybird/Connection.php:229
 Picqer\Financials\Moneybird\Connection->patch() at /app/vendor/picqer/moneybird-php-client/src/Picqer/Financials/Moneybird/Actions/Storable.php:38
 Picqer\Financials\Moneybird\Entities\Contact->update() at /app/vendor/picqer/moneybird-php-client/src/Picqer/Financials/Moneybird/Actions/Storable.php:16
...
...

This

throw new ApiException('Error ' . $response->getStatusCode() . ': ' . $errorMessage, $response->getStatusCode());
indicates that the error is not properly detected here:
private function checkWhetherRateLimitHasBeenReached(ResponseInterface $response, $errorMessage)
{
$retryAfterHeaders = $response->getHeader('Retry-After');
if($response->getStatusCode() === 429 && count($retryAfterHeaders) > 0){
$exception = new TooManyRequestsException('Error ' . $response->getStatusCode() . ': ' . $errorMessage, $response->getStatusCode());
$exception->retryAfterNumberOfSeconds = (int) current($retryAfterHeaders);
throw $exception;
}
}

This happens "sometimes"... In other occasions / when running the same command a few minutes later, the error IS detected and a TooManyRequestsException is thrown:

 Error 429: Retry later : 
#0 /app/vendor/picqer/moneybird-php-client/src/Picqer/Financials/Moneybird/Connection.php(421): Picqer\Financials\Moneybird\Connection->checkWhetherRateLimitHasBeenReached(Object(GuzzleHttp\Psr7\Response), 'Retry later\n') 
#1 /app/vendor/picqer/moneybird-php-client/src/Picqer/Financials/Moneybird/Connection.php(193): Picqer\Financials\Moneybird\Connection->parseExceptionForErrorMessages(Object(GuzzleHttp\Exception\ClientException)) 
#2 /app/vendor/picqer/moneybird-php-client/src/Picqer/Financials/Moneybird/Entities/Contact.php(83): Picqer\Financials\Moneybird\Connection->get('contacts/custom...')

I got the idea that "sometimes" the response does not contain the Retry-After header...

Will contact the MoneyBird team to discuss this.

from moneybird-php-client.

holtkamp avatar holtkamp commented on July 19, 2024

Nevermind, it appeared that the TooManyRequestsExceptionwas not processed properly in our userland code. 🤦‍♂️

Current approach seems to work nicely:

        /**
     * @see https://developer.moneybird.com/#responses
     * @see https://developer.moneybird.com/#throttling
     *
     * @param ApiException $apiException
     *
     * @throws ApiException
     */
    public function processApiException(ApiException $apiException): void
    {
        $this->logger->error($apiException->getMessage().': '.$apiException->getTraceAsString());

        if ($apiException instanceof TooManyRequestsException) {
            Assertion::integer($apiException->retryAfterNumberOfSeconds, 'unable to determine number of seconds to sleep');

            $this->logger->info('API request limit reached: sleep the indicated amount of {retryAfterNumberOfSeconds} seconds', array('retryAfterNumberOfSeconds' => $apiException->retryAfterNumberOfSeconds));

            \sleep($apiException->retryAfterNumberOfSeconds);

            $this->logger->info('done sleeping, the API should be available for requests again');

            return;
        }

        throw $apiException;
    }

from moneybird-php-client.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.