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

Improving the caching mechanism, in preparation for providing a memcache... #9

Merged
merged 5 commits into from
Dec 11, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Bugzilla.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
$wgAutoloadClasses['BugzillaCacheI'] = $cwd . '/cache/BugzillaCacheI.class.php'; $wgAutoloadClasses['BugzillaCacheI'] = $cwd . '/cache/BugzillaCacheI.class.php';
$wgAutoloadClasses['BugzillaCacheMysql'] = $cwd . '/cache/BugzillaCacheMysql.class.php'; $wgAutoloadClasses['BugzillaCacheMysql'] = $cwd . '/cache/BugzillaCacheMysql.class.php';
$wgAutoloadClasses['BugzillaCacheDummy'] = $cwd . '/cache/BugzillaCacheDummy.class.php'; $wgAutoloadClasses['BugzillaCacheDummy'] = $cwd . '/cache/BugzillaCacheDummy.class.php';
$wgAutoloadClasses['BugzillaCacheApc'] = $cwd . '/cache/BugzillaCacheApc.class.php';
$wgAutoloadClasses['BugzillaCacheMemcache'] = $cwd . '/cache/BugzillaCacheMemcache.class.php';






/** /**
Expand Down
2 changes: 1 addition & 1 deletion BugzillaOutput.class.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public function setup_template_data() {
$key = md5($this->query->id . $this->_get_size() . get_class($this)); $key = md5($this->query->id . $this->_get_size() . get_class($this));
$cache = $this->_getCache(); $cache = $this->_getCache();
if($result = $cache->get($key)) { if($result = $cache->get($key)) {
$image = $result['data']; $image = $result;
$this->response->image = $wgBugzillaChartUrl . '/' . $image; $this->response->image = $wgBugzillaChartUrl . '/' . $image;
} else { } else {
$this->response->image = $wgBugzillaChartUrl . '/' . $this->generate_chart($key) . '.png'; $this->response->image = $wgBugzillaChartUrl . '/' . $this->generate_chart($key) . '.png';
Expand Down
9 changes: 3 additions & 6 deletions BugzillaQuery.class.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function __construct($type, $options, $title) {
$this->cache = FALSE; $this->cache = FALSE;
$this->_set_options($options); $this->_set_options($options);
} }

protected function _getCache() protected function _getCache()
{ {
global $wgCacheObject; global $wgCacheObject;
Expand Down Expand Up @@ -119,7 +119,7 @@ public function fetch() {


// If the cache entry is older than this we need to invalidate it // If the cache entry is older than this we need to invalidate it
$expiry = strtotime("-$wgBugzillaCacheMins minutes"); $expiry = strtotime("-$wgBugzillaCacheMins minutes");

if( !$row ) { if( !$row ) {
// No cache entry // No cache entry


Expand All @@ -132,10 +132,7 @@ public function fetch() {
return $this->data; return $this->data;
}else { }else {
// Cache is good, use it // Cache is good, use it

$this->data = unserialize($row);
$this->id = $row['id'];
$this->fetched_at = wfTimestamp(TS_DB, $row['fetched_at']);
$this->data = unserialize($row['data']);
$this->cached = TRUE; $this->cached = TRUE;
} }
} }
Expand Down
18 changes: 18 additions & 0 deletions cache/BugzillaCacheApc.class.php
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

class BugzillaCacheApc implements BugzillaCacheI
{

public function set($key, $value, $ttl = 300) {
return apc_store($key, $value, $ttl);
}

public function get($key) {
return apc_fetch($key);
}

public function expire($key) {
return apc_delete($key);
}

}
35 changes: 35 additions & 0 deletions cache/BugzillaCacheMemcache.class.php
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

class BugzillaCacheMemcache implements BugzillaCacheI
{

protected $_memcache;

public function __construct() {
// As much as I detest using a global here, it is necessary to avoid
// needing to inject the $wgMemc object, thus breaking the usefulness
// of the interface. Using the $wgMemc object is important for the
// consistency of the code.
global $wgMemc;
$this->_memcache = $wgMemc;
}

public function set($key, $value, $ttl = 300) {
// Get the wikimedia key style expected
$key = wfMemcKey($key);
return $this->_memcache->set($key, $value, $ttl);
}

public function get($key) {
// Get the wikimedia key style expected
$key = wfMemcKey($key);
return $this->_memcache->get($key);
}

public function expire($key) {
// Get the wikimedia key style expected
$key = wfMemcKey($key);
return $this->_memcache->delete($key);
}

}
73 changes: 41 additions & 32 deletions cache/BugzillaCacheMysql.class.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2,43 +2,51 @@


class BugzillaCacheMysql implements BugzillaCacheI class BugzillaCacheMysql implements BugzillaCacheI
{ {
protected $_slave;
protected $_master;

public function __construct()
{
// TO-DO: This methodology creates some difficulties to unit testing.
$this->_slave = wfGetDB( DB_SLAVE );
$this->_master = wfGetDB( DB_MASTER );
}

public function set($key, $value, $ttl = 300) public function set($key, $value, $ttl = 300)
{ {
//TO-DO: It's probably a bad thing to write straight SQL against an $master = $this->_getDatabase();
// abstraction layer. The abstraction layer doens't offer full $key_c = $key;
// functionality, though, and this reduces the number of queries $value_c = $value;
// for something as simple as caching. Also, the doQuery() method
// is marked "private" but that is commented out; that may change $date = wfTimestamp(TS_DB);
// in a future release. $now = time(); // Using time() because it's a PHP built-in.
$key_c = $this->_master->strencode($key); $expires = $now + $ttl;
$value_c = $this->_master->strencode($value); if (null === $this->get($key)) {
$date = wfTimestamp(TS_DB); $res = $master->insert(
$now = time(); // Using time() because it's a PHP built-in. 'bugzilla_cache',
$expires = $now+$ttl; array(

'`key`' => $key_c,
$sql = 'REPLACE INTO bugzilla_cache 'fetched_at' => $date,
(`key`, `fetched_at`, `data`, `expires`) 'data' => $value_c,
VALUES 'expires' => $expires
("%s", "%s", "%s", %d)'; ),

__METHOD__
$sql = sprintf($sql, $key_c, $date, $value_c, $expires); );
$res = $this->_master->doQuery($sql); } else {
$res = $this->update(
'bugzilla_cache',
array(
'fetched_at' => $date
),
'`key` = "' . $key_c . '"',

__METHOD__
);
}

return $res; return $res;
} }


protected function _getDatabase($type = DB_MASTER) {
return wfGetDB($type);
}

public function get($key) public function get($key)
{ {
$res = $this->_slave->select( $slave = $this->_getDatabase(DB_SLAVE);
$res = $slave->select(
'bugzilla_cache', 'bugzilla_cache',
array('id', 'fetched_at', 'data', 'expires'), array('id', 'fetched_at', 'data', 'expires'),
'`key` = "' . $key . '"', '`key` = "' . $key . '"',
Expand All @@ -54,12 +62,13 @@ public function get($key)
return; return;
} }


return $row; return $row['data'];
} }


public function expire($key) public function expire($key)
{ {
return $this->_master->delete( $master = $this->_getDatabase();
return $master->delete(
'bugzilla_cache', 'bugzilla_cache',
array('`key`="' . $key .'"') array('`key`="' . $key .'"')
); );
Expand Down