Alymosul / exponent-server-sdk-php

Server-side library for working with Expo push notifications using PHP
https://packagist.org/packages/alymosul/exponent-server-sdk-php
MIT License
148 stars 77 forks source link

“Attempt to assign property "newmessage6089" on null” because of a corrupted repository? #83

Open alexislefebvre opened 1 year ago

alexislefebvre commented 1 year ago

Our error log showed this:

Attempt to assign property "newmessage6089" on null

I'm pretty sure that the error comes from these lines:

https://github.com/Alymosul/exponent-server-sdk-php/blob/615f04f4777b27900fe646e0f11058513a4bd26a/lib/Repositories/ExpoFileDriver.php#L48-L49

And

https://github.com/Alymosul/exponent-server-sdk-php/blob/615f04f4777b27900fe646e0f11058513a4bd26a/lib/Repositories/ExpoFileDriver.php#L140-L141

It looks like json_decode returned null because the file wasn't a valid JSON (sadly we didn't saved the file because we were in a rush to fix the issue).

The code may check that the content is a valid JSON before returning it:

$file = file_get_contents($this->storage);

try {
    return json_decode($file, null, 16, JSON_THROW_ON_ERROR);
} catch (\JsonException $e) {
    return([]);
}

It would start on a fresh repository, I think it's the safest option.

josaric commented 1 year ago

+1 @alexislefebvre is there any fix?

EDIT: I've deleted tokens.json because the file was invalid and it worked again.

alexislefebvre commented 1 year ago

We tried to put the call in a try catch block:

try {
    $this->expo->subscribe($channelName, $token);
} catch (\Exception $e) {
}

but it still failed, probably because this error is not recoverable.

Deleting the file is the only solution we have so far.

alexislefebvre commented 1 year ago

We are testing a workaround, it checks that the JSON is valid before using it, it relies on the fact that we use a custom path to store the file with the tokens:

class ExpoNotificationClient
{
    private const EXPO_TOKENS_STORAGE = '/tmp/exponent-server-sdk-php/tokens.json';
    private readonly \ExponentPhpSDK\Expo $expo;

    public function __construct()
    {
        $this->checkTokensStorage();
        $driver = new ExpoFileDriver();
        $driver->setStorage(self::EXPO_TOKENS_STORAGE);
        $this->expo = new Expo(new ExpoRegistrar($driver));
    }

    // …

The method:

    /**
     * Check that the tokens storage is a valid JSON, otherwise delete the file.
     */
    private function checkTokensStorage(): void
    {
        $file = file_get_contents(self::EXPO_TOKENS_STORAGE);
        try {
            json_decode($file, null, 16, JSON_THROW_ON_ERROR);
        } catch (\JsonException) {
            unlink(self::EXPO_TOKENS_STORAGE);
        }
    }
abpbackup commented 2 weeks ago

Same here. Everytime the subscriptions are empty, the tokens.json file gets null as content instead of {} or get removed. Removing it fixes the problem