OSDN Git Service

Model::Firehose: import methods
authorhylom <hylom@users.sourceforge.jp>
Tue, 25 Oct 2016 12:35:18 +0000 (21:35 +0900)
committerhylom <hylom@users.sourceforge.jp>
Tue, 25 Oct 2016 12:35:18 +0000 (21:35 +0900)
src/newslash_web/lib/Newslash/Model/Firehose.pm

index f15b9df..70daeb7 100644 (file)
@@ -167,6 +167,118 @@ sub getFireHose {
     return $hr->{$id};
 }
 
+# Like getFireHose, but does the lookup by globjid (which is unique).
+#
+# One way to implement this would be to store complete hose data with
+# each globjid, the advantage being half as many memcached requests
+# and thus half the latency.  I wouldn't mind paying most of the price
+# for this:  extra memcached RAM, and extra network bandwidth in some
+# cases.  But that would also interleave hose item cache expiration
+# times, which could lead to confusing bugs.  To avoid that, I'm
+# willing to pay the price of extra latency.
+#
+# So instead this does a lookup from globjid to id (which is cached),
+# and wraps that conversion about a getFireHoseMulti call.
+#
+# The option id_only skips the step of retrieving the actual firehose
+# data and returns a hashref (or values of hashrefs) with only the
+# id field populated.
+
+sub getFireHoseByGlobjid {
+    my($self, $globjid, $options) = @_;
+    my $hr = $self->getFireHoseByGlobjidMulti([$globjid], $options);
+    return $hr->{$globjid};
+}
+
+sub getFireHoseByGlobjidMulti {
+    my($self, $globjid_ar, $options) = @_;
+    my $ret_hr = { };
+
+       # First, convert the globjids to ids.
+
+    #my $exptime = 86400;
+    #my $globjid_to_id_hr = { };
+
+    #my $mcd_hr = { };
+    #my $mcd = $self->getMCD();
+    #my $mcdkey;
+    #if ($mcd && !$options->{memcached_no_read}) {
+    #    $mcdkey = "$self->{_mcd_keyprefix}:gl2id" if $mcd;
+    #    my @keylist = ( map { "$mcdkey:$_" } @$globjid_ar );
+    #    my $mcdkey_hr = $mcd->get_multi(@keylist);
+    #    for my $k (keys %$mcdkey_hr) {
+    #        my($id) = $k =~ /^\Q$mcdkey:\E(\d+)$/;
+    #        next unless $id;
+    #        $mcd_hr->{$id} = $mcdkey_hr->{$k};
+    #    }
+    #}
+
+    my $answer_hr = { };
+    my @remaining_ids = ( grep { !defined($mcd_hr->{$_}) } @$globjid_ar );
+    my $splice_count = 2000;
+    while (@remaining_ids) {
+        my @globjid_chunk = splice @remaining_ids, 0, $splice_count;
+        my $globjid_str = join(',', @globjid_chunk);
+        my $more_hr = $self->sqlSelectAllKeyValue(
+                                                  'globjid, id',
+                                                  'firehose',
+                                                  "globjid IN ($globjid_str)");
+        # XXX faster, or slower, than iterating over $more_hr?
+        $answer_hr = {( %$answer_hr, %$more_hr )};
+    }
+
+    #if ($mcd && %$answer_hr && !$options->{memcached_no_write}) {
+    #    for my $globjid (keys %$answer_hr) {
+    #        $mcd->set("$mcdkey:$globjid", $answer_hr->{$globjid}, $exptime);
+    #    }
+    #}
+
+    $globjid_to_id_hr = {( %$mcd_hr, %$answer_hr )};
+
+    # If only the ids are desired, we can return those now.
+    if ($options->{id_only}) {
+        return $globjid_to_id_hr;
+    }
+
+       # Now that the globjids have been converted to ids, call
+       # getFireHoseMulti.
+
+    my @ids = grep { $_ } map { $globjid_to_id_hr->{$_} } @$globjid_ar;
+    my $firehose_hr = $self->getFireHoseMulti(\@ids, $options);
+    use Data::Dumper; print STDERR scalar(gmtime) . " $$ gFHM returned non-hashref from '@ids' options: " . Dumper($options) if ref($firehose_hr) ne 'HASH';
+
+    # Then convert the keys in the answer back to globjids.
+    for my $id (keys %$firehose_hr) {
+        if (ref($firehose_hr->{$id}) ne 'HASH') {
+            my $opt_str = Dumper($options); $opt_str =~ s/\s+/ /g;
+            my $fh_str = Dumper($firehose_hr); $fh_str =~ s/\s+/ /g;
+            print STDERR scalar(gmtime) . " $$ gFHM returned non-hashref-hashref for '$id' from '@ids' options '$opt_str' fh '$fh_str'\n";
+            next;
+        }
+        $ret_hr->{ $firehose_hr->{$id}{globjid} } = $firehose_hr->{$id};
+    }
+    return $ret_hr;
+}
+
+sub getFireHoseIdFromGlobjid {
+    my($self, $globjid) = @_;
+    return $self->getFireHoseByGlobjid($globjid, { id_only => 1 });
+}
+
+sub getFireHoseIdFromUrl {
+    my($self, $url) = @_;
+    if ($url) {
+        my $fudgedurl = fudgeurl($url);
+        if ($fudgedurl) {
+            my $url_id = $self->getUrlIfExists($fudgedurl);
+            if ($url_id) {
+                return $self->getPrimaryFireHoseItemByUrl($url_id);
+            }
+        }
+    }
+    return 0;
+}
+
 sub setTopicsRenderedBySkidForItem {
     my($self, $id, $primaryskid) = @_;
     #my $constants = getCurrentStatic();
@@ -188,4 +300,30 @@ sub setTopicsRenderedBySkidForItem {
     $db->setFireHose($id, { nexuslist => " $nexus " });
 }
 
+sub setTopicsRenderedForStory {
+    my($self, $stoid, $tids) = @_;
+    my $the_tids = [ @$tids ]; # Copy tids so any changes we make don't affect the caller
+    #my $constants = getCurrentStatic();
+    my $globjs = $self->new_instance_of('Globjs');
+    my $slash_db = $self->new_instance_of('SlashDB');
+
+    my $story = $slash_db->getStory($stoid, "", 1);
+    if ($story) {
+        my $globjid = $globjs->getGlobjidCreate("stories", $story->{stoid});
+        my $id = $self->getFireHoseIdFromGlobjid($globjid);
+        my @nexus_topics;
+        if ($id) {
+            $slash_db->sqlDelete("firehose_topics_rendered", "id = $id");
+            foreach (@$the_tids) {
+                $slash_db->sqlInsert("firehose_topics_rendered", { id => $id, tid => $_});
+            }
+            my $tree = $slash_db->getTopicTree();
+            @nexus_topics = grep { $tree->{$_}->{nexus} } @$the_tids;
+            my $nexus_list = join ' ', @nexus_topics;
+            $nexus_list = " $nexus_list ";
+            $self->setFireHose($id, { nexuslist => $nexus_list });
+        }
+    }
+}
+
 1;