vadvs (vadvs) wrote in changelog,
vadvs
vadvs
changelog

[livejournal] r20327: LJSUP-10147: Implement abstract interace...

Committer: vsukhanov
LJSUP-10147: Implement abstract interace for access to friends relations
U   trunk/bin/worker/load-friends-gm
A   trunk/cgi-bin/LJ/RelationService/
A   trunk/cgi-bin/LJ/RelationService/MysqlAPI.pm
A   trunk/cgi-bin/LJ/RelationService.pm
U   trunk/cgi-bin/LJ/User.pm
Modified: trunk/bin/worker/load-friends-gm
===================================================================
--- trunk/bin/worker/load-friends-gm	2011-10-14 13:17:37 UTC (rev 20326)
+++ trunk/bin/worker/load-friends-gm	2011-10-14 13:24:25 UTC (rev 20327)
@@ -9,6 +9,7 @@
 use strict;
 use lib "$ENV{LJHOME}/cgi-bin";
 require 'ljlib.pl';
+use LJ::RelationService;
 
 use LJ::NewWorker::Gearman;
 use Storable;
@@ -26,10 +27,11 @@
     my $uid = $args->{userid};
     my $mask = $args->{mask};
 
-    my $friends = LJ::_get_friends_db($uid, $mask);
+    my $u       = LJ::load_userid($uid);
+    my @friends = LJ::RelationService->load_relation_destinations($u, mask => $mask, nogearman => 1);
 
     # nfreeze friends hashref and return
-    return Storable::nfreeze($friends);
+    return Storable::nfreeze(\@friends);
 }
 
 sub load_friend_friendof_uids {
@@ -39,9 +41,8 @@
     my $uid = $args->{uid};
     my $opts = $args->{opts};
 
-    my $u = LJ::load_userid($uid);
+    my $u    = LJ::load_userid($uid);
+    my @uids = LJ::RelationService->find_relation_destinations($u, %$opts, nogearman => 1);
 
-    my @uids = $u->_friend_friendof_uids_do(%$opts);
-
     return Storable::nfreeze(\@uids);
 }

Added: trunk/cgi-bin/LJ/RelationService/MysqlAPI.pm
===================================================================
--- trunk/cgi-bin/LJ/RelationService/MysqlAPI.pm	                        (rev 0)
+++ trunk/cgi-bin/LJ/RelationService/MysqlAPI.pm	2011-10-14 13:24:25 UTC (rev 20327)
@@ -0,0 +1,457 @@
+package LJ::RelationService::MysqlAPI;
+use strict;
+
+
+## friends
+sub find_relation_destinations {
+    my $class = shift;
+    my $u     = shift;
+    my %opts  = @_;
+    my $limit     = $opts{limit} || 50000;
+    my $nogearman = $opts{nogearman} || 0;
+
+    my $uids = $class->_friend_friendof_uids($u, 
+                        %opts,
+                        limit     => $limit, 
+                        nogearman => $nogearman, 
+                        mode      => "friends",
+                        );
+    return @$uids;
+}
+
+## friendofs
+sub find_relation_sources {
+    my $class = shift;
+    my $u     = shift;
+    my %opts  = @_;
+    my $limit     = $opts{limit} || 50000;
+    my $nogearman = $opts{nogearman} || 0;
+
+    my $uids = $class->_friend_friendof_uids($u, 
+                        %opts,
+                        limit     => $limit, 
+                        nogearman => $nogearman,
+                        mode      => "friendofs",
+                        );
+    return @$uids;
+}
+
+## friends rows
+sub load_relation_destinations {
+    my $class = shift;
+    my $u     = shift;
+    my %opts  = @_;
+    my $limit     = $opts{limit} || 50000;
+    my $nogearman = $opts{nogearman} || 0;
+
+    my $friends = $class->_get_friends($u, 
+                        %opts, 
+                        limit     => $limit, 
+                        nogearman => $nogearman,
+                        );
+    return undef unless $friends;
+    return @$friends;
+}
+
+## friendofs rows
+sub load_relation_sources {
+    my $class = shift;
+    my $u     = shift;
+    my %opts  = @_;
+    my $limit     = $opts{limit} || 50000;
+    my $nogearman = $opts{nogearman} || 0;
+
+    my $friendofs = $class->_get_friendofs($u, 
+                        %opts, 
+                        limit     => $limit, 
+                        nogearman => $nogearman,
+                        );
+    return undef unless $friendofs;
+    return @$friendofs;
+
+}
+
+
+##
+## Private methods
+##
+
+# helper method since the logic for both friends and friendofs is so similar
+sub _friend_friendof_uids {
+    my $class = shift;
+    my $u     = shift;
+    my %args  = @_;
+
+    my $mode      = $args{mode};
+    my $limit     = $args{limit};
+    my $nogearman = $args{nogearma} || 0;
+
+    ## check cache first
+    my $res = $class->_load_friend_friendof_uids_from_memcache($u, $mode, $limit);
+    return $res if defined $res;
+
+    # call normally if no gearman/not wanted
+    my $gc = '';
+    return $class->_friend_friendof_uids_do($u, skip_memcached => 1, %args) # we've already checked memcached above
+        if $nogearman or 
+           not (LJ::conf_test($LJ::LOADFRIENDS_USING_GEARMAN, $u->userid) and 
+                $gc = LJ::gearman_client());
+
+    # invoke gearman
+    my @uids = ();
+    my $args = Storable::nfreeze({uid => $u->id, opts => \%args});
+    my $task = Gearman::Task->new("load_friend_friendof_uids", \$args,
+                                  {
+                                      uniq => join("-", $mode, $u->id, $limit),
+                                      on_complete => sub {
+                                          my $res = shift;
+                                          return unless $res;
+                                          my $uidsref = Storable::thaw($$res);
+                                          @uids = @{$uidsref || []};
+                                      }
+                                  });
+    my $ts = $gc->new_task_set();
+    $ts->add_task($task);
+    $ts->wait(timeout => 30); # 30 sec timeout
+
+    return \@uids;
+
+}
+
+
+# actually get friend/friendof uids, should not be called directly
+sub _friend_friendof_uids_do {
+    my $class = shift;
+    my $u     = shift;
+    my %args  = @_;
+
+    ## ATTENTION:
+    ##  'nolimit' option should not be used to generate
+    ##  regular page. 
+    ##  Use it with care only for admin pages only.
+
+    my $limit   = $args{limit} || 50000;
+    my $nolimit = $args{nolimit} ? 1 : 0; ## use it with care
+    my $mode    = $args{mode};
+    my $skip_memcached = $args{skip_memcached};
+
+    $skip_memcached = 1 if $nolimit;
+
+    ## cache
+    unless ($skip_memcached){
+        my $res = $class->_load_friend_friendof_uids_from_memcache($u, $mode, $limit);
+        return $res if $res;
+    }
+
+    ## db
+    ## disable $limit if $nolimit requires it.
+    my $uids = $class->_load_friend_friendof_uids_from_db($u, $mode, $limit * (!$nolimit));
+
+    if (not $nolimit and $uids and @$uids){
+        ## do not cache if $nolimit option is in use,
+        ## because with disabled limit we might put in the cache
+        ## much more data than usually required.
+
+        # if the list of uids is greater than 950k
+        # -- slow but this definitely works
+        my $pack = pack("N*", $limit);
+        foreach (@$uids) {
+            last if length $pack > 1024*950;
+            $pack .= pack("N*", $_);
+        }
+
+        ## memcached
+        my $memkey = $class->_friend_friendof_uids_memkey($u, $mode);
+        LJ::MemCache::add($memkey, $pack, 3600);
+    }
+
+    return $uids;
+}
+
+sub _friend_friendof_uids_memkey {
+    my ($class, $u, $mode) = @_;
+    my $memkey;
+
+    if ($mode eq "friends") {
+        $memkey = [$u->id, "friends2:" . $u->id];
+    } elsif ($mode eq "friendofs") {
+        $memkey = [$u->id, "friendofs2:" . $u->id];
+    } else {
+        die "mode must either be 'friends' or 'friendofs'";
+    }
+
+    return $memkey;
+}
+
+sub _load_friend_friendof_uids_from_memcache {
+    my ($class, $u, $mode, $limit) = @_;
+
+    my $memkey = $class->_friend_friendof_uids_memkey($u, $mode);
+
+    if (my $pack = LJ::MemCache::get($memkey)) {
+        my ($slimit, @uids) = unpack("N*", $pack);
+        # value in memcache is good if stored limit (from last time)
+        # is >= the limit currently being requested.  we just may
+        # have to truncate it to match the requested limit
+
+        if ($slimit >= $limit) {
+            @uids = @uids[0..$limit-1] if @uids > $limit;
+            return \@uids;
+        }
+
+        # value in memcache is also good if number of items is less
+        # than the stored limit... because then we know it's the full
+        # set that got stored, not a truncated version.
+        return \@uids if @uids < $slimit;
+    }
+
+    return undef;
+}
+
+## Attention: if 'limit' arg is omited, this method loads all userid from friends table.
+sub _load_friend_friendof_uids_from_db {
+    my $class = shift;
+    my $u     = shift;
+    my $mode  = shift;
+    my $limit = shift;
+
+    $limit = " LIMIT $limit" if $limit;
+
+    my $sql = '';
+    if ($mode eq 'friends'){
+        $sql = "SELECT friendid FROM friends WHERE userid=? $limit";
+    } elsif ($mode eq 'friendofs'){
+        $sql = "SELECT userid FROM friends WHERE friendid=? $limit";
+    } else {
+        die "mode must either be 'friends' or 'friendofs'";
+    }
+
+    my $dbh  = LJ::get_db_reader();
+    my $uids = $dbh->selectcol_arrayref($sql, undef, $u->id);
+    return $uids;
+}
+
+
+
+##
+## loads rows from friends table
+##
+sub _get_friends {
+    my $class = shift;
+    my $u     = shift;
+    my %args  = @_;
+
+    my $mask          = $args{mask};
+    my $memcache_only = $args{memcache_only};
+    my $force_db      = $args{force_db};
+    my $nogearman     = $args{nogearma} || 0;
+
+    return undef unless $u->userid;
+    return undef if $LJ::FORCE_EMPTY_FRIENDS{$u->userid};
+
+    unless ($force_db) {
+        my $memc = $class->_get_friends_memc($u->userid, $mask);
+        return $memc if $memc;
+    }
+    return {} if $memcache_only; # no friends
+
+    # nothing from memcache, select all rows from the
+    # database and insert those into memcache
+    # then return rows that matched the given groupmask
+
+    # no gearman/gearman not wanted
+    my $gc = undef;
+    return $class->_get_friends_db($u->userid, $mask)
+        if $nogearman or
+            not (LJ::conf_test($LJ::LOADFRIENDS_USING_GEARMAN, $u->userid) and $gc = LJ::gearman_client());
+
+    # invoke the gearman
+    my $friends;
+    my $arg  = Storable::nfreeze({ userid => $u->userid, mask => $mask });
+    my $task = Gearman::Task->new("load_friends", \$arg,
+                                  {
+                                      uniq => $u->userid,
+                                      on_complete => sub {
+                                          my $res = shift;
+                                          return unless $res;
+                                          $friends = Storable::thaw($$res);
+                                      }
+                                  });
+
+    my $ts = $gc->new_task_set();
+    $ts->add_task($task);
+    $ts->wait(timeout => 30); # 30 sec timeout
+
+    return $friends;
+}
+
+sub _get_friends_memc {
+    my $class  = shift;
+    my $userid = shift
+        or Carp::croak("no userid to _get_friends_db");
+    my $mask = shift;
+
+    # memcache data version
+    my $ver = 1;
+
+    my $packfmt = "NH6H6NC";
+    my $packlen = 15;  # bytes
+
+    my @cols = qw(friendid fgcolor bgcolor groupmask showbydefault);
+
+    # first, check memcache
+    my $memkey = [$userid, "friends:$userid"];
+
+    my $memfriends = LJ::MemCache::get($memkey);
+    return undef unless $memfriends;
+
+    my %friends; # rows to be returned
+
+    # first byte of object is data version
+    # only version 1 is meaningful right now
+    my $memver = substr($memfriends, 0, 1, '');
+    return undef unless $memver == $ver;
+
+    # get each $packlen-byte row
+    while (length($memfriends) >= $packlen) {
+        my @row = unpack($packfmt, substr($memfriends, 0, $packlen, ''));
+
+        # don't add into %friends hash if groupmask doesn't match
+        next if $mask && ! ($row[3]+0 & $mask+0);
+
+        # add "#" to beginning of colors
+        $row[$_] = "\#$row[$_]" foreach 1..2;
+
+        # turn unpacked row into hashref
+        my $fid = $row[0];
+        my $idx = 1;
+        foreach my $col (@cols[1..$#cols]) {
+            $friends{$fid}->{$col} = $row[$idx];
+            $idx++;
+        }
+    }
+
+    # got from memcache, return
+    return \%friends;
+}
+
+sub _get_friends_db {
+    my $class  = shift;
+
+    my $userid = shift
+        or Carp::croak("no userid to _get_friends_db");
+    my $mask = shift;
+
+    my $dbh = LJ::get_db_writer();
+
+    my $lockname = "get_friends:$userid";
+    my $release_lock = sub {
+        LJ::release_lock($dbh, "global", $lockname);
+    };
+
+    # get a lock
+    my $lock = LJ::get_lock($dbh, "global", $lockname);
+    return {} unless $lock;
+
+    # in lock, try memcache
+    my $memc = _get_friends_memc($userid, $mask);
+    if ($memc) {
+        $release_lock->();
+        return $memc;
+    }
+
+    # inside lock, but still not populated, query db
+
+    # memcache data info
+    my $ver = 1;
+    my $memkey = [$userid, "friends:$userid"];
+    my $packfmt = "NH6H6NC";
+    my $packlen = 15;  # bytes
+
+    # columns we're selecting
+    my @cols = qw(friendid fgcolor bgcolor groupmask showbydefault);
+
+    my $mempack = $ver; # full packed string to insert into memcache, byte 1 is dversion
+    my %friends = ();   # friends object to be returned, all groupmasks match
+
+    my $sth = $dbh->prepare("SELECT friendid, fgcolor, bgcolor, groupmask, showbydefault " .
+                            "FROM friends WHERE userid=?");
+    $sth->execute($userid);
+    die $dbh->errstr if $dbh->err;
+    while (my @row = $sth->fetchrow_array) {
+
+        # convert color columns to hex
+        $row[$_] = sprintf("%06x", $row[$_]) foreach 1..2;
+
+        my $newpack = pack($packfmt, @row);
+        last if length($mempack) + length($newpack) > 950*1024;
+
+        $mempack .= $newpack;
+
+        # unless groupmask matches, skip adding to %friends
+        next if $mask && ! ($row[3]+0 & $mask+0);
+
+        # add "#" to beginning of colors
+        $row[$_] = "\#$row[$_]" foreach 1..2;
+
+        my $fid = $row[0];
+        my $idx = 1;
+        foreach my $col (@cols[1..$#cols]) {
+            $friends{$fid}->{$col} = $row[$idx];
+            $idx++;
+        }
+    }
+
+    LJ::MemCache::add($memkey, $mempack);
+
+    # finished with lock, release it
+    $release_lock->();
+
+    return \%friends;
+}
+
+
+## friendofs
+sub _get_friendofs {
+    my $class = shift;
+    my $u     = shift;
+    my %args  = @_;
+    my $skip_memcached = $args{skip_memcached};
+    my $limit          = $args{limit};
+    my $nolimit        = $args{nolimit};
+
+    ## ATTENTION:
+    ##  'nolimit' option should not be used to generate
+    ##  regular page. 
+    ##  Use it with care only for admin pages only.
+
+    $limit = 0 if $nolimit;
+
+    # first, check memcache
+    my $memkey = [$u->userid, "friendofs:" . $u->userid];
+
+    unless ($skip_memcached) {
+        my $memfriendofs = LJ::MemCache::get($memkey);
+        return @$memfriendofs if $memfriendofs;
+    }
+
+    # nothing from memcache, select all rows from the
+    # database and insert those into memcache
+
+    my $dbh   = LJ::get_db_writer();
+    my $limit = $limit ? '' : " LIMIT " . ($LJ::MAX_FRIENDOF_LOAD+1);
+    my $friendofs = $dbh->selectcol_arrayref
+        ("SELECT userid FROM friends WHERE friendid=? $limit",
+         undef, $u->userid) || [];
+    die $dbh->errstr if $dbh->err;
+
+    ## do not cache if $nolimit option is in use,
+    ## because with disabled limit we might put in the cache
+    ## much more data than usually required.
+    LJ::MemCache::add($memkey, $friendofs) unless $skip_memcached;
+
+    return @$friendofs;
+}
+
+
+1

Added: trunk/cgi-bin/LJ/RelationService.pm
===================================================================
--- trunk/cgi-bin/LJ/RelationService.pm	                        (rev 0)
+++ trunk/cgi-bin/LJ/RelationService.pm	2011-10-14 13:24:25 UTC (rev 20327)
@@ -0,0 +1,43 @@
+package LJ::RelationService;
+use strict;
+
+use LJ::RelationService::MysqlAPI;
+
+
+sub relation_api {
+    my $class = shift;
+    my $u     = shift;
+    return "LJ::RelationService::MysqlAPI";
+}
+
+
+## findRelationDestinations
+sub find_relation_destinations {
+    my $class = shift;
+    my $u     = shift;
+
+    my $interface = $class->relation_api($u);
+    return $interface->find_relation_destinations($u, @_);
+   
+}
+
+## findRelationSources
+sub find_relation_sources {
+    my $class = shift;
+    my $u     = shift;
+
+    my $interface = $class->relation_api($u);
+    return $interface->find_relation_sources($u, @_);
+   
+}
+
+sub load_relation_destinations {
+    my $class = shift;
+    my $u     = shift;
+
+    my $interface = $class->relation_api($u);
+    return $interface->load_relation_destinations($u, @_);
+   
+}
+
+1

Modified: trunk/cgi-bin/LJ/User.pm
===================================================================
--- trunk/cgi-bin/LJ/User.pm	2011-10-14 13:17:37 UTC (rev 20326)
+++ trunk/cgi-bin/LJ/User.pm	2011-10-14 13:24:25 UTC (rev 20327)
@@ -28,6 +28,7 @@
 use LJ::TimeUtil;
 use LJ::User::PropStorage;
 use LJ::FileStore;
+use LJ::RelationService;
 
 use Class::Autouse qw(
                       URI
@@ -4564,7 +4565,7 @@
     my $limit = int(delete $args{limit}) || 50000;
     Carp::croak("unknown option") if %args;
 
-    return $u->_friend_friendof_uids(limit => $limit, mode => "friendofs");
+    return LJ::RelationService->find_relation_sources($u, limit => $limit);
 }
 
 # returns array of friend uids.  by default, limited at 50,000 items.
@@ -4573,10 +4574,9 @@
     my $limit = int(delete $args{limit}) || 50000;
     Carp::croak("unknown option") if %args;
 
-    return $u->_friend_friendof_uids(limit => $limit, mode => "friends");
+    return LJ::RelationService->find_relation_destinations($u, limit => $limit);
 }
 
-
 # helper method since the logic for both friends and friendofs is so similar
 sub _friend_friendof_uids {
     my $u = shift;
@@ -4615,6 +4615,7 @@
 # actually get friend/friendof uids, should not be called directly
 sub _friend_friendof_uids_do {
     my ($u, %args) = @_;
+## method is also called from load-friends-gm worker.
 
     my $limit = int(delete $args{limit}) || 50000;
     my $mode  = delete $args{mode};
@@ -8653,163 +8654,16 @@
     return undef unless $userid;
     return undef if $LJ::FORCE_EMPTY_FRIENDS{$userid};
 
-    unless ($force) {
-        my $memc = _get_friends_memc($userid, $mask);
-        return $memc if $memc;
-    }
-    return {} if $memcache_only; # no friends
+    my $u = LJ::load_userid($userid);
 
-    # nothing from memcache, select all rows from the
-    # database and insert those into memcache
-    # then return rows that matched the given groupmask
-
-    # no gearman/gearman not wanted
-    my $gc = LJ::gearman_client();
-    return _get_friends_db($userid, $mask)
-        unless $gc && LJ::conf_test($LJ::LOADFRIENDS_USING_GEARMAN, $userid);
-
-    # invoke the gearman
-    my $friends;
-    my $arg = Storable::nfreeze({ userid => $userid, mask => $mask });
-    my $task = Gearman::Task->new("load_friends", \$arg,
-                                  {
-                                      uniq => "$userid",
-                                      on_complete => sub {
-                                          my $res = shift;
-                                          return unless $res;
-                                          $friends = Storable::thaw($$res);
-                                      }
-                                  });
-
-    my $ts = $gc->new_task_set();
-    $ts->add_task($task);
-    $ts->wait(timeout => 30); # 30 sec timeout
-
-    return $friends;
+    return LJ::RelationService->load_relation_destinations(
+            $u, uuid          => $uuid,
+                mask          => $mask,
+                memcache_only => $memcache_only,
+                force_db      => $force,
+                );
 }
 
-sub _get_friends_memc {
-    my $userid = shift
-        or Carp::croak("no userid to _get_friends_db");
-    my $mask = shift;
-
-    # memcache data version
-    my $ver = 1;
-
-    my $packfmt = "NH6H6NC";
-    my $packlen = 15;  # bytes
-
-    my @cols = qw(friendid fgcolor bgcolor groupmask showbydefault);
-
-    # first, check memcache
-    my $memkey = [$userid, "friends:$userid"];
-
-    my $memfriends = LJ::MemCache::get($memkey);
-    return undef unless $memfriends;
-
-    my %friends; # rows to be returned
-
-    # first byte of object is data version
-    # only version 1 is meaningful right now
-    my $memver = substr($memfriends, 0, 1, '');
-    return undef unless $memver == $ver;
-
-    # get each $packlen-byte row
-    while (length($memfriends) >= $packlen) {
-        my @row = unpack($packfmt, substr($memfriends, 0, $packlen, ''));
-
-        # don't add into %friends hash if groupmask doesn't match
-        next if $mask && ! ($row[3]+0 & $mask+0);
-
-        # add "#" to beginning of colors
-        $row[$_] = "\#$row[$_]" foreach 1..2;
-
-        # turn unpacked row into hashref
-        my $fid = $row[0];
-        my $idx = 1;
-        foreach my $col (@cols[1..$#cols]) {
-            $friends{$fid}->{$col} = $row[$idx];
-            $idx++;
-        }
-    }
-
-    # got from memcache, return
-    return \%friends;
-}
-
-sub _get_friends_db {
-    my $userid = shift
-        or Carp::croak("no userid to _get_friends_db");
-    my $mask = shift;
-
-    my $dbh = LJ::get_db_writer();
-
-    my $lockname = "get_friends:$userid";
-    my $release_lock = sub {
-        LJ::release_lock($dbh, "global", $lockname);
-    };
-
-    # get a lock
-    my $lock = LJ::get_lock($dbh, "global", $lockname);
-    return {} unless $lock;
-
-    # in lock, try memcache
-    my $memc = _get_friends_memc($userid, $mask);
-    if ($memc) {
-        $release_lock->();
-        return $memc;
-    }
-
-    # inside lock, but still not populated, query db
-
-    # memcache data info
-    my $ver = 1;
-    my $memkey = [$userid, "friends:$userid"];
-    my $packfmt = "NH6H6NC";
-    my $packlen = 15;  # bytes
-
-    # columns we're selecting
-    my @cols = qw(friendid fgcolor bgcolor groupmask showbydefault);
-
-    my $mempack = $ver; # full packed string to insert into memcache, byte 1 is dversion
-    my %friends;        # friends object to be returned, all groupmasks match
-
-    my $sth = $dbh->prepare("SELECT friendid, fgcolor, bgcolor, groupmask, showbydefault " .
-                            "FROM friends WHERE userid=?");
-    $sth->execute($userid);
-    die $dbh->errstr if $dbh->err;
-    while (my @row = $sth->fetchrow_array) {
-
-        # convert color columns to hex
-        $row[$_] = sprintf("%06x", $row[$_]) foreach 1..2;
-
-        my $newpack = pack($packfmt, @row);
-        last if length($mempack) + length($newpack) > 950*1024;
-
-        $mempack .= $newpack;
-
-        # unless groupmask matches, skip adding to %friends
-        next if $mask && ! ($row[3]+0 & $mask+0);
-
-        # add "#" to beginning of colors
-        $row[$_] = "\#$row[$_]" foreach 1..2;
-
-        my $fid = $row[0];
-        my $idx = 1;
-        foreach my $col (@cols[1..$#cols]) {
-            $friends{$fid}->{$col} = $row[$idx];
-            $idx++;
-        }
-    }
-
-    LJ::MemCache::add($memkey, $mempack);
-
-    # finished with lock, release it
-    $release_lock->();
-
-    return \%friends;
-}
-
 # <LJFUNC>
 # name: LJ::get_friendofs
 # des: Returns userids of friendofs for a given user.
@@ -8823,27 +8677,11 @@
     my $userid = LJ::want_userid($uuid);
     return undef unless $userid;
 
-    # first, check memcache
-    my $memkey = [$userid, "friendofs:$userid"];
-
-    unless ($opts->{force}) {
-        my $memfriendofs = LJ::MemCache::get($memkey);
-        return @$memfriendofs if $memfriendofs;
-    }
-
-    # nothing from memcache, select all rows from the
-    # database and insert those into memcache
-
-    my $dbh = LJ::get_db_writer();
-    my $limit = $opts->{force} ? '' : " LIMIT " . ($LJ::MAX_FRIENDOF_LOAD+1);
-    my $friendofs = $dbh->selectcol_arrayref
-        ("SELECT userid FROM friends WHERE friendid=?$limit",
-         undef, $userid) || [];
-    die $dbh->errstr if $dbh->err;
-
-    LJ::MemCache::add($memkey, $friendofs);
-
-    return @$friendofs;
+    my $u = LJ::load_userid($userid);
+    return LJ::RelationService->find_relation_sources($u, 
+            nolimit        => $opts->{force} || 0,
+            skip_memcached => $opts->{force},
+            );
 }
 
 # <LJFUNC>

Tags: livejournal, pm, vadvs, vsukhanov
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