Jędrzej Skrzypczak
Jędrzej Skrzypczak

Reputation: 138

Missing cache items [via phpfastcache] using Server Side Events

I'm using Server-Sent Events, to print messages for user.

In infinite loop, every 10 seconds I check if there is any new item in cache to broadcast:

$messages_to_broadcast = $this->_cache->getItemsByTag('inbox_message');
foreach ($messages_to_broadcast as $key => $_message) {
    $_message = $_message->get();
    if($_message->recipient == $this->_user_id || $_message->recipient == 0){
        if(!is_null($html = \CRM\Engine\MessagingService::getMessageToBroadcast($_message)))
        {
           echo "event: $_message->type \n";
           echo "data:{\n";
           echo "data:\"message_html\": \"$html\" \n";
           echo "data:}\n\n";
           $this->send_keepalive = false;
           $this->_cache->deleteItem($key);
        }
    }
}

At irregular intervals, there is event, which save message to cache:

$_cache_this = self::$_cache->getItem("message_".$_message->id);
if(!$_cache_this->isHit()){
    $_cache_this->set($_message)
        ->expiresAfter(600)
        ->addTag('inbox_message');
    self::$_cache->save($_cache_this);
}

The problem is that while I check in infinite loop for new items in cache, I get empty array. When I reload page, or browser reconnect to Server Side Events stream, item appears in cache. Is there any flush method I'm missing here? I'm using files as cache method.

\phpFastCache\CacheManager::setDefaultConfig(array(
    "path" => DIR_TMP
));
global $cache;
$cache = \phpFastCache\CacheManager::getInstance('files');

Upvotes: 0

Views: 858

Answers (3)

Geolim4
Geolim4

Reputation: 454

Phpfastcache is storing (the exact definition is "caching" in fact) the cache item statically in the cache backend object. So effectively you'll need to release the object using detachItem() method or clear() to empty the cache.

As described on this issue, I'll update the Wiki coming soon to clarify that behaviour for perpetual CLI scripts.

Upvotes: 1

Florent Poinsaut
Florent Poinsaut

Reputation: 51

In a loop, you have to use the detachItem method of PhpFastCache to force it to get the right value.

Here an example:

while (1) {
    $cache = $this->cacheService->getCache();
    if (null !== $cache) {
        try {
            $item = $cache->getItem('my_key');
            if ($item->isHit()) {
                echo "event: message\ndata: $item->get()\n\n";
            }
            $cache->detachItem($item);
        } catch (InvalidArgumentException | PhpfastcacheInvalidArgumentException $e) {
            $this->logger->error(
                'There has been an error when getting cache item: '
                .$e->getMessage().' - '.$e->getFile().' - '.$e->getLine()
            );
        }
    }

    ob_flush();
    flush();

    if (connection_aborted()) {
        break;
    }
    sleep(1);
}

I open a issue to ask more doc here: https://github.com/PHPSocialNetwork/phpfastcache/issues/687

Upvotes: 2

Marc D.
Marc D.

Reputation: 74

It's a while you've asked this, but usually you can only grab the items in cache by tag, haven't seen a method that let's you get all cache entries.

$entries = $cache->getItemsByTag('inbox_message')

$entries will now hold all your items.

Have a look here: https://github.com/PHPSocialNetwork/phpfastcache/blob/final/docs/examples/tagsMethods.php where you can see a complete example on usage.

Upvotes: 0

Related Questions