Skip to content

Commit

Permalink
feature 3077 : improve cache invalidation
Browse files Browse the repository at this point in the history
- add "lastmodified" automatic field for categories, groups, users, tags and images tables
- provide a "server key" to the client cache manager

git-svn-id: http://piwigo.org/svn/trunk@28532 68402e56-0260-453c-a942-63ccdbb3a9ee
  • Loading branch information
mistic100 committed May 24, 2014
1 parent 59f418f commit fea2a4e
Show file tree
Hide file tree
Showing 12 changed files with 263 additions and 116 deletions.
11 changes: 5 additions & 6 deletions admin/batch_manager_global.php
Expand Up @@ -701,12 +701,11 @@
$template->assign('thumb_params', $thumb_params);
}

$template->assign(
array(
'nb_thumbs_page' => $nb_thumbs_page,
'nb_thumbs_set' => count($page['cat_elements_id']),
)
);
$template->assign(array(
'nb_thumbs_page' => $nb_thumbs_page,
'nb_thumbs_set' => count($page['cat_elements_id']),
'CACHE_KEYS' => get_admin_client_cache_keys(array('tags'))
));

trigger_action('loc_end_element_set_global');

Expand Down
5 changes: 4 additions & 1 deletion admin/batch_manager_unit.php
Expand Up @@ -248,7 +248,10 @@
));
}

$template->assign('ELEMENT_IDS', implode(',', $element_ids));
$template->assign(array(
'ELEMENT_IDS' => implode(',', $element_ids),
'CACHE_KEYS' => get_admin_client_cache_keys(array('tags')),
));
}

trigger_action('loc_end_element_set_unit');
Expand Down
6 changes: 5 additions & 1 deletion admin/cat_perm.php
Expand Up @@ -298,7 +298,11 @@
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign(array('PWG_TOKEN' => get_pwg_token(), 'INHERIT' => $conf['inheritance_by_default']));
$template->assign(array(
'PWG_TOKEN' => get_pwg_token(),
'INHERIT' => $conf['inheritance_by_default'],
'CACHE_KEYS' => get_admin_client_cache_keys(array('groups', 'users')),
));

$template->assign_var_from_handle('ADMIN_CONTENT', 'cat_perm');
?>
61 changes: 53 additions & 8 deletions admin/include/functions.php
Expand Up @@ -400,13 +400,8 @@ function delete_orphan_tags()
{
$orphan_tag_ids[] = $tag['id'];
}

$query = '
DELETE
FROM '.TAGS_TABLE.'
WHERE id IN ('.implode(',', $orphan_tag_ids).')
;';
pwg_query($query);

delete_tags($orphan_tag_ids);
}
}

Expand Down Expand Up @@ -2733,4 +2728,54 @@ function deltree($path, $trash_path=null)
}
}

?>
/**
* Returns keys to identify the state of main tables. A key consists of the
* last modification timestamp and the total of items (separated by a _).
* Additionally returns the hash of root path.
* Used to invalidate LocalStorage cache on admin pages.
*
* @param string|string[] list of keys to retrieve (categories,groups,images,tags,users)
* @return string[]
*/
function get_admin_client_cache_keys($requested=array())
{
$tables = array(
'categories' => CATEGORIES_TABLE,
'groups' => GROUPS_TABLE,
'images' => IMAGES_TABLE,
'tags' => TAGS_TABLE,
'users' => USER_INFOS_TABLE
);

if (!is_array($requested))
{
$requested = array($requested);
}
if (empty($requested))
{
$requested = array_keys($tables);
}
else
{
$requested = array_intersect($requested, array_keys($tables));
}

$keys = array(
'_hash' => md5(get_absolute_root_url()),
);

foreach ($requested as $item)
{
$query = '
SELECT CONCAT(
UNIX_TIMESTAMP(MAX(lastmodified)),
"_",
COUNT(*)
)
FROM '. $tables[$item] .'
;';
list($keys[$item]) = pwg_db_fetch_row(pwg_query($query));
}

return $keys;
}
6 changes: 5 additions & 1 deletion admin/picture_modify.php
Expand Up @@ -408,7 +408,11 @@
;';
$associate_options_selected = query2array($query, null, 'id');

$template->assign(compact('associate_options_selected', 'represent_options_selected'));
$template->assign(array(
'associate_options_selected' => $associate_options_selected,
'represent_options_selected' => $represent_options_selected,
'CACHE_KEYS' => get_admin_client_cache_keys(array('tags', 'categories')),
));

trigger_action('loc_end_picture_modify');

Expand Down
22 changes: 9 additions & 13 deletions admin/themes/default/js/LocalStorageCache.js
@@ -1,7 +1,8 @@
var LocalStorageCache = function(key, lifetime, loader) {
this.key = key;
this.lifetime = lifetime*1000;
this.loader = loader;
var LocalStorageCache = function(options) {
this.key = options.key + '-' + options.serverId;
this.serverKey = options.serverKey;
this.lifetime = options.lifetime ? options.lifetime*1000 : 3600*1000;
this.loader = options.loader;

this.storage = window.localStorage;
this.ready = !!this.storage;
Expand All @@ -14,28 +15,23 @@ LocalStorageCache.prototype.get = function(callback) {
if (this.ready && this.storage[this.key] != undefined) {
var cache = JSON.parse(this.storage[this.key]);

if (now - cache.timestamp <= this.lifetime) {
if (now - cache.timestamp <= this.lifetime && cache.key == this.serverKey) {
callback(cache.data);
return;
}
}

this.loader(function(data) {
if (that.ready) {
that.storage[that.key] = JSON.stringify({
timestamp: now,
data: data
});
}

that.set.call(that, data);
callback(data);
});
};

LocalStorageCache.prototype.set = function(data) {
if (this.ready) {
that.storage[that.key] = JSON.stringify({
this.storage[this.key] = JSON.stringify({
timestamp: new Date().getTime(),
key: this.serverKey,
data: data
});
}
Expand Down
35 changes: 17 additions & 18 deletions admin/themes/default/template/batch_manager_global.tpl
Expand Up @@ -68,16 +68,22 @@ jQuery(document).ready(function() {ldelim}
jQuery("a.preview-box").colorbox();

{* <!-- TAGS --> *}
var tagsCache = new LocalStorageCache('tagsAdminList', 5*60, function(callback) {
jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.tags.getAdminList', function(data) {
var tags = data.result.tags;
for (var i=0, l=tags.length; i<l; i++) {
tags[i].id = '~~' + tags[i].id + '~~';
}

callback(tags);
});
var tagsCache = new LocalStorageCache({
key: 'tagsAdminList',
serverKey: '{$CACHE_KEYS.tags}',
serverId: '{$CACHE_KEYS._hash}',
loader: function(callback) {
jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.tags.getAdminList', function(data) {
var tags = data.result.tags;
for (var i=0, l=tags.length; i<l; i++) {
tags[i].id = '~~' + tags[i].id + '~~';
}

callback(tags);
});
}
});

jQuery('[data-selectize=tags]').selectize({
Expand All @@ -92,14 +98,7 @@ jQuery(document).ready(function() {ldelim}
labelField: 'name',
searchField: ['name'],
plugins: ['remove_button'],
create: function(input, callback) {
tagsCache.clear();
callback({
id: input,
name: input
});
}
create: true
});

tagsCache.get(function(tags) {
Expand Down
35 changes: 17 additions & 18 deletions admin/themes/default/template/batch_manager_unit.tpl
Expand Up @@ -10,31 +10,30 @@
{footer_script}
(function(){
{* <!-- TAGS --> *}
var tagsCache = new LocalStorageCache('tagsAdminList', 5*60, function(callback) {
jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.tags.getAdminList', function(data) {
var tags = data.result.tags;
for (var i=0, l=tags.length; i<l; i++) {
tags[i].id = '~~' + tags[i].id + '~~';
}

callback(tags);
});
var tagsCache = new LocalStorageCache({
key: 'tagsAdminList',
serverKey: '{$CACHE_KEYS.tags}',
serverId: '{$CACHE_KEYS._hash}',
loader: function(callback) {
jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.tags.getAdminList', function(data) {
var tags = data.result.tags;
for (var i=0, l=tags.length; i<l; i++) {
tags[i].id = '~~' + tags[i].id + '~~';
}

callback(tags);
});
}
});

jQuery('[data-selectize=tags]').selectize({
valueField: 'id',
labelField: 'name',
searchField: ['name'],
plugins: ['remove_button'],
create: function(input, callback) {
tagsCache.clear();
callback({
id: input,
name: input
});
}
create: true
});

tagsCache.get(function(tags) {
Expand Down
84 changes: 61 additions & 23 deletions admin/themes/default/template/cat_perm.tpl
Expand Up @@ -6,10 +6,16 @@
{footer_script}
(function(){
{* <!-- GROUPS --> *}
var groupsCache = new LocalStorageCache('groupsAdminList', 5*60, function(callback) {
jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.groups.getList&per_page=99999', function(data) {
callback(data.result.groups);
});
var groupsCache = new LocalStorageCache({
key: 'groupsAdminList',
serverKey: '{$CACHE_KEYS.groups}',
serverId: '{$CACHE_KEYS._hash}',
loader: function(callback) {
jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.groups.getList&per_page=99999', function(data) {
callback(data.result.groups);
});
}
});

jQuery('[data-selectize=groups]').selectize({
Expand All @@ -32,22 +38,28 @@ groupsCache.get(function(groups) {
});

{* <!-- USERS --> *}
var usersCache = new LocalStorageCache('usersAdminList', 5*60, function(callback) {
var page = 0,
users = [];
(function load(page){
jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.users.getList&display=username&per_page=99999&page='+ page, function(data) {
users = users.concat(data.result.users);
if (data.result.paging.count == data.result.paging.per_page) {
load(++page);
}
else {
callback(users);
}
});
}(page));
var usersCache = new LocalStorageCache({
key: 'usersAdminList',
serverKey: '{$CACHE_KEYS.users}',
serverId: '{$CACHE_KEYS._hash}',
loader: function(callback) {
var users = [];
// recursive loader
(function load(page){
jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.users.getList&display=username&per_page=99999&page='+ page, function(data) {
users = users.concat(data.result.users);
if (data.result.paging.count == data.result.paging.per_page) {
load(++page);
}
else {
callback(users);
}
});
}(0));
}
});

jQuery('[data-selectize=users]').selectize({
Expand All @@ -68,6 +80,29 @@ usersCache.get(function(users) {
}, this));
});
});

{* <!-- TOGGLES --> *}
function checkStatusOptions() {
if (jQuery("input[name=status]:checked").val() == "private") {
jQuery("#privateOptions, #applytoSubAction").show();
}
else {
jQuery("#privateOptions, #applytoSubAction").hide();
}
}

checkStatusOptions();
jQuery("#selectStatus").change(function() {
checkStatusOptions();
});

{if isset($nb_users_granted_indirect) && $nb_users_granted_indirect>0}
jQuery(".toggle-indirectPermissions").click(function(e){
jQuery(".toggle-indirectPermissions").toggle();
jQuery("#indirectPermissionsDetails").toggle();
e.preventDefault();
});
{/if}
}());
{/footer_script}

Expand Down Expand Up @@ -111,8 +146,8 @@ usersCache.get(function(users) {
{if isset($nb_users_granted_indirect) && $nb_users_granted_indirect>0}
<p>
{'%u users have automatic permission because they belong to a granted group.'|@translate:$nb_users_granted_indirect}
<a href="#" id="indirectPermissionsDetailsHide" style="display:none">{'hide details'|@translate}</a>
<a href="#" id="indirectPermissionsDetailsShow">{'show details'|@translate}</a>
<a href="#" class="toggle-indirectPermissions" style="display:none">{'hide details'|@translate}</a>
<a href="#" class="toggle-indirectPermissions">{'show details'|@translate}</a>

<ul id="indirectPermissionsDetails" style="display:none">
{foreach from=$user_granted_indirect_groups item=group_details}
Expand Down Expand Up @@ -184,7 +219,10 @@ usersCache.get(function(users) {

<p style="margin:12px;text-align:left;">
<input class="submit" type="submit" value="{'Save Settings'|@translate}" name="submit">
<label id="applytoSubAction" style="display:none;"><input type="checkbox" name="apply_on_sub" {if $INHERIT}checked="checked"{/if}>{'Apply to sub-albums'|@translate}</label>
<label id="applytoSubAction" style="display:none;">
<input type="checkbox" name="apply_on_sub" {if $INHERIT}checked="checked"{/if}>
{'Apply to sub-albums'|@translate}
</label>
</p>

<input type="hidden" name="pwg_token" value="{$PWG_TOKEN}">
Expand Down

0 comments on commit fea2a4e

Please sign in to comment.