From 11a4c3d502b874b32095e7cdb4fb4c43c4dd070f Mon Sep 17 00:00:00 2001
From: fliespl <a.rzadkowolski@gmail.com>
Date: Sun, 4 May 2025 18:07:26 +0200
Subject: [PATCH] implement rate limit handling

---
 src/ClientFactory.php | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/ClientFactory.php b/src/ClientFactory.php
index 4c2d5ac7..0f746df6 100644
--- a/src/ClientFactory.php
+++ b/src/ClientFactory.php
@@ -13,13 +13,18 @@
 
 namespace JoliCode\Slack;
 
+use Http\Client\Common\Exception\ClientErrorException;
 use Http\Client\Common\Plugin\ErrorPlugin;
 use Http\Client\Common\Plugin\HeaderAppendPlugin;
+use Http\Client\Common\Plugin\RetryPlugin;
 use Http\Client\Common\PluginClient;
+use Http\Client\Exception\HttpException;
 use Http\Discovery\Psr17FactoryDiscovery;
 use Http\Discovery\Psr18ClientDiscovery;
 use JoliCode\Slack\HttpPlugin\AddSlackPathAndHostPlugin;
 use JoliCode\Slack\HttpPlugin\SlackErrorPlugin;
+use Psr\Http\Client\ClientExceptionInterface;
+use Psr\Http\Message\RequestInterface;
 use Psr\Http\Client\ClientInterface;
 
 class ClientFactory
@@ -34,12 +39,30 @@ public static function create(string $token, ?ClientInterface $httpClient = null
         // Decorates the HTTP client with some plugins
         $uri = Psr17FactoryDiscovery::findUriFactory()->createUri('https://slack.com/api');
         $pluginClient = new PluginClient($httpClient, [
-            new ErrorPlugin(),
             new SlackErrorPlugin(),
             new AddSlackPathAndHostPlugin($uri),
             new HeaderAppendPlugin([
                 'Authorization' => 'Bearer ' . $token,
             ]),
+            new RetryPlugin([
+                'retries' => 3,
+                'exception_decider' => function (RequestInterface $request, ClientExceptionInterface $e) {
+                    // retry only server errors and rate limits
+                    return !$e instanceof HttpException || ($e->getCode() === 429 || ($e->getCode() >= 500 && $e->getCode() < 600));
+                },
+                'exception_delay' => function (RequestInterface $request, ClientExceptionInterface $e, int $retries): int {
+                    if ($e instanceof ClientErrorException) {
+                        $response = $e->getResponse();
+                        if ($response->hasHeader('Retry-After')) {
+                            $retryAfter = (int) $response->getHeaderLine('retry-after');
+                            return $retryAfter * 1000000;
+                        }
+                    }
+
+                    return RetryPlugin::defaultExceptionDelay($request, $e, $retries);
+                },
+            ]),
+            new ErrorPlugin(),                            
         ]);
 
         // Instantiate our client extending the one generated by Jane