Igor Gariev (gariev) wrote in changelog,
Igor Gariev
gariev
changelog

[ljcom] r11087: LJSUP-10124: [internal] Make user cluste...

Committer: gariev
LJSUP-10124: [internal] Make user cluster DB switching dynamically
Updated ExtBlock - better local cache control, serialization support
U   trunk/bin/upgrading/update-db-local.pl
U   trunk/cgi-bin/LJ/ExtBlock.pm
U   trunk/cgi-bin/LJ/Hooks/SUP.pm
Modified: trunk/bin/upgrading/update-db-local.pl
===================================================================
--- trunk/bin/upgrading/update-db-local.pl	2011-10-12 18:20:21 UTC (rev 11086)
+++ trunk/bin/upgrading/update-db-local.pl	2011-10-12 22:06:02 UTC (rev 11087)
@@ -1019,6 +1019,8 @@
 (
     blockid         varchar(20),
     blocktext       blob,
+    last_updated    INT UNSIGNED NOT NULL DEFAULT 0,
+    serialization   char(1),                        -- default is NULL, 'J' = JSON, 'S' = Storable
     PRIMARY KEY (blockid)
 )
 TYPE=InnoDB
@@ -2139,6 +2141,11 @@
         do_alter("sup_extblocks",
                  "ALTER TABLE sup_extblocks ADD last_updated INT UNSIGNED NOT NULL DEFAULT 0");
     }
+    
+    unless (column_type("sup_extblocks", "serialization")) {
+        do_alter("sup_extblocks",
+                 "ALTER TABLE sup_extblocks ADD serialization CHAR(1)");
+    }
 
     unless (column_type("userapps", "width")) {
         do_alter("userapps", qq{

Modified: trunk/cgi-bin/LJ/ExtBlock.pm
===================================================================
--- trunk/cgi-bin/LJ/ExtBlock.pm	2011-10-12 18:20:21 UTC (rev 11086)
+++ trunk/cgi-bin/LJ/ExtBlock.pm	2011-10-12 22:06:02 UTC (rev 11087)
@@ -2,15 +2,66 @@
 use strict;
 use warnings;
 
+=head1 NAME 
+
+LJ::ExtBlock - LJ interface to persistent store for everything
+
+Don't create a table each time you need to store something!
+
+=head1 SYNOPSYS
+
+    use LJ::ExtBlock;
+
+    LJ::ExtBlock->create_or_replace('foo', {"some" => "data"});
+
+    # ... later ...
+    if (my $block = LJ::ExtBlock->load_by_id('foo')) {
+        my $data = $block->data;
+    }
+
+=head1 METHODS
+
+=over 
+
+=item $block = LJ::ExtBlock->create_or_replace($block_id, $data)
+
+
+=item $block = LJ::ExtBlock->load_by_id($block_id, $options)
+
+Options (hashref): 
+
+=over
+
+=item - skip_local_cache (boolean) - do not use in-process cache at all, reload everytime from memcache/db
+
+=item - cache_valid (number) - use local cache only if it's at most <number> seconds late, default is 5 mins.
+
+=back 
+
+
+=item $data = $block->data
+
+
+=item $block->delete or LJ::ExtBlock->delete($block_id)
+
+
+=back
+
+=cut
+
+
 use Carp qw/ croak confess /;
+use LJ::JSON;
 
+our %LOCAL_CACHE; ## block id --> [$object, time()]
+
 ##
 ## Memcache routines
 ##
 use base 'LJ::MemCacheable';
     *_memcache_id                   = \&blockid;
 sub _memcache_key_prefix            { "sup_extblock" }
-sub _memcache_stored_props          { qw/ 1 blockid blocktext / }
+sub _memcache_stored_props          { qw/ 2 blockid blocktext last_updated serialization/ }
     *_memcache_hashref_to_object    = \*_new;
 sub _memcache_expires               { 3600 }
 
@@ -24,6 +75,15 @@
     my $params = shift || {};
     confess "No object data" unless ref $params eq 'HASH';
     my $self  = bless $params, ref $class || $class;
+
+    if (my $serialization = $self->{'serialization'}) {
+        if ($serialization eq 'J') {
+            $self->{'_data'} = LJ::JSON->from_json($self->{'blocktext'});
+        } else {
+            die "Unknown serialization method: $serialization";
+        }
+    }
+
     return $self;
 }
 
@@ -33,6 +93,10 @@
 sub blockid    { shift->{blockid}           }
 sub blocktext  { shift->{blocktext}         }
 sub timestamp  { shift->{last_updated}      }
+sub data       { 
+    my $self = shift; 
+    return $self->{'_data'} || $self->{'blocktext'};
+}
 
 ##
 ## Class method. Returns a list (arrayref) of all known block IDs
@@ -52,14 +116,18 @@
     my $opts = shift || {};
 
     ## 1. Find in local cache
-    if ($LJ::REQ_CACHE_EXT_BLOCK{$id} && !$opts->{'skip_local_cache'}) {
-        return $LJ::REQ_CACHE_EXT_BLOCK{$id};
+    my $cache_valid = $opts->{'cache_valid'} || 300;
+    if (my $b = $LOCAL_CACHE{$id}) {
+        my ($ext_block, $cached_on) = @$b;
+        if (!$opts->{'skip_local_cache'} && ($cached_on + $cache_valid > time)) {
+            return $ext_block;
+        }
     }
 
     ## 2. Find in memcache
     my $self = $class->_load_from_memcache($id);
     if ($self) {
-        $LJ::REQ_CACHE_EXT_BLOCK{$id} = $self;
+        $LOCAL_CACHE{$id} = [$self, time()];
         return $self;
     }
 
@@ -73,7 +141,7 @@
 
     $self = $class->_new($hash);
     $self->_store_to_memcache;
-    $LJ::REQ_CACHE_EXT_BLOCK{$id} = $self;
+    $LOCAL_CACHE{$id} = [$self, time()];
     return $self;
 }
 
@@ -85,16 +153,27 @@
     my $id = shift;
     my $text = shift;
 
+    my $serialization;
+    if (ref $text) {
+        $serialization = 'J';
+        $text = LJ::JSON->to_json($text);
+    }
+
     my $dbh = LJ::get_db_writer();
-    my $sth = $dbh->prepare("REPLACE INTO sup_extblocks (blockid, blocktext, last_updated) VALUES (?, ?, ?)");
+    my $sth = $dbh->prepare("REPLACE INTO sup_extblocks (blockid, blocktext, last_updated, serialization) VALUES (?, ?, ?, ?)");
 
     my $now = time;
-    $sth->execute($id, $text, $now)
+    $sth->execute($id, $text, $now, $serialization)
         or confess 'failed to replace into ext block with id: ' . $id . ', error = ' . $DBI::errstr;
 
-    my $self = $class->_new({ blockid => $id, blocktext => $text, last_updated => $now });
+    my $self = $class->_new({ 
+        blockid         => $id, 
+        blocktext       => $text, 
+        last_updated    => $now,
+        serialization   => $serialization,
+    });
     $self->_store_to_memcache;
-    $LJ::REQ_CACHE_EXT_BLOCK{$id} = $self;
+    $LOCAL_CACHE{$id} = [$self, time()];
 
     return $self;
 }
@@ -107,7 +186,7 @@
     my $id = shift;
     $id = $class->{blockid} if ref $class; # === if object
 
-    undef $LJ::REQ_CACHE_EXT_BLOCK{$id};
+    undef $LOCAL_CACHE{$id};
     
     $class->_remove_from_memcache($id);
  

Modified: trunk/cgi-bin/LJ/Hooks/SUP.pm
===================================================================
--- trunk/cgi-bin/LJ/Hooks/SUP.pm	2011-10-12 18:20:21 UTC (rev 11086)
+++ trunk/cgi-bin/LJ/Hooks/SUP.pm	2011-10-12 22:06:02 UTC (rev 11087)
@@ -324,7 +324,6 @@
 
 LJ::register_hook('start_request', sub{
     $LJ::SUP_REQUEST_ID = int(rand(1e9));
-    %LJ::REQ_CACHE_EXT_BLOCK = ();
     @LJ::SUP_LJ_ENTRY_REQ = ();
     return;
 });

Tags: gariev, ljcom, pl, pm
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments