88use Google \Client as GoogleClient ;
99use Google \Service \FirebaseCloudMessaging ;
1010use GuzzleHttp \Client ;
11- use GuzzleHttp \Exception \ClientException ;
11+ use GuzzleHttp \Exception \RequestException ;
12+ use GuzzleHttp \Pool ;
13+ use GuzzleHttp \Psr7 \Request ;
14+ use GuzzleHttp \Psr7 \Response as GuzzleResponse ;
1215use Illuminate \Support \Facades \Cache ;
1316use Illuminate \Support \Str ;
1417
1518class FcmV1 extends Fcm
1619{
1720 const CACHE_SECONDS = 55 * 60 ; // 55 minutes
1821
22+ /**
23+ * Number of concurrent requests to multiplex in the same connection.
24+ *
25+ * @var int
26+ */
27+ protected $ concurrentRequests = 10 ;
28+
1929 protected $ unregisteredDeviceTokens = [];
2030
31+ protected $ feedbacks = [];
32+
2133 /**
2234 * Fcm constructor.
2335 * Override parent constructor.
@@ -29,6 +41,8 @@ public function __construct()
2941 $ this ->url = 'https://fcm.googleapis.com/v1/projects/ ' . $ this ->config ['projectId ' ] . '/messages:send ' ;
3042
3143 $ this ->client = new Client ($ this ->config ['guzzle ' ] ?? []);
44+
45+ $ this ->concurrentRequests = $ this ->config ['concurrentRequests ' ] ?? 10 ;
3246 }
3347
3448 /**
@@ -88,45 +102,51 @@ public function send(array $deviceTokens, array $message)
88102 $ headers = $ this ->addRequestHeaders ();
89103 $ jsonData = ['message ' => $ this ->buildMessage ($ message )];
90104
91- $ feedbacks = [];
105+ $ this -> feedbacks = [];
92106 $ this ->unregisteredDeviceTokens = [];
93107
108+ $ requests = [];
94109 foreach ($ deviceTokens as $ deviceToken ) {
95- try {
96- $ jsonData ['message ' ]['token ' ] = $ deviceToken ;
110+ $ jsonData ['message ' ]['token ' ] = $ deviceToken ;
97111
98- $ result = $ this ->client ->post (
99- $ this ->url ,
100- [
101- 'headers ' => $ headers ,
102- 'json ' => $ jsonData ,
103- ]
104- );
112+ $ body = json_encode ($ jsonData );
113+
114+ $ requests [$ deviceToken ] = new Request ('POST ' , $ this ->url , $ headers , $ body );
115+ }
105116
106- $ json = $ result ->getBody ();
117+ $ pool = new Pool ($ this ->client , $ requests , [
118+ 'concurrency ' => $ this ->concurrentRequests ,
119+ 'fulfilled ' => function (GuzzleResponse $ response , $ deviceToken ) {
120+ // this is delivered each successful response
107121
108- $ feedbacks [$ deviceToken ] = [
122+ $ this -> feedbacks [$ deviceToken ] = [
109123 'success ' => true ,
110- 'response ' => json_decode ($ json , true , 512 , JSON_BIGINT_AS_STRING ),
111- ];
112- } catch (ClientException $ e ) {
113- $ feedbacks [$ deviceToken ] = [
114- 'success ' => false ,
115- 'error ' => json_decode ($ e ->getResponse ()->getBody ()->getContents (), true ),
124+ 'response ' => json_decode ((string ) $ response ->getBody (), true , 512 , JSON_BIGINT_AS_STRING ),
116125 ];
126+ },
127+ 'rejected ' => function (RequestException $ reason , $ deviceToken ) {
128+ // this is delivered each failed request
117129
118- $ this -> unregisteredDeviceTokens [] = $ deviceToken ;
119- } catch ( \ Exception $ e ) {
120- $ feedbacks [$ deviceToken ] = [
130+ $ error = json_decode (( string ) $ reason -> getResponse ()-> getBody (), true ) ;
131+
132+ $ this -> feedbacks [$ deviceToken ] = [
121133 'success ' => false ,
122- 'error ' => $ e -> getMessage () ,
134+ 'error ' => $ error ,
123135 ];
124136
125- $ this ->unregisteredDeviceTokens [] = $ deviceToken ;
126- }
127- }
137+ if (isset ($ error ['error ' ]['status ' ]) && $ error ['error ' ]['status ' ] === 'INVALID_ARGUMENT ' ) {
138+ $ this ->unregisteredDeviceTokens [] = $ deviceToken ;
139+ }
140+ },
141+ ]);
142+
143+ // Initiate the transfers and create a promise
144+ $ promise = $ pool ->promise ();
145+
146+ // Force the pool of requests to complete.
147+ $ promise ->wait ();
128148
129- $ this ->setFeedback ($ feedbacks );
149+ $ this ->setFeedback ($ this -> feedbacks );
130150 }
131151
132152 /**
0 commit comments