In #1421974: Allow messages to be saved in prepareRow() the queue message options was added, but as far I can tell this doesn't work for rows skipped via prepareRow(). I think that inside MigrateSource::prepareRow() we need to clean the existing messages (wipe old messages) and save the queued ones before setting currentRow and currentKey to NULL.

Right now the queued message are saved inside Migration::import(), but skipped records don't go that far into processing (they are skipped inside MigrationSource::next() function).

This is the code I have inside MyMigration::prepareRow() and doesn't work. The messages are saved after a valid row is found with the id of the valid row.


  function prepareRow() {
    // ...
    if (!$this->hasAllMandatoryFields()) {
      $this->queueMessage(t('Row skipped because is missing essential information'), MigrationBase::MESSAGE_INFORMATIONAL);
      return FALSE;
    }
    // ...
  }

Right now I fixed by adding changing Migration::saveQueuedMessages():

  /**
   * Save any messages we've queued up to the message table.
   *
   * @param $wipe
   *   Boolean value indicating if the old messages should be wiped before save.
   */
  public function saveQueuedMessages($wipe = FALSE) {
    if ($wipe) {
      $this->map->delete($this->currentSourceKey(), TRUE);
    }

    foreach ($this->queuedMessages as $queued_message) {
      $this->saveMessage($queued_message['message'], $queued_message['level']);
    }
    $this->queuedMessages = array();
  }

And calling it inside MigrationSource::prepareRow():

  /**
   * Give the calling migration a shot at manipulating, and possibly rejecting,
   * the source row.
   *
   * @return bool
   *  FALSE if the row is to be skipped.
   */
  protected function prepareRow($row) {
    migrate_instrument_start(get_class($this->activeMigration) . ' prepareRow');
    $return = $this->activeMigration->prepareRow($row);
    migrate_instrument_stop(get_class($this->activeMigration) . ' prepareRow');
    // We're explicitly skipping this row - keep track in the map table
    if ($return === FALSE) {
      $this->activeMigration->getMap()->saveIDMapping($row, array(),
        MigrateMap::STATUS_IGNORED, $this->activeMigration->rollbackAction);
      $this->activeMigration->saveQueuedMessages(TRUE); // Save queued messages
      $this->numIgnored++;
      $this->currentRow = NULL;
      $this->currentKey = NULL;
    }
    else {
      $return = TRUE;
    }
    $this->numProcessed++;
    return $return;
  }

Comments

Luxian’s picture

Adding the patch with the code I use right now

mikeryan’s picture

Status: Active » Needs review

When submitting a patch, please set the status to "needs review".

Status: Needs review » Needs work

The last submitted patch, migrate-queued_message_issue_for_rejected_row-1982564-1.patch, failed testing.

Luxian’s picture

Status: Needs work » Needs review
StatusFileSize
new1.55 KB

I didn't want to send the patch for testing before getting a confirmation that I'm not doing anything work with my approach. Maybe this patch would work.

Status: Needs review » Needs work

The last submitted patch, migrate-queued_message_issue_for_rejected_row-1982564-4.patch, failed testing.

mikeryan’s picture

Looks like you're deleting the map table row rather than messages?

Luxian’s picture

Status: Needs work » Needs review
StatusFileSize
new1.63 KB

Let's try it like this. I changed the order a little bit: saveQueuedMessages() is called before saveIDMapping() and should be no problem even if the mapping gets deleted.

Status: Needs review » Needs work

The last submitted patch, migrate-queued_message_issue_for_rejected_row-1982564-7.patch, failed testing.

mikeryan’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, migrate-queued_message_issue_for_rejected_row-1982564-7.patch, failed testing.

mikeryan’s picture

Status: Needs work » Needs review
StatusFileSize
new1.12 KB

Here's a simpler approach, does this work for you?

Status: Needs review » Needs work

The last submitted patch, migrate-preserve_prepareRow_messages-1982564-11.patch, failed testing.

Luxian’s picture

Status: Needs work » Needs review
StatusFileSize
new1.53 KB

Unfortunately the messages are not saved with your patch. Rows that are skipped in prepareRow() are not processed in migration.inc. Messages can be saved only inside source.inc (prepareRow() or next() functions).

I'll post a new patch. This time I didn't change much inside migrate.inc (made the function saveQueuedMessages() public instead of protected) and called map->delete() straight from source -> prepareRow().

I tried to run the tests on my local and I don't have the error reported by testbot. Maybe is something wrong with automatic tests.

Status: Needs review » Needs work

The last submitted patch, migrate-preserve_prepareRow_messages-1982564-13.patch, failed testing.

mikeryan’s picture

Issue tags: +Migrate 2.6

Tagging for Migrate 2.6.

mikeryan’s picture

Status: Needs work » Needs review
Issue tags: -Migrate 2.6

Status: Needs review » Needs work
Issue tags: +Migrate 2.6

The last submitted patch, migrate-preserve_prepareRow_messages-1982564-13.patch, failed testing.

mikeryan’s picture

Status: Needs work » Fixed

Ignore the failed tests, nothing to do with this...

I've committed a simplified version of the patch, thanks!

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