Coming here from #993186: Node access rebuilds should go newest to oldest I was looking at the code in Drupal 8 for rebuilding nodes via a batch process. I have not tested it but it looks very broken - like someone made an attempt to improve the code along the lines of that issue at some point, but did so incorrectly.

Here's the code:

function _node_access_rebuild_batch_operation(&$context) {
  if (empty($context['sandbox'])) {
    // Initiate multistep processing.
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['current_node'] = 0;
    $context['sandbox']['max'] = \Drupal::entityQuery('node')->count()->execute();
  }

  // Process the next 20 nodes.
  $limit = 20;
  $nids = \Drupal::entityQuery('node')
    ->condition('nid', $context['sandbox']['current_node'], '>')
    ->sort('nid', 'DESC')
    ->range(0, $limit)
    ->execute();
  $nodes = node_load_multiple($nids, TRUE);
  foreach ($nodes as $nid => $node) {
    // To preserve database integrity, only write grants if the node
    // loads successfully.
    if (!empty($node)) {
      \Drupal::entityManager()->getAccessControlHandler('node')->writeGrants($node);
    }
    $context['sandbox']['progress']++;
    $context['sandbox']['current_node'] = $nid;
  }

  // Multistep processing : report progress.
  if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
  }
}

So the first 20 nodes get processed in descending order: 20,19,18....1.

At the end of which, $context['sandbox']['progress'] is 20, and $context['sandbox']['current_node'] is 1.

Therefore, the next time through the batch, it will process these nodes: 21,20,19,18...2.

Oops, each node except the first is double-processed (and most are on their way to being processed 20 times).

But it's actually even worse, since $context['sandbox']['progress'] will be 40 after this second round, even though only 21 nodes have been processed. So it will eventually hit $context['sandbox']['max'] before all nodes have been processed, and the batch will finish with many nodes not rebuilt at all.

Again, I have not tested this so it's possible I'm missing something, but to me it looks like that's what will happen.

Comments

David_Rothstein’s picture

Status: Active » Needs review
StatusFileSize
new520 bytes

Here's a simple patch - make the code go back to the way it worked in Drupal 7, and leave it to #993186: Node access rebuilds should go newest to oldest to figure out how to properly do it in descending order.

Probably there should be some kind of tests for this too.

David_Rothstein’s picture

Adding a related issue (although not the same as this one).

fabianx’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Quick fix

What we have currently is totally broken, so lets get the Quick Fix in and improve upon it.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Agreed, this is a revert of a one-liner. I had a quick check to see if we could revert the original commit but it's far too long ago to do that.

Committed/pushed to 8.0.x, thanks!

  • catch committed 58b78c4 on 8.0.x
    Issue #2331113 by David_Rothstein: Fixed Node access rebuilds are...

Status: Fixed » Closed (fixed)

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