@@ -121,6 +121,14 @@ class Http
121121 */
122122 protected $ queue ;
123123
124+ /**
125+ * Request queue to prevent API
126+ * overload.
127+ *
128+ * @var SplQueue
129+ */
130+ protected $ interactionQueue ;
131+
124132 /**
125133 * Number of requests that are waiting for a response.
126134 *
@@ -148,6 +156,7 @@ public function __construct(string $token, LoopInterface $loop, LoggerInterface
148156 $ this ->logger = $ logger ;
149157 $ this ->driver = $ driver ;
150158 $ this ->queue = new SplQueue ;
159+ $ this ->interactionQueue = new SplQueue ;
151160
152161 $ this ->promiseV3 = str_starts_with (InstalledVersions::getVersion ('react/promise ' ), '3. ' );
153162 }
@@ -451,7 +460,9 @@ protected function getBucket(string $key): Bucket
451460 if (! isset ($ this ->buckets [$ key ])) {
452461 $ bucket = new Bucket ($ key , $ this ->loop , $ this ->logger , function (Request $ request ) {
453462 $ deferred = new Deferred ();
454- $ this ->queue ->enqueue ([$ request , $ deferred ]);
463+ self ::isInteractionEndpoint ($ request )
464+ ? $ this ->interactionQueue ->enqueue ([$ request , $ deferred ])
465+ : $ this ->queue ->enqueue ([$ request , $ deferred ]);
455466 $ this ->checkQueue ();
456467
457468 return $ deferred ->promise ();
@@ -469,8 +480,10 @@ protected function getBucket(string $key): Bucket
469480 */
470481 protected function checkQueue (): void
471482 {
483+ $ this ->checkInteractionQueue ();
484+
472485 if ($ this ->waiting >= static ::CONCURRENT_REQUESTS || $ this ->queue ->isEmpty ()) {
473- $ this ->logger ->debug ('http not checking ' , ['waiting ' => $ this ->waiting , 'empty ' => $ this ->queue ->isEmpty ()]);
486+ $ this ->logger ->debug ('http not checking queue ' , ['waiting ' => $ this ->waiting , 'empty ' => $ this ->queue ->isEmpty ()]);
474487
475488 return ;
476489 }
@@ -493,6 +506,47 @@ protected function checkQueue(): void
493506 });
494507 }
495508
509+ /**
510+ * Checks the interaction queue to see if more requests can be
511+ * sent out.
512+ */
513+ protected function checkInteractionQueue (): void
514+ {
515+ if ($ this ->interactionQueue ->isEmpty ()) {
516+ $ this ->logger ->debug ('http not checking interaction queue ' , ['waiting ' => $ this ->waiting , 'empty ' => $ this ->interactionQueue ->isEmpty ()]);
517+
518+ return ;
519+ }
520+
521+ /**
522+ * @var Request $request
523+ * @var Deferred $deferred
524+ */
525+ [$ request , $ deferred ] = $ this ->interactionQueue ->dequeue ();
526+
527+ $ this ->executeRequest ($ request )->then (function ($ result ) use ($ deferred ) {
528+ $ this ->checkQueue ();
529+ $ deferred ->resolve ($ result );
530+ }, function ($ e ) use ($ deferred ) {
531+ $ this ->checkQueue ();
532+ $ deferred ->reject ($ e );
533+ });
534+ }
535+
536+ /**
537+ * Checks if the request is for an interaction endpoint.
538+ *
539+ * @link https://discord.com/developers/docs/interactions/receiving-and-responding#endpoints
540+ *
541+ * @param Request $request
542+ * @return bool
543+ */
544+ public static function isInteractionEndpoint (Request $ request ): bool
545+ {
546+ $ endpoint = (string ) $ request ->getUrl ();
547+ return strpos ($ endpoint , '/interactions ' ) === 0 ;
548+ }
549+
496550 /**
497551 * Returns an exception based on the request.
498552 *
0 commit comments