Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use FCM HTTP V1 Api for Batch Messaging #805

Merged
merged 3 commits into from
Jun 26, 2023
Merged

Conversation

jeromegamez
Copy link
Member

@jeromegamez jeromegamez commented Jun 21, 2023

Closes #804

:octocat:

@codecov
Copy link

codecov bot commented Jun 21, 2023

Codecov Report

Merging #805 (dfde52d) into 7.x (30a0541) will decrease coverage by 0.36%.
The diff coverage is 75.80%.

Impacted file tree graph

@@             Coverage Diff              @@
##                7.x     #805      +/-   ##
============================================
- Coverage     68.58%   68.23%   -0.36%     
+ Complexity     1659     1626      -33     
============================================
  Files           170      164       -6     
  Lines          4699     4624      -75     
============================================
- Hits           3223     3155      -68     
+ Misses         1476     1469       -7     

@jeromegamez jeromegamez force-pushed the fcm-http-v1-batches branch from 36f9d82 to dfde52d Compare June 26, 2023 12:57
@jeromegamez jeromegamez marked this pull request as ready for review June 26, 2023 13:03
@jeromegamez jeromegamez merged commit ee7ea30 into 7.x Jun 26, 2023
@jeromegamez jeromegamez deleted the fcm-http-v1-batches branch June 26, 2023 13:03
@rudyzeinoun
Copy link

Thanks for the amazingly fast resolution.
Is the max devices limit still needed? The new API doesn't use batching, so any number of devices can be sent, as long as the messages fit altogether in memory. Right?

@jeromegamez
Copy link
Member Author

Theoretically not, but as far as I remember, I saw the limit remained in the Admin Node SDK as well, but it could have been an oversight on their part 🤔

I don't know what it would do to memory consumption and execution time, though, and if this is something that I should consider a developer to be aware of (and chunk the messages beforehand) or if I should wait until someone opens an issue saying "I tried to send 1 Million messages and my server crashed" 😅.

What do you think?

@rudyzeinoun
Copy link

rudyzeinoun commented Jun 26, 2023

I'm subjective because I will eventually need to do this myself anyway. But I can imagine anyone sending to 499 tokens will need this after a few days of reaching 500 tokens. Use cases like notifying followers, notifying a broadcast channel (although topics exist for that). They can easily exceed 500.

If it's left for the developer to chunk them, there will be 2 levels of Promises (one from the library and another from the developer's project). It would be harder on beginners for sure.

@jeromegamez
Copy link
Member Author

jeromegamez commented Jun 26, 2023

That's a good argument - and now that you say it, I forgot that I was thinking about chunking the messages in the SDK a while ago - I'm confident the limit was there due to the batch API supporting only multipart requests (and responses) to avoid too large message bodies, which now shouldn't be an issue anymore.

Long story short: I'll remove the limit 💪🏻

@rudyzeinoun
Copy link

That was easy 😁 thank you

@jeromegamez
Copy link
Member Author

I'm not in the business of making things difficult 😅. You're welcome, and thanks a lot for your valuable feedback! 🌺

@cutekanudo21
Copy link

To confirm its load, today i have tested it upto 3000 invalid tokens and two real tokens, it takes sometime in loading but request completes. Then i tried with 5000 invalid tokens / 2 real token and it crashes with http error 500. (FYI: VPS with 4v core & 8GB RAM)

Here is my code: `<?php

declare(strict_types=1);

require 'vendor/autoload.php';

use Kreait\Firebase\Factory;

putenv('GOOGLE_APPLICATION_CREDENTIALS=./fcmtest.json');

$fcm = (new Factory())->createMessaging();

/*** TOKEN ARRAY ***/
$deviceTokens = [];

$deviceTokens[] = 'REAL_TOKEN_1'; // This is real valid token

for ($i = 1; $i <= 5000; $i++) {
$deviceTokens[] = 'dummy_token_' . $i; // 5000 dummy token just for a testing...

$deviceTokens[] = 'REAL_TOKEN_2'; // This is real valid token

$message = [
'notification' => [
'title' => 'Notification Title',
'body' => 'Notification Body',
'image' => 'https://example.com/test.jpg',
],
'webpush' => [
'fcm_options' => [
'link' => 'https://example.com'
],
],
];

$report = $fcm->sendMulticast($message, $deviceTokens);

// echo 'Successful sends: '.$report->successes()->count().PHP_EOL;
// echo 'Failed sends: '.$report->failures()->count().PHP_EOL;

?>`

@cutekanudo21
Copy link

cutekanudo21 commented Jun 28, 2023

Another question related to your answer yesterday here: https://stackoverflow.com/questions/76563436/firebase-http-v1-api-and-no-batch-send-anymore/76568887#76568887

how to print oauth 2 access token in that pure php code, so that we can save that token for an hour, so that we can't exceeded quota limit of 50/100 refresh token.

@jeromegamez
Copy link
Member Author

@rudyzeinoun This is what I was afraid about 😅 (@cutekanudo21, this has nothing to you with your valid issue)

@cutekanudo21 Without knowing the exact reason for the error ("Error 500" allows just guesswork), it might be that the PHP max execution time was exceeded or that the memory of your server was exhausted.

In real life, you would certainly not have 5K invalid tokens, but even with valid tokens the problem would probably be the same. You should inspect the actual reason for the error, but if it's the max execution time, using a queue might help. In case of memory exhaustion, chunking the tokens and calling the method with batches might work.

In general, it is recommended to use topics when sending messages to a large amount of devices.

As to your second question - in pure PHP (I assume you mean without using the SDK), you can wrap the Google Credentials in the FetchAuthTokenCache class. Here's how it's done in the SDK:

$credentials = new FetchAuthTokenCache($credentials, ['prefix' => $cachePrefix], $this->authTokenCache);

@cutekanudo21
Copy link

cutekanudo21 commented Jun 28, 2023

Thanks for your reply. I also tried increasing max exec time to 120 and memory limit: 512m but still it can't handle 7000.

In my Plesk panel, i checked server resources statistics but it's just use some % only, no any server load actually.

If there's any other php settings required let me know.

So using your SDK, I think no need to save token because you may save it in cache for an hour?

@jeromegamez
Copy link
Member Author

You still have to configure the cache as described here: https://firebase-php.readthedocs.io/en/stable/setup.html#authentication-tokens

If your plesk server grants you access to the PHP error log, you should be able to see there what caused the 500 error. Server configuration is out of scope of what I can provide free support for, though, I hope you understand 🙏🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Discontinued FCM Messaging API
3 participants