I'm not sure how the tables got mismatched. It could happen during a backup restore or something... But in any case, during cron the dreaded Invalid argument supplied for foreach() in /.../taxonomy.module on line 1241 error appears because of this code:


/**
 * Implementation of hook_cron().
 */
function fuzzysearch_cron() {
  $query = db_query_range("SELECT nid FROM {fuzzysearch_index_queue}", 0, variable_get('fuzzysearch_index_cron', 150));
  while ($result = db_fetch_object($query)) {
    fuzzysearch_index($result->nid);
  }
}

If there are nid's returned by this query, and they are not present in the node table, non-existent nid's get sent to node_load, thus causing the error.

Replacing with this heavier function works, but it might be better if the else clause were compiled into a cleaner compound query to improve performance..



/**
 * Implementation of hook_cron().
 */
function fuzzysearch_cron() {
  //build a list of nodes in the node table
  $query = db_query("SELECT nid FROM {node}");  
  $nodes = array();
  while ($result = db_fetch_object($query)) {
    $nodes[] = $result->nid;
  }

  //run through queued nodes, eliminating those no longer in node table
  $query = db_query_range("SELECT nid FROM {fuzzysearch_index_queue}", 0, variable_get('fuzzysearch_index_cron', 150));
  while ($result = db_fetch_object($query)) {
    if(in_array($result->nid,$nodes)){
		fuzzysearch_index($result->nid);
	}else{
		db_query("DELETE FROM {fuzzysearch_index} WHERE nid = %d", $result->nid);
		db_query("DELETE FROM {fuzzysearch_index_queue} WHERE nid = %d", $result->nid);
	}
  }
}

Comments

awolfey’s picture

My guess is that something is deleting your nodes in a way that doesn't invoke nodeapi.

I think the place to check if the node still exists before indexing is in fuzzysearch_index. It would be reusable code there.

awolfey’s picture

Wrap node_load() in an if to make sure it loads. If not, delete the row from the queue and return.

tmsimont’s picture

i just updated my solution -- i had a bug in the code i posted.

the issue with wrapping node_load in an if is that the function will return a malformed node even if there's no nid to match... this is fixed in D7, but is a big issue in D6 which often leads to this error. see: http://drupal.org/node/839654

I know that the mismatch occurred during a content backup or swap -- I've been in and out of the content tables a few times. I don't think it's too uncommon for nodes to get deleted without having gone through the nodeapi.

i'm not sure if you need to update your module to account for such situations, but it might be helpful to others that run into this issue.

tmsimont’s picture

the downside to check for the node still existing in fuzzysearch_index() is that it would require a lot of additional queries... 1 for each node instead of 1 query for all nids to start... but then again, you wouldn't have to call in_array() so many times... maybe a whole new function is needed, like "fuzzysearch_clean_nonexistent_nodes()"

awolfey’s picture

This should do it at the top of fuzzysearch_index();

if (!$node = node_load($nid)) {
  db_query("DELETE FROM {fuzzysearch_index_queue} WHERE nid = %d", $nid);
  db_query("DELETE FROM {fuzzysearch_index} WHERE nid = %d", $nid);
  return;
}

If you want to submit a patch please do it against the dev version. Thanks

awolfey’s picture

Status: Active » Fixed

Fixed. This works.

<?php
  // No node, nothing to do.
  if (!$node = node_load($nid)) {
    return;
  }
?>

Status: Fixed » Closed (fixed)

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

Anonymous’s picture

Issue summary: View changes

fixed bug in solution