mark: A photo of Mark kneeling on top of the Taal Volcano in the Philippines. It was a long hike. (Default)
Mark Smith ([staff profile] mark) wrote in [site community profile] changelog2009-03-06 07:53 am

[dw-free] Need new trust group method

[commit: http://hg.dwscoalition.org/dw-free/rev/eae6da291a54]

http://bugs.dwscoalition.org/show_bug.cgi?id=442

Add trust_list and trust_group_list methods to LJ::User.

Patch by [staff profile] mark.

Files modified:
  • bin/test/test-wtf
  • cgi-bin/DW/User/Edges/WatchTrust.pm
  • cgi-bin/DW/User/Edges/WatchTrust/Loader.pm
--------------------------------------------------------------------------------
diff -r 8149c4258dbf -r eae6da291a54 bin/test/test-wtf
--- a/bin/test/test-wtf	Fri Mar 06 07:33:37 2009 +0000
+++ b/bin/test/test-wtf	Fri Mar 06 07:52:58 2009 +0000
@@ -27,7 +27,7 @@ sub rst {
         foreach ( $u1->id, $u2->id );
 
     foreach my $u ( $u1, $u2 ) {
-        foreach my $mc ( qw/ trust_group / ) {
+        foreach my $mc ( qw/ trust_group wt_list / ) {
             LJ::memcache_kill( $u, $mc );
         }
     }
@@ -80,6 +80,13 @@ push @tests, [ 'trust list one member', 
 } ];
 
 ################################################################################
+push @tests, [ 'trust_list one member', sub
+{
+    my $ids = $u1->trust_list;
+    return scalar( keys %$ids ) == 1 ? 1 : 0;
+} ];
+
+################################################################################
 push @tests, [ 'mutually trust list empty', sub
 {
     my @ids = $u1->mutually_trusted_userids;
@@ -123,6 +130,13 @@ push @tests, [ 'trust list empty', sub
 {
     my @ids = $u1->trusted_userids;
     return scalar( @ids ) == 0 ? 1 : 0;
+} ];
+
+################################################################################
+push @tests, [ 'trust_list empty', sub
+{
+    my $ids = $u1->trust_list;
+    return scalar( keys %$ids ) == 0 ? 1 : 0;
 } ];
 
 ################################################################################
@@ -346,8 +360,19 @@ push @tests, [ 'validate trustmask == 1'
 push @tests, [ 'validate trustmask == 1', sub
 {
     rst();
+
+    # have to create a group with a known id for these tests
+    $u1->edit_trust_group( id => 1, groupname => 'bar group', _force_create => 1 );
+
     $u1->add_edge( $u2, trust => { nonotify => 1 } );
     return ( $u1->trustmask( $u2 ) == 1 ) ? 1 : 0;
+} ];
+
+################################################################################
+push @tests, [ 'validate nobody in group 1', sub
+{
+    my $ids = $u1->trust_group_list( id => 1 );
+    return ( scalar ( keys %$ids ) == 0 ) ? 1 : 0;
 } ];
 
 ################################################################################
@@ -355,6 +380,13 @@ push @tests, [ 'add to group, validate t
 {
     $u1->edit_trustmask( $u2, add => 1 );
     return ( $u1->trustmask( $u2 ) == 3 ) ? 1 : 0;
+} ];
+
+################################################################################
+push @tests, [ 'validate in group 1', sub
+{
+    my $ids = $u1->trust_group_list( id => 1 );
+    return ( scalar ( keys %$ids ) == 1 ) ? 1 : 0;
 } ];
 
 ################################################################################
diff -r 8149c4258dbf -r eae6da291a54 cgi-bin/DW/User/Edges/WatchTrust.pm
--- a/cgi-bin/DW/User/Edges/WatchTrust.pm	Fri Mar 06 07:33:37 2009 +0000
+++ b/cgi-bin/DW/User/Edges/WatchTrust.pm	Fri Mar 06 07:52:58 2009 +0000
@@ -126,7 +126,7 @@ sub _add_wt_edge {
     LJ::MemCache::delete( [$from_userid, "trustmask:$from_userid:$to_userid"] );
     LJ::memcache_kill( $to_userid, 'wt_edges_rev' );
     LJ::memcache_kill( $from_userid, 'wt_edges' );
-    LJ::memcache_kill( $from_userid, 'watch_list' );
+    LJ::memcache_kill( $from_userid, 'wt_list' );
     LJ::memcache_kill( $from_userid, 'watched' );
     LJ::memcache_kill( $from_userid, 'trusted' );
     LJ::memcache_kill( $to_userid, 'watched_by' );
@@ -204,7 +204,7 @@ sub _del_wt_edge {
     # kill memcaches
     LJ::memcache_kill( $from_u, 'wt_edges' );
     LJ::memcache_kill( $to_u, 'wt_edges_rev' );
-    LJ::memcache_kill( $from_u, 'watch_list' );
+    LJ::memcache_kill( $from_u, 'wt_list' );
     LJ::memcache_kill( $from_u, 'watched' );
     LJ::memcache_kill( $from_u, 'trusted' );
     LJ::memcache_kill( $to_u, 'watched_by' );
@@ -525,6 +525,100 @@ sub mutually_trusted_userids {
 #      { groupmask => NNN, fgcolor => '#xxx', bgcolor => '#xxx', showbydefault => NNN }
 #   }
 #
+# one entry in the hashref for everything the given user trusts.  note that fgcolor/bgcolor
+# are only really useful for watched users, so these will be default/empty if the user
+# is only trusted.
+#
+# arguments is a hash of options
+#    memcache_only => 1,     if set, never hit database
+#    force_database => 1,    if set, ALWAYS hit database (DANGER)
+#
+sub trust_list {
+    my ( $u, %args ) = @_;
+    $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;
+    confess 'extra/invalid arguments' if %args;
+
+    # special case, we can disable loading friends for a user if there is a site
+    # problem or some other issue with this codebranch
+    return undef if $LJ::FORCE_EMPTY_FRIENDS{ $u->id };
+
+    # attempt memcache if allowed
+    unless ( $db_only ) {
+        my $memc = DW::User::Edges::WatchTrust::Loader::_trust_list_memc( $u );
+        return $memc if $memc;
+    }
+
+    # bail early if we are supposed to only hit memcache, this saves us from a
+    # potentially expensive database call in codepaths that are best-effort
+    return {} if $memc_only;
+
+    # damn you memcache for not having our data
+    return DW::User::Edges::WatchTrust::Loader::_trust_list_db( $u );
+}
+*LJ::User::trust_list = \&trust_list;
+
+
+# returns hashref;
+#
+#   { userid =>
+#      { groupmask => NNN, fgcolor => '#xxx', bgcolor => '#xxx', showbydefault => NNN }
+#   }
+#
+# one entry in the hashref for everything the given user has in a particular trust
+# group.  you can specify the group by id or name.
+#
+# arguments is a hash of options
+#    id => 1,                if set, get members of trust group id 1
+#    name => "Foo Group",    if set, get members of trust group "Foo Group"
+#    memcache_only => 1,     if set, never hit database
+#    force_database => 1,    if set, ALWAYS hit database (DANGER)
+#
+sub trust_group_list {
+    my ( $u, %args ) = @_;
+    $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 $name = delete $args{name};
+    my $id = delete $args{id};
+    confess 'extra/invalid arguments' if %args;
+    confess 'need one of: id, name' unless $id || $name;
+    confess 'do not need both: id, name' if $id && $name;
+
+    # special case, we can disable loading friends for a user if there is a site
+    # problem or some other issue with this codebranch
+    return undef if $LJ::FORCE_EMPTY_FRIENDS{ $u->id };
+
+    # load the user's groups
+    my $grp = $u->trust_groups( id => $id, name => $name );
+    return {} unless $grp;
+
+    # calculate mask to use later
+    my $mask = 1 << $grp->{groupnum};
+
+    # attempt memcache if allowed
+    unless ( $db_only ) {
+        my $memc = DW::User::Edges::WatchTrust::Loader::_trust_group_list_memc( $mask, $u );
+        return $memc if $memc;
+    }
+
+    # bail early if we are supposed to only hit memcache, this saves us from a
+    # potentially expensive database call in codepaths that are best-effort
+    return {} if $memc_only;
+
+    # damn you memcache for not having our data
+    return DW::User::Edges::WatchTrust::Loader::_trust_group_list_db( $mask, $u );
+}
+*LJ::User::trust_group_list = \&trust_group_list;
+
+
+# returns hashref;
+#
+#   { userid =>
+#      { groupmask => NNN, fgcolor => '#xxx', bgcolor => '#xxx', showbydefault => NNN }
+#   }
+#
 # one entry in the hashref for everything the given user is watching.
 #
 # arguments is a hash of options
diff -r 8149c4258dbf -r eae6da291a54 cgi-bin/DW/User/Edges/WatchTrust/Loader.pm
--- a/cgi-bin/DW/User/Edges/WatchTrust/Loader.pm	Fri Mar 06 07:33:37 2009 +0000
+++ b/cgi-bin/DW/User/Edges/WatchTrust/Loader.pm	Fri Mar 06 07:52:58 2009 +0000
@@ -116,8 +116,33 @@ sub _wt_userids {
 }
 
 
+# helper to filter the _wt_list by a groupmask AND
+sub _filter_wt_list {
+    my ( $mask, $raw ) = @_;
+    return {} unless $mask; # undef/0 = no matches!
+    return undef unless defined $raw && ref $raw eq 'HASH';
+    return $raw unless keys %$raw;
+
+    return
+        {
+            map  { $_ => $raw->{$_}                }
+            grep { $raw->{$_}->{groupmask} & $mask }
+            keys %$raw
+        };
+}
+
+
+# helper, simply passes down to _wt_list_memc and filters
+sub _watch_list_memc       { return _filter_wt_list( 1 << 61, _wt_list_memc( @_ ) ); }
+sub _watch_list_db         { return _filter_wt_list( 1 << 61, _wt_list_db( @_ ) );   }
+sub _trust_list_memc       { return _filter_wt_list( 1,       _wt_list_memc( @_ ) ); }
+sub _trust_list_db         { return _filter_wt_list( 1,       _wt_list_db( @_ ) );   }
+sub _trust_group_list_memc { return _filter_wt_list( shift(), _wt_list_memc( @_ ) ); }
+sub _trust_group_list_db   { return _filter_wt_list( shift(), _wt_list_db( @_ ) );   }
+
+
 # attempt to load a user's watch list from memcache
-sub _watch_list_memc {
+sub _wt_list_memc {
     my $u = $_[0];
 
     # variable setup
@@ -129,7 +154,7 @@ sub _watch_list_memc {
     my @cols    = qw/ to_userid fgcolor bgcolor groupmask showbydefault /;
 
     # first, check memcache
-    my $memkey = [$userid, "watch_list:$userid"];
+    my $memkey = [$userid, "wt_list:$userid"];
     my $memdata = LJ::MemCache::get($memkey);
     return undef unless $memdata;
 
@@ -159,13 +184,13 @@ sub _watch_list_memc {
 
 
 # attempt to load a user's watch list from the database
-sub _watch_list_db {
+sub _wt_list_db {
     my $u = $_[0];
 
     my $userid = $u->id;
     my $dbh = LJ::get_db_writer();
 
-    my $lockname = "get_watch_list:$userid";
+    my $lockname = "get_wt_list:$userid";
     my $release_lock = sub {
         LJ::release_lock($dbh, "global", $lockname);
         return $_[0];
@@ -176,7 +201,7 @@ sub _watch_list_db {
     return {} unless $lock;
 
     # in lock, try memcache
-    my $memc = _watch_list_memc( $u );
+    my $memc = _wt_list_memc( $u );
     return $release_lock->( $memc ) if $memc;
 
     # we are now inside the lock, but memcache was empty, so we must query
@@ -184,7 +209,7 @@ sub _watch_list_db {
 
     # memcache data info
     my $ver     = 2;         # memcache data version
-    my $memkey  = [$userid, "watch_list:$userid"];
+    my $memkey  = [$userid, "wt_list:$userid"];
     my $packfmt = "NH6H6QC"; # pack format
     my $packlen = 19;        # length of $packfmt
 
@@ -195,7 +220,7 @@ sub _watch_list_db {
 
     # try the SQL on the master database
     my $sth = $dbh->prepare( 'SELECT to_userid, fgcolor, bgcolor, groupmask, showbydefault ' .
-                             'FROM wt_edges WHERE from_userid = ? AND groupmask & 1<<61' );
+                             'FROM wt_edges WHERE from_userid = ?' );
     $sth->execute( $userid );
     confess $dbh->errstr if $dbh->err;
 
--------------------------------------------------------------------------------