[dw-free] [community]/read isn't up
[commit: http://hg.dwscoalition.org/dw-free/rev/035ff3532833]
http://bugs.dwscoalition.org/show_bug.cgi?id=387
* Fix but in ordering for delete_trust_group that would never clear memcache
trustmask since it nuked user memberships too early.
* Add watch_list( community_okay => 1 ) flag which can be passed to get the
watch_list for a community. This flag should only be passed by the reading
page logic - we don't want to accidentally invoke loading community members
as being on the watch_list.
Patch by
mark.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=387
* Fix but in ordering for delete_trust_group that would never clear memcache
trustmask since it nuked user memberships too early.
* Add watch_list( community_okay => 1 ) flag which can be passed to get the
watch_list for a community. This flag should only be passed by the reading
page logic - we don't want to accidentally invoke loading community members
as being on the watch_list.
Patch by
![[staff profile]](https://www.dreamwidth.org/img/silk/identity/user_staff.png)
Files modified:
- bin/test/test-wtf
- cgi-bin/DW/Logic/LogItems.pm
- cgi-bin/DW/User/Edges/WatchTrust.pm
- cgi-bin/DW/User/Edges/WatchTrust/Loader.pm
-------------------------------------------------------------------------------- diff -r dfd18646e8e7 -r 035ff3532833 bin/test/test-wtf --- a/bin/test/test-wtf Sat Mar 07 06:07:58 2009 +0000 +++ b/bin/test/test-wtf Sat Mar 07 07:10:16 2009 +0000 @@ -11,22 +11,27 @@ use Data::Dumper; # much time passes ... my $u1 = LJ::load_user( 'tester0394' ) or die 'no tester0394'; my $u2 = LJ::load_user( 'tester0395' ) or die 'no tester0395'; +my $uc = LJ::load_user( 'testcomm' ) or die 'no testcomm'; +$uc->is_community or die 'testcomm not a community :('; my @tests; print "Beginning tests...\n"; print " u1 = " . $u1->user . '(' . $u1->id . ")\n"; -print " u2 = " . $u2->user . '(' . $u2->id . ")\n\n"; +print " u2 = " . $u2->user . '(' . $u2->id . ")\n"; +print " uc = " . $uc->user . '(' . $uc->id . ")\n\n"; my $dbh = LJ::get_db_writer(); # reset, delete, etc sub rst { $dbh->do( 'DELETE FROM wt_edges WHERE from_userid = ? OR to_userid = ?', undef, $_, $_ ) - foreach ( $u1->id, $u2->id ); + foreach ( $u1->id, $u2->id, $uc->id ); $dbh->do( 'DELETE FROM trust_groups WHERE userid = ?', undef, $_ ) - foreach ( $u1->id, $u2->id ); + foreach ( $u1->id, $u2->id, $uc->id ); + $dbh->do( 'DELETE FROM reluser WHERE userid = ? OR targetid = ?', undef, $_, $_ ) + foreach ( $u1->id, $u2->id, $uc->id ); - foreach my $u ( $u1, $u2 ) { + foreach my $u ( $u1, $u2, $uc ) { foreach my $mc ( qw/ trust_group wt_list / ) { LJ::memcache_kill( $u, $mc ); } @@ -478,6 +483,26 @@ push @tests, [ 'allowed to watch and tru } ]; ################################################################################ +push @tests, [ 'join community', sub +{ + rst(); + $u1->add_edge( $uc, member => 1 ); + return ( scalar( $uc->member_userids ) == 1 ) ? 1 : 0; +} ]; + +################################################################################ +push @tests, [ 'community watch list has zero', sub +{ + return ( scalar( keys %{ $uc->watch_list } ) == 0 ) ? 1 : 0; +} ]; + +################################################################################ +push @tests, [ 'community watch list has one', sub +{ + return ( scalar( keys %{ $uc->watch_list( community_okay => 1 ) } ) == 1 ) ? 1 : 0; +} ]; + +################################################################################ $| = 1; my $id = 1; foreach my $test ( @tests ) { diff -r dfd18646e8e7 -r 035ff3532833 cgi-bin/DW/Logic/LogItems.pm --- a/cgi-bin/DW/Logic/LogItems.pm Sat Mar 07 06:07:58 2009 +0000 +++ b/cgi-bin/DW/Logic/LogItems.pm Sat Mar 07 07:10:16 2009 +0000 @@ -120,7 +120,7 @@ sub watch_items return undef if $fr_loaded; # get all friends for this user and groupmask - my $friends = $u->watch_list; + my $friends = $u->watch_list( community_okay => 1 ); my %friends_u; # strip out rows with invalid journal types diff -r dfd18646e8e7 -r 035ff3532833 cgi-bin/DW/User/Edges/WatchTrust.pm --- a/cgi-bin/DW/User/Edges/WatchTrust.pm Sat Mar 07 06:07:58 2009 +0000 +++ b/cgi-bin/DW/User/Edges/WatchTrust.pm Sat Mar 07 07:10:16 2009 +0000 @@ -559,7 +559,7 @@ sub trust_list { return {} if $memc_only; # damn you memcache for not having our data - return DW::User::Edges::WatchTrust::Loader::_trust_list_db( $u ); + return DW::User::Edges::WatchTrust::Loader::_trust_list_db( $u, force_database => $db_only ); } *LJ::User::trust_list = \&trust_list; @@ -612,7 +612,7 @@ sub trust_group_list { return {} if $memc_only; # damn you memcache for not having our data - return DW::User::Edges::WatchTrust::Loader::_trust_group_list_db( $mask, $u ); + return DW::User::Edges::WatchTrust::Loader::_trust_group_list_db( $mask, $u, force_database => $db_only ); } *LJ::User::trust_group_list = \&trust_group_list; @@ -634,6 +634,7 @@ sub watch_list { $u = LJ::want_user( $u ) or confess 'invalid user object'; my $memc_only = delete $args{memcache_only} || 0; my $db_only = delete $args{force_database} || 0; + my $comm_okay = delete $args{community_okay} || 0; confess 'extra/invalid arguments' if %args; # special case, we can disable loading friends for a user if there is a site @@ -642,7 +643,7 @@ sub watch_list { # attempt memcache if allowed unless ( $db_only ) { - my $memc = DW::User::Edges::WatchTrust::Loader::_watch_list_memc( $u ); + my $memc = DW::User::Edges::WatchTrust::Loader::_watch_list_memc( $u, community_okay => $comm_okay ); return $memc if $memc; } @@ -651,7 +652,11 @@ sub watch_list { return {} if $memc_only; # damn you memcache for not having our data - return DW::User::Edges::WatchTrust::Loader::_watch_list_db( $u ); + return DW::User::Edges::WatchTrust::Loader::_watch_list_db( + $u, + force_database => $db_only, + community_okay => $comm_okay + ); } *LJ::User::watch_list = \&watch_list; @@ -794,15 +799,6 @@ sub delete_trust_group { my $bit = $grp->{groupnum}+0; return 0 unless $bit >= 1 && $bit <= 60; - # remove the bits for deleted groups from all friends groupmasks - my $dbh = LJ::get_db_writer() - or return 0; - $dbh->do( - q{UPDATE wt_edges SET groupmask = groupmask & ~(1 << ?) WHERE from_userid = ?}, - undef, $bit, $u->id - ); - return 0 if $dbh->err; - # remove all posts from allowing that group: my @posts_to_clean = @{ $u->selectcol_arrayref( q{SELECT jitemid FROM logsec2 WHERE journalid = ? AND allowmask & (1 << ?)}, @@ -832,8 +828,13 @@ sub delete_trust_group { # notify the tags system so it can do its thing LJ::Tags::deleted_trust_group( $u, $bit ); + # used here down + my $dbh = LJ::get_db_writer() + or return 0; + # iterate over everybody in this group and remove the bit - foreach my $tid ( keys %{ $u->trust_group_list( id => $bit ) || {} } ) { + my $tglist = $u->trust_group_list( id => $bit, force_database => 1 ); + foreach my $tid ( keys %{ $tglist || {} } ) { $dbh->do( q{UPDATE wt_edges SET groupmask = groupmask & ~(1 << ?) WHERE from_userid = ? AND to_userid = ?}, undef, $bit, $u->id, $tid diff -r dfd18646e8e7 -r 035ff3532833 cgi-bin/DW/User/Edges/WatchTrust/Loader.pm --- a/cgi-bin/DW/User/Edges/WatchTrust/Loader.pm Sat Mar 07 06:07:58 2009 +0000 +++ b/cgi-bin/DW/User/Edges/WatchTrust/Loader.pm Sat Mar 07 07:10:16 2009 +0000 @@ -143,7 +143,7 @@ sub _trust_group_list_db { return _fil # attempt to load a user's watch list from memcache sub _wt_list_memc { - my $u = $_[0]; + my ( $u, %args ) = @_; # variable setup my %rows; # rows to be returned @@ -154,7 +154,8 @@ sub _wt_list_memc { my @cols = qw/ to_userid fgcolor bgcolor groupmask showbydefault /; # first, check memcache - my $memkey = [$userid, "wt_list:$userid"]; + my $key = ( $args{community_okay} && $u->is_community ) ? 'c_wt_list' : 'wt_list'; + my $memkey = [$userid, "$key:$userid"]; my $memdata = LJ::MemCache::get($memkey); return undef unless $memdata; @@ -185,7 +186,7 @@ sub _wt_list_memc { # attempt to load a user's watch list from the database sub _wt_list_db { - my $u = $_[0]; + my ( $u, %args ) = @_; my $userid = $u->id; my $dbh = LJ::get_db_writer(); @@ -200,8 +201,8 @@ sub _wt_list_db { my $lock = LJ::get_lock($dbh, "global", $lockname); return {} unless $lock; - # in lock, try memcache - my $memc = _wt_list_memc( $u ); + # in lock, try memcache first (unless told not to) + my $memc = $args{force_database} ? undef : _wt_list_memc( $u, community_okay => $args{community_okay} ); return $release_lock->( $memc ) if $memc; # we are now inside the lock, but memcache was empty, so we must query @@ -209,14 +210,54 @@ sub _wt_list_db { # memcache data info my $ver = 2; # memcache data version - my $memkey = [$userid, "wt_list:$userid"]; + my $key = ( $args{community_okay} && $u->is_community ) ? 'c_wt_list' : 'wt_list'; + my $memkey = [$userid, "$key:$userid"]; my $packfmt = "NH6H6QC"; # pack format my $packlen = 19; # length of $packfmt # columns we're selecting - my @cols = qw/ to_userid fgcolor bgcolor groupmask showbydefault /; my $mempack = $ver; # full packed string to insert into memcache, byte 1 is dversion my %rows; # rows object to be returned, all groupmasks match + + # at this point we branch. if we're trying to get the list of things the community + # watches - for usage in the friends page only - then we change paths. + if ( $u->is_community && $args{community_okay} ) { + # simply get userids from elsewhen to build %rows + foreach my $uid ( $u->member_userids ) { + # pack data into list, but only store up to 950k of data before + # bailing. (practical limit of 64k watch list entries.) + # + # also note that we fake a lot of this, since communities don't actually + # have a watch list. + my $newpack = pack( $packfmt, ( $uid, '000000', 'ffffff', 1 << 61, '1' ) ); + last if length($mempack) + length($newpack) > 950*1024; + + $mempack .= $newpack; + + # more faking it for fun and profit + $rows{$uid} = { + to_userid => $uid, + fgcolor => '#000000', + bgcolor => '#ffffff', + groupmask => 1 << 61, + showbydefault => '1', + }; + } + + # now stuff in memcache and bail + LJ::MemCache::set( $memkey, $mempack ); + return $release_lock->( \%rows ); + } + + # at this point, if they're not an individual, then throw an empty set of data in memcache + # and bail out. only individuals have watch lists. + unless ( $u->is_individual ) { + LJ::MemCache::set( $memkey, $mempack ); + return $release_lock->( \%rows ); + } + + # actual watching path + my @cols = qw/ to_userid fgcolor bgcolor groupmask showbydefault /; # try the SQL on the master database my $sth = $dbh->prepare( 'SELECT to_userid, fgcolor, bgcolor, groupmask, showbydefault ' . @@ -248,7 +289,7 @@ sub _wt_list_db { } # now stuff in memcache - LJ::MemCache::add($memkey, $mempack); + LJ::MemCache::set($memkey, $mempack); # finished with lock, release it return $release_lock->( \%rows ); --------------------------------------------------------------------------------