Committer: afedorov
LJSUP-10900: Implement MessagePack protocol driver to access to Relation Service.U trunk/cgi-bin/LJ/RelationService/MysqlAPI.pm U trunk/cgi-bin/LJ/RelationService.pm U trunk/cgi-bin/LJ/User.pm U trunk/cgi-bin/ljrelation.pl
Modified: trunk/cgi-bin/LJ/RelationService/MysqlAPI.pm =================================================================== --- trunk/cgi-bin/LJ/RelationService/MysqlAPI.pm 2012-03-28 12:33:21 UTC (rev 21574) +++ trunk/cgi-bin/LJ/RelationService/MysqlAPI.pm 2012-03-28 13:23:05 UTC (rev 21575) @@ -251,30 +251,37 @@ sub remove_relation_to { - my $class = shift; - my $u = shift; - my %opts = @_; + my $class = shift; + my $u = shift; + my $friend = shift; + my $type = shift; + + if ( $type eq 'F' ) { + return $class->_remove_relation_to_type_f($u, $friend); + } else { + return $class->_removee_relation_to_type_other($u, $friend, $type); + } +} - my $friendid = int $opts{friendid}; +sub _remove_relation_to_type_f { + my $class = shift; + my $u = shift; + my $friend = shift; my $dbh = LJ::get_db_writer() or return 0; - my $cnt = $dbh->do(" - DELETE - FROM friends WHERE - userid = ? AND - friendid=? - ", undef, $u->userid, $friendid); + my $cnt = $dbh->do("DELETE FROM friends WHERE userid=? AND friendid=?", + undef, $u->userid, $friend->userid); if (!$dbh->err && $cnt > 0) { - LJ::run_hooks('defriended', $u, LJ::load_userid($friendid)); - LJ::User->decrease_friendsof_counter($friendid); + LJ::run_hooks('defriended', $u, $friend); + LJ::User->decrease_friendsof_counter($friend->userid); # delete friend-of memcache keys for anyone who was removed - LJ::MemCache::delete([ $u->userid, "frgmask:" . $u->userid . ":$friendid" ]); - LJ::memcache_kill($friendid, 'friendofs'); - LJ::memcache_kill($friendid, 'friendofs2'); + LJ::MemCache::delete([ $u->userid, "frgmask:" . $u->userid . ":" . $friend->userid ]); + LJ::memcache_kill($friend->userid, 'friendofs'); + LJ::memcache_kill($friend->userid, 'friendofs2'); LJ::memcache_kill($u->userid, 'friends'); LJ::memcache_kill($u->userid, 'friends2'); @@ -283,7 +290,55 @@ return $cnt; } +sub _remove_relation_to_type_other { + my $class = shift; + my $u = shift; + my $friend = shift; + my $type = shift; + + my $typeid = LJ::get_reluser_id($type)+0; + my $userid = ref($u) ? $u->userid : $u; + my $friendid = ref($friend) ? $friend->userid : $friend; + if ($typeid) { + # clustered reluser2 table + return undef unless $u->writer; + + $u->do("DELETE FROM reluser2 WHERE " . ($userid ne '*' ? ("userid=".$userid." AND ") : "") . + ($friendid ne '*' ? ("targetid=".$friendid." AND ") : "") . "type=$typeid"); + + return undef if $u->err; + } else { + # non-clustered global reluser table + my $dbh = LJ::get_db_writer() + or return undef; + + my $qtype = $dbh->quote($type); + $dbh->do("DELETE FROM reluser WHERE " . ($userid ne '*' ? ("userid=".$userid." AND ") : "") . + ($friendid ne '*' ? ("targetid=".$friendid." AND ") : "") . "type=$qtype"); + + return undef if $dbh->err; + } + + # if one of userid or targetid are '*', then we need to note the modtime + # of the reluser edge from the specified id (the one that's not '*') + # so that subsequent gets on rel:userid:targetid:type will know to ignore + # what they got from memcache + my $eff_type = $typeid || $type; + if ($userid eq '*') { + LJ::MemCache::set([$friendid, "relmodt:$friendid:$eff_type"], time()); + } elsif ($friendid eq '*') { + LJ::MemCache::set([$userid, "relmodu:$userid:$eff_type"], time()); + + # if neither userid nor targetid are '*', then just call _set_rel_memcache + # to update the rel:userid:targetid:type memcache key as well as the + # userid and targetid modtime keys + } else { + LJ::_set_rel_memcache($userid, $friendid, $eff_type, 0); + } +} + + ## ## Private methods ## @@ -651,7 +706,7 @@ # database and insert those into memcache my $dbh = LJ::get_db_writer(); - my $limit_sql = $limit ? '' : " LIMIT " . ($LJ::MAX_FRIENDOF_LOAD+1); + my $limit_sql = $limit ? '' : " LIMIT " . ($LJ::MAX_FRIENDOF_LOAD + 1); my $friendofs = $dbh->selectcol_arrayref ("SELECT userid FROM friends WHERE friendid=? $limit_sql", undef, $u->userid) || []; @@ -665,5 +720,51 @@ return @$friendofs; } +sub is_relation_to { + my $class = shift; + my $u = shift; + my $friend = shift; + my $type = shift; + my %opts = @_; + + return undef unless $type && $u && $friend; -1 + my $userid = LJ::want_userid($u); + my $friendid = LJ::want_userid($friend); + + my $typeid = LJ::get_reluser_id($type)+0; + my $eff_type = $typeid || $type; + + my $key = "$userid-$friendid-$eff_type"; + return $LJ::REQ_CACHE_REL{$key} if defined $LJ::REQ_CACHE_REL{$key}; + + # did we get something from memcache? + my $memval = LJ::_get_rel_memcache($userid, $friendid, $eff_type); + return $memval if defined $memval; + + # are we working on reluser or reluser2? + my ($db, $table); + if ($typeid) { + # clustered reluser2 table + $db = LJ::get_cluster_reader($u); + $table = "reluser2"; + } else { + # non-clustered reluser table + $db ||= LJ::get_db_reader(); + $table = "reluser"; + } + + # get data from db, force result to be {0|1} + my $dbval = $db->selectrow_array("SELECT COUNT(*) FROM $table ". + "WHERE userid=? AND friendid=? AND type=? ", + undef, $userid, $friendid, $eff_type) + ? 1 : 0; + + # set in memcache + LJ::_set_rel_memcache($userid, $friendid, $eff_type, $dbval); + + # return and set request cache + return $LJ::REQ_CACHE_REL{$key} = $dbval; +} + +1; Modified: trunk/cgi-bin/LJ/RelationService.pm =================================================================== --- trunk/cgi-bin/LJ/RelationService.pm 2012-03-28 12:33:21 UTC (rev 21574) +++ trunk/cgi-bin/LJ/RelationService.pm 2012-03-28 13:23:05 UTC (rev 21575) @@ -60,7 +60,7 @@ $opts{offset} ||= 0; $opts{limit} ||= 50000; - if ($class->_load_alt_api('read', $type)){ + if ($class->_load_alt_api('read', $type)) { my $alt = $class->alt_api($u); if ($alt) { $alt->find_relation_destinations($u, $type, %opts); @@ -83,7 +83,7 @@ $opts{offset} ||= 0; $opts{limit} ||= 50000; - if ($class->_load_alt_api('read', $type)){ + if ($class->_load_alt_api('read', $type)) { my $alt = $class->alt_api($u); if ($alt) { $alt->find_relation_sources($u, $type, %opts); @@ -105,7 +105,7 @@ $opts{offset} ||= 0; $opts{limit} ||= 50000; - if ($class->_load_alt_api('read', $type)){ + if ($class->_load_alt_api('read', $type)) { my $alt = $class->alt_api($u); if ($alt) { $alt->load_relation_destinations($u, $type, %opts); @@ -128,7 +128,7 @@ return undef unless $type and $u and $friend; - if ($class->_load_alt_api('update')){ + if ($class->_load_alt_api('update')) { my $alt = $class->alt_api($u); if ($alt){ $alt->create_relation_to($u, $friend, $type, %opts); @@ -141,18 +141,48 @@ sub remove_relation_to { - my $class = shift; - my $u = shift; + my $class = shift; + my $u = shift; + my $friend = shift; + my $type = shift; + $u = LJ::want_user($u) unless $u eq '*'; + $friend = LJ::want_user($friend) unless $u eq '*'; + + return undef unless $type and $u and $friend; + return undef if $u eq '*' and $friend eq '*'; + + if ($class->_load_alt_api('update')) { + my $alt = $class->alt_api($u, $friend, $type); + if ($alt){ + $alt->remove_relation_to($u, $friend, $type); + } + } + my $interface = $class->relation_api($u); + return $interface->remove_relation_to($u, $friend, $type); +} + +sub is_relation_to { + my $class = shift; + my $u = shift; + my $friend = shift; + my $type = shift; + my %opts = @_; + $u = LJ::want_user($u); - if ($class->_load_alt_api('update')){ + $friend = LJ::want_user($friend); + + return undef unless $u && $friend && $type; + + if ($class->_load_alt_api('read', $type)) { my $alt = $class->alt_api($u); - if ($alt){ - $alt->create_relation_to($u, @_); + if ($alt) { + $alt->is_relation_to($u, $friend, $type, %opts); } } + my $interface = $class->relation_api($u); - return $interface->remove_relation_to($u, @_); + return $interface->is_relation_to($u, $friend, $type, %opts); } 1; Modified: trunk/cgi-bin/LJ/User.pm =================================================================== --- trunk/cgi-bin/LJ/User.pm 2012-03-28 12:33:21 UTC (rev 21574) +++ trunk/cgi-bin/LJ/User.pm 2012-03-28 13:23:05 UTC (rev 21575) @@ -9093,25 +9093,16 @@ my $dbh = LJ::get_db_writer() or return 0; - foreach my $del_id (@del_ids) { - my $cnt = $dbh->do("DELETE FROM friends WHERE userid=$userid AND friendid=$del_id"); - - if (!$dbh->err && $cnt > 0) { - LJ::run_hooks('defriended', $u, LJ::load_userid($del_id)); - LJ::User->decrease_friendsof_counter($del_id); - } - } - my $sclient = LJ::theschwartz(); # part of the criteria for whether to fire defriended event my $notify = !$LJ::DISABLED{esn} && !$opts->{nonotify} && $u->is_visible && $u->is_person; + foreach my $del_id (@del_ids) { + LJ::RelationService->remove_relation_to( $u, $del_id, 'F' ); + } + # delete friend-of memcache keys for anyone who was removed foreach my $fid (@del_ids) { - LJ::MemCache::delete([ $userid, "frgmask:$userid:$fid" ]); - LJ::memcache_kill($fid, 'friendofs'); - LJ::memcache_kill($fid, 'friendofs2'); - my $friendee = LJ::load_userid($fid); if ($sclient) { my @jobs; @@ -9131,10 +9122,6 @@ } } - LJ::memcache_kill($userid, 'friends'); - LJ::memcache_kill($userid, 'friends2'); - LJ::mark_dirty($userid, "friends"); - return 1; } *delete_friend_edge = \&LJ::remove_friend; Modified: trunk/cgi-bin/ljrelation.pl =================================================================== --- trunk/cgi-bin/ljrelation.pl 2012-03-28 12:33:21 UTC (rev 21574) +++ trunk/cgi-bin/ljrelation.pl 2012-03-28 13:23:05 UTC (rev 21575) @@ -281,47 +281,12 @@ # </LJFUNC> sub check_rel { - my $db = isdb($_[0]) ? shift : undef; + my $class = shift; my ($userid, $targetid, $type) = @_; return undef unless $type && $userid && $targetid; - my $u = LJ::want_user($userid); - $userid = LJ::want_userid($userid); - $targetid = LJ::want_userid($targetid); - - my $typeid = LJ::get_reluser_id($type)+0; - my $eff_type = $typeid || $type; - - my $key = "$userid-$targetid-$eff_type"; - return $LJ::REQ_CACHE_REL{$key} if defined $LJ::REQ_CACHE_REL{$key}; - - # did we get something from memcache? - my $memval = LJ::_get_rel_memcache($userid, $targetid, $eff_type); - return $memval if defined $memval; - - # are we working on reluser or reluser2? - my $table; - if ($typeid) { - # clustered reluser2 table - $db = LJ::get_cluster_reader($u); - $table = "reluser2"; - } else { - # non-clustered reluser table - $db ||= LJ::get_db_reader(); - $table = "reluser"; - } - - # get data from db, force result to be {0|1} - my $dbval = $db->selectrow_array("SELECT COUNT(*) FROM $table ". - "WHERE userid=? AND targetid=? AND type=? ", - undef, $userid, $targetid, $eff_type) - ? 1 : 0; - - # set in memcache - LJ::_set_rel_memcache($userid, $targetid, $eff_type, $dbval); - - # return and set request cache - return $LJ::REQ_CACHE_REL{$key} = $dbval; + my $result = LJ::RelationService->is_relation_to($userid, $targetid, $type); + return $result; } # <LJFUNC> @@ -521,45 +486,11 @@ $targetid = LJ::want_userid($targetid) unless $targetid eq '*'; return undef unless $type && $userid && $targetid; - my $typeid = LJ::get_reluser_id($type)+0; + my $result = LJ::RelationService->remove_relation_to($userid, $targetid, $type); + return undef unless $result; - if ($typeid) { - # clustered reluser2 table - return undef unless $u->writer; - $u->do("DELETE FROM reluser2 WHERE " . ($userid ne '*' ? "userid=$userid AND " : "") . - ($targetid ne '*' ? "targetid=$targetid AND " : "") . "type=$typeid"); - return undef if $u->err; - } else { - # non-clustered global reluser table - my $dbh = LJ::get_db_writer() - or return undef; - - my $qtype = $dbh->quote($type); - $dbh->do("DELETE FROM reluser WHERE " . ($userid ne '*' ? "userid=$userid AND " : "") . - ($targetid ne '*' ? "targetid=$targetid AND " : "") . "type=$qtype"); - - return undef if $dbh->err; - } - - # if one of userid or targetid are '*', then we need to note the modtime - # of the reluser edge from the specified id (the one that's not '*') - # so that subsequent gets on rel:userid:targetid:type will know to ignore - # what they got from memcache - my $eff_type = $typeid || $type; - if ($userid eq '*') { - LJ::MemCache::set([$targetid, "relmodt:$targetid:$eff_type"], time()); - } elsif ($targetid eq '*') { - LJ::MemCache::set([$userid, "relmodu:$userid:$eff_type"], time()); - - # if neither userid nor targetid are '*', then just call _set_rel_memcache - # to update the rel:userid:targetid:type memcache key as well as the - # userid and targetid modtime keys - } else { - LJ::_set_rel_memcache($userid, $targetid, $eff_type, 0); - } - return 1; }