#1991684: Node history markers (comment & node "new" indicator, "x new comments" links) forces render caching to be per user moves history fetching from being done once for each node in a teaser, to all at once (but currently in a separate HTTP request), this means looping over history_read() to get the timestamp for each nid.

We could take an array of nids and return just those with a timestamp instead to bring that down to one query.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

andypost’s picture

Component: base system » history.module
Status: Active » Needs review
Issue tags: +API addition
FileSize
1.35 KB

While on that, here's simple patch

PS: Also I'm trying to implement manager #2081585: [META] Modernize the History module

andypost’s picture

Fixed doc-block comment

tstoeckler’s picture

+++ b/core/modules/history/history.module
@@ -41,6 +41,48 @@ function history_read($nid) {
+  $nodes_to_read = array();
+  foreach ($nids as $nid) {
+    if (isset($history[$nid])) {
+      $return[$nid] = $history[$nid];
+    }
+    else {
+      $nodes_to_read[$nid] = 0;
+    }
+  }
+
+  if (empty($nodes_to_read)) {
+    return $return;
+  }

I think using array_diff_key() here would make this much more readable. Also, from reading the code it seems because of the " = 0" the empty() check will never return TRUE. I might be mistaken, though.

andypost’s picture

The reason to use loop is to initialize array with 0 for nodes that are not been viewed by user so added comment.
So the static cache is filled with a proper return value.

Check for array emptiness could be done without empty() but this more readable.
php -r '$a = array(1 => 0); if (empty($a)) print "empty"; else print "not empty";'

tstoeckler’s picture

Ahh, I totally missed that you're filling two different arrays, there. $return != $nodes_to_read. I get it now.

tstoeckler’s picture

Forgot to add: Code looks quite good. I don't feel comfortable RTBCing this myself, however.

Wim Leers’s picture

Status: Needs review » Needs work

I doubt having a static cache is valuable in this case. It's extremely unlikely this is being called many times. We only use static caches for frequently called functions.

+++ b/core/modules/history/history.module
@@ -41,6 +41,49 @@ function history_read($nid) {
+      // Initialize value if current user has not been viewed the node.

s/has not been viewed/has not viewed/

tstoeckler’s picture

Re #7: This code is only re-using the static from history_read(). That way history_read_multiple() doesn't re-fetch items that history_read() already fetched. Thinking about this I think that part could be streamlined by history_read_multiple() maintaining its own static, and history_read() simply being a one-line call to history_read_multiple(array($nid));. That would be sort of in-line with entity_load() and so forth. Also, I think we should definitely use a drupal_static() here to avoid double DB queries. Even if the chances are small. In this particular case a drupal_static() doesn't hurt, and there are efforts to move this to a HistoryManager anyway, which would store this properly in the object state.

Don't know if you guys agree with my proposal but leaving needs work for the second item in #7 at lesat.

andypost’s picture

Status: Needs work » Needs review
FileSize
1.8 KB
1019 bytes

I prefer to preserve the name of static cache as 'history_read' because there's could be a code that uses it.
And this static cache should be shared by both functions, same as #8 said

New patch incorporated suggested changes

Status: Needs review » Needs work

The last submitted patch, drupal8.history-module.2078753-9.patch, failed testing.

andypost’s picture

Status: Needs work » Needs review
FileSize
1.8 KB
586 bytes

This allows to test new function! #9 shows that we have test coverage

Status: Needs review » Needs work

The last submitted patch, drupal8.history-module.2078753-11.patch, failed testing.

tstoeckler’s picture

Looks great, thanks! But for the test fails, this looks ready to go.

andypost’s picture

Status: Needs work » Needs review
FileSize
2.84 KB
1.72 KB

Fix test failures (json need int value)
Used new function in controller

larowlan’s picture

Just some minor nitpicks

  1. +++ b/core/modules/history/history.module
    @@ -30,14 +30,51 @@
    + * Retrieves the timestamp for the current user's last view of a nodes.
    

    'Retrieves the last viewed timestamp for each of the passed node IDs.' perhaps?

  2. +++ b/core/modules/history/history.module
    @@ -30,14 +30,51 @@
    + *   A node IDs.
    

    An array of node IDs

  3. +++ b/core/modules/history/history.module
    @@ -30,14 +30,51 @@
    +    $nodes_to_read[$row->nid] = (int)$row->timestamp;
    

    (int) $row->timestamp = needs a space after the cast

tstoeckler’s picture

  1. +++ b/core/modules/history/history.module
    @@ -100,7 +101,10 @@ function history_write($nid, $account = NULL) {
    +    // Update static cache.
    +    $history = &drupal_static('history_read', array());
    +    $history[$nid] = REQUEST_TIME;
    

    Ohh, that's very savvy. Nice!

I'd re-roll for #15 but then I can't RTBC :-P

andypost’s picture

tstoeckler’s picture

Status: Needs review » Reviewed & tested by the community

Looks good. I don't have anything to complain about.

catch’s picture

Status: Reviewed & tested by the community » Needs work

Looks good except I don't understand why we don't use __FUNCTION__ for the static naming. While that's a tiny API change I'd be very surprised if there's a module fiddling with that static.

andypost’s picture

Status: Needs work » Needs review

Suppose there's no modules dealing with this static but I preserved history_read name for BC.
__FUNCTION__ should not used because logic for static cache moved to new function

catch’s picture

I don't think we need a BC layer for that.

andypost’s picture

So here's suggested __FUNCTION__

catch’s picture

Status: Needs review » Reviewed & tested by the community

Thanks!

Wim Leers’s picture

Nicely done — HistoryController now looks much better :)

catch’s picture

Title: history_read() should take an array of node IDs » Change notice: Add history_read_multiple()
Status: Reviewed & tested by the community » Active
Issue tags: +Needs change record

Committed/pushed to 8.x, thanks!

Could use a very short change notice for the API addition.

andypost’s picture

Status: Active » Needs review
catch’s picture

Title: Change notice: Add history_read_multiple() » Add history_read_multiple()
Status: Needs review » Fixed
andypost’s picture

Issue tags: -Needs change record

fix tags

Automatically closed -- issue fixed for 2 weeks with no activity.