madeon (madeon) wrote in changelog,
madeon
madeon
changelog

[livejournal] r22437: LJSUP-12940: Remove duplicating users fr...

Committer: sbelyaev
LJSUP-12940: Remove duplicating users from reposted list and fix counter
U   trunk/cgi-bin/LJ/Entry/Repost.pm
Modified: trunk/cgi-bin/LJ/Entry/Repost.pm
===================================================================
--- trunk/cgi-bin/LJ/Entry/Repost.pm	2012-07-13 08:10:50 UTC (rev 22436)
+++ trunk/cgi-bin/LJ/Entry/Repost.pm	2012-07-13 08:28:28 UTC (rev 22437)
@@ -7,16 +7,16 @@
 require 'ljprotocol.pl';
 use LJ::Lang;
 
-use constant {  REPOST_KEYS_EXPIRING => 0,
-                REPOST_USERS_LIST_LIMIT => 25,
+use constant { REPOST_KEYS_EXPIRING => 60*60*2,
+               REPOST_USERS_LIST_LIMIT => 25,
              };
 
-
 sub __get_count {
     my ($u, $jitemid) = @_;
 
     my $journalid = $u->userid;
     my $memcache_key = "reposted_count:$journalid:$jitemid";
+
     my ($count) = LJ::MemCache::get($memcache_key);
     if ($count) {
         return $count;
@@ -32,7 +32,9 @@
                                                    $u->userid,
                                                    $jitemid, );
 
-    LJ::MemCache::set($memcache_key, $count_jitemid, REPOST_KEYS_EXPIRING);
+    LJ::MemCache::set(  $memcache_key,
+                        $count_jitemid,
+                        REPOST_KEYS_EXPIRING );
 
     return $count_jitemid;
 }
@@ -52,12 +54,12 @@
         or die "get cluster for journal failed";
 
     my @repost_jitemid = $dbcr->selectrow_array( 'SELECT reposted_jitemid ' .
-                                                  'FROM repost2 ' .
-                                                  'WHERE journalid = ? AND jitemid = ? AND reposterid = ?',
-                                                  undef,
-                                                  $u->userid,
-                                                  $jitemid,
-                                                  $reposterid, );
+                                                 'FROM repost2 ' .
+                                                 'WHERE journalid = ? AND jitemid = ? AND reposterid = ?',
+                                                 undef,
+                                                 $u->userid,
+                                                 $jitemid,
+                                                 $reposterid, );
 
     if (@repost_jitemid) {
         LJ::MemCache::set($memcache_key, $repost_jitemid[0], REPOST_KEYS_EXPIRING);
@@ -68,55 +70,68 @@
 }
 
 sub __create_repost_record {
-    my ($u, $itemid, $repost_journalid, $repost_itemid) = @_;
+    my ($u, $jitemid, $repost_journalid, $repost_itemid) = @_;
 
     my $journalid = $u->userid;
     my $time  = time();
-    my $query = 'INSERT INTO repost2(journalid,
-                                    jitemid,
-                                    reposterid,
-                                    reposted_jitemid';
-    $query .= LJ::is_enabled('repost2_with_time') ? 
-                            ',repost_time) VALUES(?,?,?,?,?)' :
-                            ') VALUES(?,?,?,?)'; 
-                                    
+    my $query = 'INSERT INTO repost2 (journalid,' .
+                                     'jitemid,' .
+                                     'reposterid, ' .
+                                     'reposted_jitemid' .
+                                     ',repost_time) VALUES(?,?,?,?,?)'; 
+
     $u->do( $query,
             undef,
             $u->userid,
-            $itemid,
+            $jitemid,
             $repost_journalid,
             $repost_itemid,
             $time );
 
-    my $memcache_key_count = "reposted_count:$journalid:$itemid";
-    my $memcache_key_status = "reposted_itemid:$journalid:$itemid:$repost_journalid";
+    # 
+    # remove last users list block from cache
+    # 
+    my $current_count = __get_count($u, $jitemid);
+    my $last_block_id = int( $current_count / REPOST_USERS_LIST_LIMIT );    
+    LJ::MemCache::delete("reposters_list_chunk:$journalid:$jitemid:$last_block_id");
+    
+    #
+    # inc or add reposters counter
+    #
+    my $memcache_key_count = "reposted_count:$journalid:$jitemid";
+    LJ::MemCache::incr($memcache_key_count, 1);       
 
-    __clear_reposters_list($journalid, $itemid);
-
-    if (!LJ::MemCache::incr($memcache_key_count, 1)) {
-        my $count = __get_count($u, $itemid);
-        LJ::MemCache::add($memcache_key_count, int($count));
-    }
-
+    my $memcache_key_status = "reposted_itemid:$journalid:$jitemid:$repost_journalid";
     LJ::MemCache::set($memcache_key_status, $repost_itemid, REPOST_KEYS_EXPIRING);
 }
 
 sub __delete_repost_record {
-    my ($u, $itemid, $reposterid) = @_;
-
+    my ($u, $jitemid, $reposterid) = @_;
     my $journalid = $u->userid;
-    my $memcache_key = "reposted_count:$journalid:$itemid";
-    my $memcache_key_status = "reposted_itemid:$journalid:$itemid:$reposterid";
-    LJ::MemCache::delete($memcache_key);
-    LJ::MemCache::delete($memcache_key_status);
 
-    __clear_reposters_list($journalid, $itemid);
-
+    #
+    # remove users list
+    #
+    __clean_reposters_list($u, $jitemid);
+    
+    #
+    # remove record from db
+    #
     $u->do('DELETE FROM repost2 WHERE journalid = ? AND jitemid = ? AND reposterid = ?',
             undef,
             $u->userid,
-            $itemid,
+            $jitemid,
             $reposterid,);
+
+    #
+    # remove cached reposts count 
+    #
+    LJ::MemCache::delete("reposted_count:$journalid:$jitemid");
+        
+    #
+    # remove cached status
+    #
+    LJ::MemCache::delete("reposted_itemid:$journalid:$jitemid:$reposterid");
 }
 
 sub __create_post {
@@ -131,23 +146,31 @@
     my $event_text_stub = LJ::Lang::ml('entry.reference.event_text', { 'url' =>  $url}) | 
                           "Entry reposted from $url";
 
+    #
+    # Needs to create new entry
+    #
     my %req = ( 'username'    => $u->user,
                 'event'       => $event_text_stub,
                 'subject'     => '',
                 'tz'          => $timezone,
               );
 
-    # move to LJ::API
-    my $res = LJ::Protocol::do_request("postevent", \%req, \$err, $flags);
-
-    $flags->{u} = undef;
+    #
+    # Sends request to create new 
+    #
+    my $res = LJ::Protocol::do_request("postevent", 
+                                        \%req, 
+                                        \$err, 
+                                        $flags);
+                                        
     if ($err) {
          my ($code, $text) = split(/:/, $err);
          $$error = LJ::API::Error->make_error( $text, -$code );
          return;
     }
 
-    return LJ::Entry->new($u, jitemid => $res->{'itemid'} );
+    return LJ::Entry->new(  $u, 
+                            jitemid => $res->{'itemid'} );
 }
 
 sub __create_repost {
@@ -159,11 +182,15 @@
     my $error     = $opts->{'error'};
 
     if (!$entry_obj->visible_to($u)) {
-        $$error = LJ::API::Error->make_error( LJ::Lang::ml('repost.access_denied'), -9002);
+        $$error = LJ::API::Error->make_error( LJ::Lang::ml('repost.access_denied'), 
+                                              -9002);
         return;
     }
 
-    my $post_obj = __create_post($u, $timezone, $entry_obj->url, $error);
+    my $post_obj = __create_post($u, 
+                                 $timezone, 
+                                 $entry_obj->url, 
+                                 $error);
     if (!$post_obj) {
         return;
     }
@@ -172,7 +199,9 @@
     $post_obj->convert_to_repost($mark);
     $post_obj->set_prop( 'repost' => 'e' );
 
+    #
     # create record
+    #
     my $repost_jitemid = $post_obj->jitemid;
     
     my $journalid = $entry_obj->journalid;
@@ -215,35 +244,27 @@
     return $reposted;
 }
 
-sub __clear_reposters_list {
-    my ($journalid, $jitemid) = @_;
+sub __clean_reposters_list {
+    my ($u, $jitemid) = @_;
 
-    my $subkey = "$journalid:$jitemid";
-    my $memcached_key_list = "reposters_keys_list:$subkey";
+    # get blocks count
+    my $blocks_count = int(__get_count($u, $jitemid)/REPOST_USERS_LIST_LIMIT) + 1;
+ 
+    # construct memcache keys base
+    my $journalid = $u->userid;
+    my $key_base = "reposters_list_chunk:$journalid:$jitemid";
 
-    my ($keys_list) = LJ::MemCache::get($memcached_key_list) ;
-    if (defined $keys_list) {
-        my @keys = split(/:/, $keys_list);
-        foreach my $key (@keys) {
-            my $memcache_key = "reposters_list_chunk:$subkey:$key";
-            LJ::MemCache::delete($memcache_key);
-        }
+    # clean all blocks
+    for (my $i = 0; $i < $blocks_count; $i++) {
+        LJ::MemCache::delete("$key_base:$i");
     }
-    LJ::MemCache::delete($memcached_key_list);
 }
 
 sub __put_reposters_list {
     my ($journalid, $jitemid, $data, $lastrequest) = @_;
 
-    my $subkey = "$journalid:$jitemid";
+    my $subkey       = "$journalid:$jitemid";
     my $memcache_key = "reposters_list_chunk:$subkey:$lastrequest";
-    my $memcache_keys_list = "reposters_keys_list:$subkey";
-
-    if ($lastrequest) {
-        LJ::MemCache::append($memcache_keys_list,":$lastrequest");
-    } else {
-        LJ::MemCache::set($memcache_keys_list, "$lastrequest", REPOST_KEYS_EXPIRING);
-    }
     
     my $serialized = LJ::JSON->to_json( $data );
     LJ::MemCache::set( $memcache_key, $serialized, REPOST_KEYS_EXPIRING );
@@ -278,16 +299,14 @@
     my $final_limit = REPOST_USERS_LIST_LIMIT + 1;
     my $query_reposters = 'SELECT reposterid ' .
                           'FROM repost2 ' .
-                          'WHERE journalid = ? AND jitemid = ? ';
+                          'WHERE journalid = ? AND jitemid = ? ' .
+                          'ORDER BY repost_time ' .
+                          "LIMIT $lastrequest, $final_limit";
 
-    $query_reposters .=  LJ::is_enabled('repost2_with_time') ? 'ORDER BY repost_time ' :  '';
-    $query_reposters .= "LIMIT $lastrequest, $final_limit";
-
     my $reposters = $dbcr->selectcol_arrayref( $query_reposters,
                                                undef,
                                                $u->userid,
                                                $jitemid,);
-
     return $reposters;
 }
 
@@ -308,26 +327,42 @@
     my $journalid = $entry->journalid;
     my $jitemid   = $entry->jitemid;
 
+    #
+    # $lastrequest should be >= 0
+    #
     if (!$lastrequest || $lastrequest < 0) {
         $lastrequest = 0;
     }
 
+    #
+    # Try to get value from cache
+    #
     my $cached_reposters = __get_reposters_list($journalid, 
                                                 $jitemid, 
                                                 $lastrequest);
     if ($cached_reposters) {
+        $cached_reposters->{'count'}  = __get_count($entry->journal, 
+                                                    $entry->jitemid);
         return $cached_reposters;
     }
+    
 
+    #
+    # If there is no cache then get from db
+    #
     my $repostersids = __get_reposters( $entry->journal,
                                         $jitemid,
                                         $lastrequest );
 
+    #
+    # construct answer structure
+    #
     my $reposters_info = { users => [] };
     my $users = $reposters_info->{'users'};
 
     my $reposters_count = scalar @$repostersids;
     $reposters_info->{'last'}   = $lastrequest + 1;
+
     if ($reposters_count < REPOST_USERS_LIST_LIMIT + 1) {
         $reposters_info->{'nomore'} = 1;
     } else {
@@ -340,15 +375,21 @@
     }  
  
     $reposters_info->{'last'}   = $lastrequest + 1;
-    $reposters_info->{'count'}  = __get_count($entry->journal, 
-                                              $entry->jitemid);
 
+    #
+    # put data structure to cache
+    #
     __put_reposters_list( $journalid,
                           $jitemid,
                           $reposters_info, 
                           $lastrequest );
 
-    
+    #
+    # no need to cache 'count' 
+    #
+    $reposters_info->{'count'}  = __get_count($entry->journal, 
+                                              $entry->jitemid);
+
     return $reposters_info; 
 }
 
@@ -379,15 +420,43 @@
 
 sub delete {
     my ($class, $u, $entry_obj) = @_;
-    my $repost_itemid = __get_repostid( $entry_obj->journal, $entry_obj->jitemid, $u->userid );
+    
+    #
+    # Get entry id to delete
+    #
+    my $repost_itemid = __get_repostid( $entry_obj->journal, 
+                                        $entry_obj->jitemid, 
+                                        $u->userid );
 
-    if ($repost_itemid) {
-        LJ::set_remote($u);
-        my $result = LJ::API::Event->delete({ itemid => $repost_itemid, journalid => $u->userid} ); 
-        if ($result->{'error'}) { 
+    #
+    # If entry exists in db 
+    #
+    if ($repost_itemid) {        
+        LJ::set_remote($u);    
+        
+        #
+        # Try to delete entry
+        #
+        my $result = LJ::API::Event->delete({ itemid => $repost_itemid, 
+                                              journalid => $u->userid   } );
+    
+        #
+        # If entry doesnt't exists then it should be removed from db
+        #
+        my $entry_not_found_code = LJ::API::Error->get_error_code('entry_not_found');        
+        my $error = $result->{'error'};
+        
+        #
+        # Error is deversed from 'entry not found'  
+        #
+        if ($error && $error->{'error_code'} != $entry_not_found_code) { 
             return $result;
         }
-        __delete_repost_record($entry_obj->journal, $entry_obj->jitemid, $u->userid);
+        
+        
+        __delete_repost_record( $entry_obj->journal, 
+                                $entry_obj->jitemid, 
+                                $u->userid);
     
         return  { 'delete' => 'OK' };
     }
@@ -417,7 +486,9 @@
     my $journalid = $entry_obj->journalid;
     my $jitemid   = $entry_obj->jitemid;
 
-    my $repost_itemid = __get_repostid( $entry_obj->journal, $jitemid, $u->userid );
+    my $repost_itemid = __get_repostid( $entry_obj->journal, 
+                                        $jitemid, 
+                                        $u->userid );
 
     my $error;
     if ($repost_itemid) {
@@ -429,13 +500,16 @@
                                              'timezone'   => $timezone,
                                              'error'      => \$error } );
         if ($reposted_obj) {
-            my $count = __get_count($entry_obj->journal, $entry_obj->jitemid);
+            my $count = __get_count($entry_obj->journal, 
+                                    $entry_obj->jitemid);
+
             $result->{'result'} = { 'count' => $count };
         } 
     }
 
     if ($error && !$error->{'error'}) {
-        $result = LJ::API::Error->make_error( LJ::Lang::ml('api.error.unknown_error'), -9000 );
+        $result = LJ::API::Error->make_error( LJ::Lang::ml('api.error.unknown_error'), 
+                                              -9000 );
     } elsif ($error) {
         $result = $error;
     }
@@ -454,7 +528,9 @@
         if ($link) {
             my ($org_journalid, $org_jitemid) = split(/:/, $link);
             return 0 unless int($org_journalid);
-            my $journal = int($org_journalid) ? LJ::want_user($org_journalid) : undef;
+
+            my $journal = int($org_journalid) ? LJ::want_user($org_journalid) : 
+                                                undef;
             
             my $fake_entry = LJ::Entry->new( $journal, jitemid => $org_jitemid);
 

Tags: livejournal, madeon, pm, sbelyaev
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