Changeset 28532


Ignore:
Timestamp:
May 24, 2014, 4:18:04 PM (10 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.