In the implementation of a test for #562932: {filter_format}.cache is not saved, I need to check if the cache was cleared correctly when filters were added/changed/reordered in a text format.

Currently, the test is doing something like this:

    $result = db_query('SELECT * FROM {cache_filter}')->fetchObject();
    $this->assertFalse($result, t('Filter cache cleared.'));

The problem I see here is that we cannot assume that the cache subsystem being used is the default (database tables, DrupalDatabaseCache class). So, we need an API function to check if a cache bin is empty.

A cache bin might be considered empty if it does not contain any valid (non expired) data for any cache ID.

Attached an initial patch:
- Added cache_bin_is_empty($bin) API function to check if a cache bin is empty .
- Added isEmpty() method to DrupalCacheInterface.
- Implemented isEmpty() in DrupalDatabaseCache class.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dropcube’s picture

FileSize
1.5 KB

uf, removed eclipse project stuff from the patch.

Dries’s picture

Why do we use the word _bin_ in the function name? I think this should be called cache_is_empty() for consistency.

catch’s picture

Shouldn't this be a db_query_range($query, 0, 1);?

dropcube’s picture

FileSize
1.51 KB

As suggested above:
- Changed the function name to cache_is_empty()
- Used db_query_range()

sun’s picture

+++ includes/cache.inc	12 Sep 2009 13:41:07 -0000
@@ -260,6 +275,19 @@
+  
+  /**
+  * Check if a cache bin is empty.
+  *

Trailing white-space and misaligned PHPDoc comment here.

+++ includes/cache.inc	12 Sep 2009 13:41:07 -0000
@@ -449,4 +477,11 @@
+    $result = db_query_range("SELECT data FROM {" . $this->bin . "} ", 0, 1)->fetchField();

Shouldn't this be a count query or similar?

If that first row by coincidence happens to be big, then we process a lot of data for nothing.

+++ includes/cache.inc	12 Sep 2009 13:41:07 -0000
@@ -449,4 +477,11 @@
+  }
+
 }

Please remove the trailing blank line after ::isEmpty().

I'm on crack. Are you, too?

Damien Tournoud’s picture

Status: Needs review » Needs work

See http://drupal.org/update/modules/6/7#select_count for how this query should be written.

dropcube’s picture

Status: Needs work » Needs review
FileSize
1.51 KB

- Fixed coding style issues.
- Used a count query as described at http://drupal.org/update/modules/6/7#select_count

Damien Tournoud’s picture

+++ includes/cache.inc	13 Sep 2009 11:30:24 -0000
@@ -260,6 +275,19 @@
+  /**
+   * Check if a cache bin is empty.
+   *
+   * A cache bin is considered empty if it does not contain any valid data for any
+   * cache ID.
+   *
+   * @param $bin
+   *   The cache bin to check.
+   * @return
+   *   TRUE if the cache bin specified is empty.
+   */
+  function isEmpty();

The docblock doesn't match the function parameters.

+++ includes/cache.inc	13 Sep 2009 11:30:24 -0000
@@ -449,4 +477,10 @@
+  function isEmpty() {
+    $this->garbageCollection();
+    $result = db_query_range("SELECT 1 FROM {" . $this->bin . "} ", 0, 1)->fetchField();
+    return empty($result);
+  }

This has to be a dynamic query, because the table changes.

Something like this should work:

db_select($this->bin)
  ->addExpression('1', 'count')
  ->limit(0, 1)
  ->execute()
  ->fetchField();

This review is powered by Dreditor.

Damien Tournoud’s picture

Never write DB:TNG from memory... the correct query is probably more:

$query = db_select($this->bin);
$query->addExpression('1');
$query->range(0, 1)
  ->execute()
  ->fetchField();
dropcube’s picture

FileSize
3.36 KB

- Used dynamic query.
- Fixed parameters in PHPDoc.
- Added tests.

dropcube’s picture

FileSize
3.31 KB

forgot to remove the comments, here it's

Status: Needs review » Needs work

The last submitted patch failed testing.

CorniI’s picture

Please add an implemenation to includes/cache-install.inc DrupalFakeCache class which was committed a minute ago...

dropcube’s picture

Status: Needs work » Needs review
FileSize
3.78 KB

- Added DrupalFakeCache::isEmpty() method.

sun’s picture

+++ includes/cache.inc	13 Sep 2009 15:47:47 -0000
@@ -449,4 +475,14 @@
+  function isEmpty() {
+    $this->garbageCollection();

Hm - auto-running GC looks like some (perhaps?) unwanted magic to me. Not sure though.

+++ modules/simpletest/tests/cache.test	13 Sep 2009 15:47:49 -0000
@@ -312,3 +312,40 @@
+class CacheIsEmptyCase extends CacheTestCase {
...
+      'group' => 'Cache'

Missing trailing comma after last array element.

+++ modules/simpletest/tests/cache.test	13 Sep 2009 15:47:49 -0000
@@ -312,3 +312,40 @@
+  function testIsEmpty() {
+    // Clear the cache bin.
+    cache_clear_all('*', $this->default_bin);
+    $this->assertTrue(cache_is_empty($this->default_bin), t('The cache bin is empty'));
+    // Add some data to the cache bin.
+    cache_set($this->default_cid, $this->default_value, $this->default_bin);
+    $this->assertCacheExists(t('Cache was set.'), $this->default_value, $this->default_cid);
+    $this->assertFalse(cache_is_empty($this->default_bin), t('The cache bin is not empty'));
+    // Remove the cached data.
+    cache_clear_all($this->default_cid, $this->default_bin);
+    $this->assertCacheRemoved(t('Cache was removed.'), $this->default_cid);
+    $this->assertTrue(cache_is_empty($this->default_bin), t('The cache bin is empty'));
+  }

Can we squeeze a blank line between the chunks/chapters here? :)

This review is powered by Dreditor.

Dries’s picture

I'm happy with this now, and it cleans up some of the existing APIs which is Slush-worthy. Committed to CVS HEAD. Thanks.

dropcube’s picture

Status: Needs review » Fixed

@sun

Hm - auto-running GC looks like some (perhaps?) unwanted magic to me. Not sure though.

There might be a case, when the bin only contains expired entries. So, once the garbage collector has run, the bin is actually empty. As the comments say, a cache bin is considered empty if it does not contain any *valid* data for any cache ID.

andypost’s picture

Status: Fixed » Needs work

Looks like this change is breaks alternative cache-backends (memcache, apc...) because it's not possible to count items in most of them.
Is this API change is really required?

catch’s picture

We have wildcard cache clearing in our API as well, but neither support that, I think it's OK for them to just silently not work for things like this - better than querying cache tables directly when you are using the default backend.

dropcube’s picture

Status: Needs work » Fixed

In this case, alternative cache-backends could use flags or any other approach to know if a cache bin is empty. For example, when a bin is flushed, set the flag to empty, then when data is set, change the flag to non-empty, etc...

chx’s picture

or, to be one the safe side you can always report as nonempty, worst can happen is a test fail, big deal.

Status: Fixed » Closed (fixed)
Issue tags: -API clean-up

Automatically closed -- issue fixed for 2 weeks with no activity.