? Pending

User tests: Successful: Unsuccessful:

avatar mbabker
mbabker
2 Jan 2017

Pull Request for Issue #12893

Summary of Changes

Creates JCache::contains() and JCacheStorage::contains() as a means to look into the cache pool to determine if a cache item with a specified key exists. Implements this method in many places where a $cache->get() === false type of check had been in use previously.

Testing Instructions

With caching enabled, things should still work as expected. Explicitly, you can store something to the cache then check for its existence with something like this:

$id   = 'testCacheContainsItem';
$data = 'testData';

/** @var JCacheControllerCallback $cache */
$cache = JFactory::getCache('_testing');

if ($cache->store($data, $id) === false)
{
	throw new Exception('Initial Store Failed');
}

var_dump($cache->contains($id));

Documentation Changes Required

None, but it should probably be noted there may be a small (if it's even noticeable) performance hit with this.

Right now, most places just do a single $cache->get() call and if the result exists then it is used otherwise it does the operation that generates the cache data and stores it. With this, two calls to the cache store will be made. However, except for Memcache (no trailing d) and Cache_Lite, all of the stores have a way to check if a key exists in the store which is more performant. The get() methods will all read the data out of the store and do any processing required to make it usable to the PHP API (for example our filesystem handler does a string replacement to remove the PHP opening tag so the file's contents can be unserialized) while the contains() method simply checks the catalog to determine presence, a more efficient lookup operation.

avatar mbabker mbabker - open - 2 Jan 2017
avatar mbabker mbabker - change - 2 Jan 2017
Status New Pending
avatar joomla-cms-bot joomla-cms-bot - change - 2 Jan 2017
Category Administration com_login Front End com_banners com_finder Libraries Modules Unit Tests
avatar laoneo
laoneo - comment - 3 Jan 2017

I have tested this item successfully on 492f05c

Tested the functionality with the administrator login module.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/13452.

avatar laoneo laoneo - test_item - 3 Jan 2017 - Tested successfully
avatar csthomas
csthomas - comment - 4 Jan 2017

IMHO For performance reason I would suggest to change it.

  • usual if you use contains() then later you will call get()
  • it is not atomic (contains may return true but later in code get() won't return value because it expired)
  • for a few cache storages contains() equivalent does not exist and we have to call get(). If we need that value then we have to call get() again which is not good for performance.

Suggestion for cache method:

  • change current method get(...) to get($id, $group = null, $raiseIfMissing = false) which may raise an exception if key not existed.
  • or add to contains() additional parameter like contains($id, $group = null, &$value = null), then if cache contains key then $value will be set up.

What do you thing?

avatar mbabker
mbabker - comment - 4 Jan 2017

?

No caching API I have reviewed or worked with operates in this way and I personally would find that behavior confusing and inconsistent (essentially you're saying contains() should be able to return the value through a reference and I don't think a user configurable parameter should dictate whether the API throws an Exception).

You're right that it is not atomic. Every caching API has this same issue. There isn't a good solution for that. It's also not an issue unique to caching operations, filesystem operations have this same issue (in between the time it takes one to check a file exists and to read the file it could be deleted by another process as an example).

avatar anibalsanchez
anibalsanchez - comment - 4 Jan 2017

I have tested this item successfully on 492f05c

Test OK


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/13452.

avatar anibalsanchez anibalsanchez - test_item - 4 Jan 2017 - Tested successfully
avatar csthomas
csthomas - comment - 5 Jan 2017

Another options which probably won't convince you:

  • get(...) with additional parameter like get($id, $group = null, &$found = null). If key is found then $found = true otherwise false.
  • or get(...) with additional parameter like get($id, $group = null, $default = false). This way we can call $cache->get('key', null, false); and check if value === false without care about what internal handler value is returned if key has not been found.

This way we can have:

  • contains() to simple test key exists;
  • and extended get() for atomic contains() with get() together.
avatar mbabker
mbabker - comment - 5 Jan 2017

It's still violating SRP. I'd rather just leave the API alone and close this over add something to a signature to create a singular atomic method. And again, it's not a "flaw" in this implementation or isolated to cache usage; any CRUD operation to a data source can (and probably will at some point in its lifetime) run into an issue because of non-atomicy.

avatar csthomas
csthomas - comment - 5 Jan 2017

If contains() (for some handlers that call get in contains()) can in the future cache data in a variable in the handler until get() will be call then I agree with that.

avatar jeckodevelopment jeckodevelopment - change - 6 Jan 2017
Status Pending Ready to Commit
avatar jeckodevelopment
jeckodevelopment - comment - 6 Jan 2017

RTC


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/13452.

avatar rdeutz rdeutz - change - 6 Jan 2017
Status Ready to Commit Fixed in Code Base
Closed_Date 0000-00-00 00:00:00 2017-01-06 18:32:34
Closed_By rdeutz
Labels Added: ?
avatar rdeutz rdeutz - close - 6 Jan 2017
avatar rdeutz rdeutz - merge - 6 Jan 2017

Add a Comment

Login with GitHub to post a comment