Changeset 28532


Ignore:
Timestamp:
05/24/14 16:18:04 (5 years ago)
Author:
mistic100
Message:

feature 3077 : improve cache invalidation

  • add "lastmodified" automatic field for categories, groups, users, tags and images tables
  • provide a "server key" to the client cache manager
Location:
trunk
Files:
1 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/admin/batch_manager_global.php

    r28502 r28532  
    702702} 
    703703 
    704 $template->assign( 
    705   array( 
    706     'nb_thumbs_page' => $nb_thumbs_page, 
    707     'nb_thumbs_set' => count($page['cat_elements_id']), 
    708     ) 
    709   ); 
     704$template->assign(array( 
     705  'nb_thumbs_page' => $nb_thumbs_page, 
     706  'nb_thumbs_set' => count($page['cat_elements_id']), 
     707  'CACHE_KEYS' => get_admin_client_cache_keys(array('tags')) 
     708  )); 
    710709 
    711710trigger_action('loc_end_element_set_global'); 
  • trunk/admin/batch_manager_unit.php

    r28500 r28532  
    249249  } 
    250250 
    251   $template->assign('ELEMENT_IDS', implode(',', $element_ids)); 
     251  $template->assign(array( 
     252    'ELEMENT_IDS' => implode(',', $element_ids), 
     253    'CACHE_KEYS' => get_admin_client_cache_keys(array('tags')), 
     254    )); 
    252255} 
    253256 
  • trunk/admin/cat_perm.php

    r26461 r28532  
    299299// |                           sending html code                           | 
    300300// +-----------------------------------------------------------------------+ 
    301 $template->assign(array('PWG_TOKEN' => get_pwg_token(), 'INHERIT' => $conf['inheritance_by_default'])); 
     301$template->assign(array( 
     302  'PWG_TOKEN' => get_pwg_token(), 
     303  'INHERIT' => $conf['inheritance_by_default'], 
     304  'CACHE_KEYS' => get_admin_client_cache_keys(array('groups', 'users')), 
     305  )); 
    302306 
    303307$template->assign_var_from_handle('ADMIN_CONTENT', 'cat_perm'); 
  • trunk/admin/include/functions.php

    r27926 r28532  
    401401      $orphan_tag_ids[] = $tag['id']; 
    402402    } 
    403  
    404     $query = ' 
    405 DELETE 
    406   FROM '.TAGS_TABLE.' 
    407   WHERE id IN ('.implode(',', $orphan_tag_ids).') 
    408 ;'; 
    409     pwg_query($query); 
     403     
     404    delete_tags($orphan_tag_ids); 
    410405  } 
    411406} 
     
    27342729} 
    27352730 
    2736 ?> 
     2731/** 
     2732 * Returns keys to identify the state of main tables. A key consists of the 
     2733 * last modification timestamp and the total of items (separated by a _). 
     2734 * Additionally returns the hash of root path. 
     2735 * Used to invalidate LocalStorage cache on admin pages. 
     2736 * 
     2737 * @param string|string[] list of keys to retrieve (categories,groups,images,tags,users) 
     2738 * @return string[] 
     2739 */ 
     2740function get_admin_client_cache_keys($requested=array()) 
     2741{ 
     2742  $tables = array( 
     2743    'categories' => CATEGORIES_TABLE, 
     2744    'groups' => GROUPS_TABLE, 
     2745    'images' => IMAGES_TABLE, 
     2746    'tags' => TAGS_TABLE, 
     2747    'users' => USER_INFOS_TABLE 
     2748    ); 
     2749     
     2750  if (!is_array($requested)) 
     2751  { 
     2752    $requested = array($requested); 
     2753  } 
     2754  if (empty($requested)) 
     2755  { 
     2756    $requested = array_keys($tables); 
     2757  } 
     2758  else 
     2759  { 
     2760    $requested = array_intersect($requested, array_keys($tables)); 
     2761  } 
     2762   
     2763  $keys = array( 
     2764    '_hash' => md5(get_absolute_root_url()), 
     2765    ); 
     2766   
     2767  foreach ($requested as $item) 
     2768  { 
     2769    $query = ' 
     2770SELECT CONCAT( 
     2771    UNIX_TIMESTAMP(MAX(lastmodified)), 
     2772    "_", 
     2773    COUNT(*) 
     2774  ) 
     2775  FROM '. $tables[$item] .' 
     2776;'; 
     2777    list($keys[$item]) = pwg_db_fetch_row(pwg_query($query)); 
     2778  } 
     2779   
     2780  return $keys; 
     2781} 
  • trunk/admin/picture_modify.php

    r28500 r28532  
    409409$associate_options_selected = query2array($query, null, 'id'); 
    410410 
    411 $template->assign(compact('associate_options_selected', 'represent_options_selected')); 
     411$template->assign(array( 
     412  'associate_options_selected' => $associate_options_selected, 
     413  'represent_options_selected' => $represent_options_selected, 
     414  'CACHE_KEYS' => get_admin_client_cache_keys(array('tags', 'categories')), 
     415  )); 
    412416 
    413417trigger_action('loc_end_picture_modify'); 
  • trunk/admin/themes/default/js/LocalStorageCache.js

    r28494 r28532  
    1 var LocalStorageCache = function(key, lifetime, loader) { 
    2   this.key = key; 
    3   this.lifetime = lifetime*1000; 
    4   this.loader = loader; 
     1var LocalStorageCache = function(options) { 
     2  this.key = options.key + '-' + options.serverId; 
     3  this.serverKey = options.serverKey; 
     4  this.lifetime = options.lifetime ? options.lifetime*1000 : 3600*1000; 
     5  this.loader = options.loader; 
    56   
    67  this.storage = window.localStorage; 
     
    1516    var cache = JSON.parse(this.storage[this.key]); 
    1617     
    17     if (now - cache.timestamp <= this.lifetime) { 
     18    if (now - cache.timestamp <= this.lifetime && cache.key == this.serverKey) { 
    1819      callback(cache.data); 
    1920      return; 
     
    2223   
    2324  this.loader(function(data) { 
    24     if (that.ready) { 
    25       that.storage[that.key] = JSON.stringify({ 
    26         timestamp: now, 
    27         data: data 
    28       }); 
    29     } 
    30      
     25    that.set.call(that, data); 
    3126    callback(data); 
    3227  }); 
     
    3530LocalStorageCache.prototype.set = function(data) { 
    3631  if (this.ready) { 
    37     that.storage[that.key] = JSON.stringify({ 
     32    this.storage[this.key] = JSON.stringify({ 
    3833      timestamp: new Date().getTime(), 
     34      key: this.serverKey, 
    3935      data: data 
    4036    }); 
  • trunk/admin/themes/default/template/batch_manager_global.tpl

    r28502 r28532  
    6969   
    7070  {* <!-- TAGS --> *} 
    71   var tagsCache = new LocalStorageCache('tagsAdminList', 5*60, function(callback) { 
    72     jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.tags.getAdminList', function(data) { 
    73       var tags = data.result.tags; 
    74        
    75       for (var i=0, l=tags.length; i<l; i++) { 
    76         tags[i].id = '~~' + tags[i].id + '~~'; 
    77       } 
    78        
    79       callback(tags); 
    80     }); 
     71  var tagsCache = new LocalStorageCache({ 
     72    key: 'tagsAdminList', 
     73    serverKey: '{$CACHE_KEYS.tags}', 
     74    serverId: '{$CACHE_KEYS._hash}', 
     75 
     76    loader: function(callback) { 
     77      jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.tags.getAdminList', function(data) { 
     78        var tags = data.result.tags; 
     79         
     80        for (var i=0, l=tags.length; i<l; i++) { 
     81          tags[i].id = '~~' + tags[i].id + '~~'; 
     82        } 
     83         
     84        callback(tags); 
     85      }); 
     86    } 
    8187  }); 
    8288   
     
    9399    searchField: ['name'], 
    94100    plugins: ['remove_button'], 
    95     create: function(input, callback) { 
    96       tagsCache.clear(); 
    97        
    98       callback({ 
    99         id: input, 
    100         name: input 
    101       }); 
    102     } 
     101    create: true 
    103102  }); 
    104103   
  • trunk/admin/themes/default/template/batch_manager_unit.tpl

    r28500 r28532  
    1111(function(){ 
    1212{* <!-- TAGS --> *} 
    13 var tagsCache = new LocalStorageCache('tagsAdminList', 5*60, function(callback) { 
    14   jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.tags.getAdminList', function(data) { 
    15     var tags = data.result.tags; 
    16      
    17     for (var i=0, l=tags.length; i<l; i++) { 
    18       tags[i].id = '~~' + tags[i].id + '~~'; 
    19     } 
    20      
    21     callback(tags); 
    22   }); 
     13var tagsCache = new LocalStorageCache({ 
     14  key: 'tagsAdminList', 
     15  serverKey: '{$CACHE_KEYS.tags}', 
     16  serverId: '{$CACHE_KEYS._hash}', 
     17 
     18  loader: function(callback) { 
     19    jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.tags.getAdminList', function(data) { 
     20      var tags = data.result.tags; 
     21       
     22      for (var i=0, l=tags.length; i<l; i++) { 
     23        tags[i].id = '~~' + tags[i].id + '~~'; 
     24      } 
     25       
     26      callback(tags); 
     27    }); 
     28  } 
    2329}); 
    2430 
     
    2834  searchField: ['name'], 
    2935  plugins: ['remove_button'], 
    30   create: function(input, callback) { 
    31     tagsCache.clear(); 
    32      
    33     callback({ 
    34       id: input, 
    35       name: input 
    36     }); 
    37   } 
     36  create: true 
    3837}); 
    3938 
  • trunk/admin/themes/default/template/cat_perm.tpl

    r28496 r28532  
    77(function(){ 
    88{* <!-- GROUPS --> *} 
    9 var groupsCache = new LocalStorageCache('groupsAdminList', 5*60, function(callback) { 
    10   jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.groups.getList&per_page=99999', function(data) { 
    11     callback(data.result.groups); 
    12   }); 
     9var groupsCache = new LocalStorageCache({ 
     10  key: 'groupsAdminList', 
     11  serverKey: '{$CACHE_KEYS.groups}', 
     12  serverId: '{$CACHE_KEYS._hash}', 
     13 
     14  loader: function(callback) { 
     15    jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.groups.getList&per_page=99999', function(data) { 
     16      callback(data.result.groups); 
     17    }); 
     18  } 
    1319}); 
    1420 
     
    3339 
    3440{* <!-- USERS --> *} 
    35 var usersCache = new LocalStorageCache('usersAdminList', 5*60, function(callback) { 
    36   var page = 0, 
    37       users = []; 
    38     
    39   (function load(page){ 
    40     jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.users.getList&display=username&per_page=99999&page='+ page, function(data) { 
    41       users = users.concat(data.result.users); 
    42        
    43       if (data.result.paging.count == data.result.paging.per_page) { 
    44         load(++page); 
    45       } 
    46       else { 
    47         callback(users); 
    48       } 
    49     }); 
    50   }(page)); 
     41var usersCache = new LocalStorageCache({ 
     42  key: 'usersAdminList', 
     43  serverKey: '{$CACHE_KEYS.users}', 
     44  serverId: '{$CACHE_KEYS._hash}', 
     45 
     46  loader: function(callback) { 
     47    var users = []; 
     48     
     49    // recursive loader 
     50    (function load(page){ 
     51      jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.users.getList&display=username&per_page=99999&page='+ page, function(data) { 
     52        users = users.concat(data.result.users); 
     53         
     54        if (data.result.paging.count == data.result.paging.per_page) { 
     55          load(++page); 
     56        } 
     57        else { 
     58          callback(users); 
     59        } 
     60      }); 
     61    }(0)); 
     62  } 
    5163}); 
    5264 
     
    6981  }); 
    7082}); 
     83 
     84{* <!-- TOGGLES --> *} 
     85function checkStatusOptions() { 
     86  if (jQuery("input[name=status]:checked").val() == "private") { 
     87    jQuery("#privateOptions, #applytoSubAction").show(); 
     88  } 
     89  else { 
     90    jQuery("#privateOptions, #applytoSubAction").hide(); 
     91  } 
     92} 
     93 
     94checkStatusOptions(); 
     95jQuery("#selectStatus").change(function() { 
     96  checkStatusOptions(); 
     97}); 
     98 
     99{if isset($nb_users_granted_indirect) && $nb_users_granted_indirect>0} 
     100  jQuery(".toggle-indirectPermissions").click(function(e){ 
     101    jQuery(".toggle-indirectPermissions").toggle(); 
     102    jQuery("#indirectPermissionsDetails").toggle(); 
     103    e.preventDefault(); 
     104  }); 
     105{/if} 
    71106}()); 
    72107{/footer_script} 
     
    112147  <p> 
    113148    {'%u users have automatic permission because they belong to a granted group.'|@translate:$nb_users_granted_indirect} 
    114     <a href="#" id="indirectPermissionsDetailsHide" style="display:none">{'hide details'|@translate}</a> 
    115     <a href="#" id="indirectPermissionsDetailsShow">{'show details'|@translate}</a> 
     149    <a href="#" class="toggle-indirectPermissions" style="display:none">{'hide details'|@translate}</a> 
     150    <a href="#" class="toggle-indirectPermissions">{'show details'|@translate}</a> 
    116151 
    117152    <ul id="indirectPermissionsDetails" style="display:none"> 
     
    185220  <p style="margin:12px;text-align:left;"> 
    186221    <input class="submit" type="submit" value="{'Save Settings'|@translate}" name="submit"> 
    187     <label id="applytoSubAction" style="display:none;"><input type="checkbox" name="apply_on_sub" {if $INHERIT}checked="checked"{/if}>{'Apply to sub-albums'|@translate}</label> 
     222    <label id="applytoSubAction" style="display:none;"> 
     223      <input type="checkbox" name="apply_on_sub" {if $INHERIT}checked="checked"{/if}> 
     224      {'Apply to sub-albums'|@translate} 
     225    </label> 
    188226  </p> 
    189227 
  • trunk/admin/themes/default/template/picture_modify.tpl

    r28500 r28532  
    1111(function(){ 
    1212{* <!-- CATEGORIES --> *} 
    13 var categoriesCache = new LocalStorageCache('categoriesAdminList', 5*60, function(callback) { 
    14   jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.categories.getAdminList', function(data) { 
    15     callback(data.result.categories); 
    16   }); 
     13var categoriesCache = new LocalStorageCache({ 
     14  key: 'categoriesAdminList', 
     15  serverKey: '{$CACHE_KEYS.categories}', 
     16  serverId: '{$CACHE_KEYS._hash}', 
     17 
     18  loader: function(callback) { 
     19    jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.categories.getAdminList', function(data) { 
     20      callback(data.result.categories); 
     21    }); 
     22  } 
    1723}); 
    1824 
     
    3743 
    3844{* <!-- TAGS --> *} 
    39 var tagsCache = new LocalStorageCache('tagsAdminList', 5*60, function(callback) { 
    40   jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.tags.getAdminList', function(data) { 
    41     var tags = data.result.tags; 
    42      
    43     for (var i=0, l=tags.length; i<l; i++) { 
    44       tags[i].id = '~~' + tags[i].id + '~~'; 
    45     } 
    46      
    47     callback(tags); 
    48   }); 
     45var tagsCache = new LocalStorageCache({ 
     46  key: 'tagsAdminList', 
     47  serverKey: '{$CACHE_KEYS.tags}', 
     48  serverId: '{$CACHE_KEYS._hash}', 
     49 
     50  loader: function(callback) { 
     51    jQuery.getJSON('{$ROOT_URL}ws.php?format=json&method=pwg.tags.getAdminList', function(data) { 
     52      var tags = data.result.tags; 
     53       
     54      for (var i=0, l=tags.length; i<l; i++) { 
     55        tags[i].id = '~~' + tags[i].id + '~~'; 
     56      } 
     57       
     58      callback(tags); 
     59    }); 
     60  } 
    4961}); 
    5062 
     
    5466  searchField: ['name'], 
    5567  plugins: ['remove_button'], 
    56   create: function(input, callback) { 
    57     tagsCache.clear(); 
    58      
    59     callback({ 
    60       id: input, 
    61       name: input 
    62     }); 
    63   } 
     68  create: true 
    6469}); 
    6570 
  • trunk/install/piwigo_structure-mysql.sql

    r28143 r28532  
    3737  `image_order` varchar(128) default NULL, 
    3838  `permalink` varchar(64) binary default NULL, 
     39  `lastmodified` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    3940  PRIMARY KEY  (`id`), 
    4041  UNIQUE KEY `categories_i3` (`permalink`), 
    41   KEY `categories_i2` (`id_uppercat`) 
     42  KEY `categories_i2` (`id_uppercat`), 
     43  KEY `lastmodified` (`lastmodified`) 
    4244) ENGINE=MyISAM; 
    4345 
     
    107109  `name` varchar(255) NOT NULL default '', 
    108110  `is_default` enum('true','false') NOT NULL default 'false', 
    109   PRIMARY KEY  (`id`), 
    110   UNIQUE KEY `groups_ui1` (`name`) 
     111  `lastmodified` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
     112  PRIMARY KEY  (`id`), 
     113  UNIQUE KEY `groups_ui1` (`name`), 
     114  KEY `lastmodified` (`lastmodified`) 
    111115) ENGINE=MyISAM; 
    112116 
     
    200204  `latitude` double(8, 6) default NULL, 
    201205  `longitude` double(9, 6) default NULL, 
     206  `lastmodified` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    202207  PRIMARY KEY  (`id`), 
    203208  KEY `images_i2` (`date_available`), 
     
    206211  KEY `images_i5` (`date_creation`), 
    207212  KEY `images_i1` (`storage_category_id`), 
    208   KEY `images_i6` (`latitude`) 
     213  KEY `images_i6` (`latitude`), 
     214  KEY `lastmodified` (`lastmodified`) 
    209215) ENGINE=MyISAM; 
    210216 
     
    306312  `name` varchar(255) NOT NULL default '', 
    307313  `url_name` varchar(255) binary NOT NULL default '', 
    308   PRIMARY KEY  (`id`), 
    309   KEY `tags_i1` (`url_name`) 
     314  `lastmodified` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
     315  PRIMARY KEY  (`id`), 
     316  KEY `tags_i1` (`url_name`), 
     317  KEY `lastmodified` (`lastmodified`) 
    310318) ENGINE=MyISAM; 
    311319 
     
    424432  `level` tinyint unsigned NOT NULL default '0', 
    425433  `activation_key` char(20) default NULL, 
    426   PRIMARY KEY (`user_id`) 
     434  `lastmodified` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
     435  PRIMARY KEY (`user_id`), 
     436  KEY `lastmodified` (`lastmodified`) 
    427437) ENGINE=MyISAM; 
    428438 
Note: See TracChangeset for help on using the changeset viewer.