Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
One important bit of the functionality you need on a day to day basis when
you work on a migration is rollback. You want to iterate on top of your existing migration,
add some new fields, work on proper processing, or simply consider a little bit more data this time.
In order to have a fluent development flow, you need to be able to rollback migrations.
Proposed resolution
Add a migration rollback functionality.
Remaining tasks
User interface changes
API changes
Comment | File | Size | Author |
---|---|---|---|
#21 | interdiff.txt | 2.19 KB | mikeryan |
#21 | add_a_rollback-2361093-21.patch | 21.5 KB | mikeryan |
Comments
Comment #1
penyaskitoComment #2
dawehnerGiven how horrible it is, to have this missing, let's declare that at least as major.
Here is a patch which is NOT meant to be fine, I just want someone of the migration team be motivated to actually work on it :)
Comment #3
giorgio79 CreditAttribution: giorgio79 commentedI used https://www.drupal.org/project/backup_migrate in D7 for rollbacks :) May be enough to create a backend auto interface if that module is installed :)
Comment #4
dawehnerWell, this is just a workaround, having proper support would be nice though.
Comment #5
mikeryanOK, picking up some of dawehner's work, this patch works to rollback entities (testing with the beer example in migrate_plus). Should we fill in rollback operations for all destinations in this patch or (my preference) get the basic infrastructure and entity rollback in here, and add some novice tasks to fill in the rest?
I'll note that I've changed rollbackMultiple() to rollback() - batch deletion is of limited value given entities in particular don't have bulk deletion in core.
Comment #6
benjy CreditAttribution: benjy at CodeDrop commentedI've not reviewed this yet but i'd agree with just having support for the generic entity destination and then creating follow-ups for the other destinations.
Comment #7
krlucas CreditAttribution: krlucas commentedHow do I even test this?
Where do I contribute the "drush migrate-rollback" command? Or am I thinking about it all wrong.
I have written a non-Drupal migrate module for D8 and am able to execute it using "drush migrate-manifest ..."
That said, I presume those wishing to execute a rollback for a d6_node migration are wondering similar things?
Comment #8
mikeryan@krlucas: The Migrate Plus project is where the full drush commands for migration are being done. #2403411: Implement migrate-rollback command for D8 is the issue for implementing drush migrate-rollback once the API in this issue has been committed to core.
Comment #11
mikeryanTime to reroll!
Comment #12
Devin Carlson CreditAttribution: Devin Carlson commentedA reroll of #5.
Comment #13
mikeryanThis is critical for developing migrations.
Comment #14
mikeryanWith event goodness - still needs tests though. Works with latest migrate_plus patch at #2403411: Implement migrate-rollback command for D8.
Comment #15
phenaproximaI see several minor issues...
Nit: more than 80 characters. =P
Why can this be an array or boolean? More explanation would be good here. The use of the word "values" in the parameter name implies an array.
Nit, but I think it's clearer to say "the migration being rolled back", dropping the word "entity".
If this is going to be completely commented out until we properly implement the reverse requirement check, IMO this should not be here now.
$return is never changed. Why don't we just return MigrationInterface::RESULT_COMPLETED directly?
"Key of the destination object"? Not sure I understand this. Can it be better-explained in the doc comment?
Nit: ID is capitalized here, but it's Id everywhere else?
The parameter name in the doc comment does not match the actual parameter name :)
Comment #17
mikeryanAs it happens, I'm revisiting this today...
Comment #18
mikeryanUpdated patch to feature parity with import (e.g., managing idle/rolling-back status). Had hoped to do tests today, but didn't get to them...
Comment #19
mikeryanNow with tests! Ready for human review once the bots have their say...
Comment #20
benjy CreditAttribution: benjy at PreviousNext commentedI think this is looking pretty good, mainly a few style issues and some questions.
The spacing and order of these seems weird. Is this inline with what core does? Ignore me if it is.
Incorrect event class.
Is it all or nothing in core?
I think this could all be on one line :)
Inconsistent formatting.
I'm not a big fan of the serialized array so we can use it as a key. Maybe not here but it would be nice if could get the keys another way.
This is something we do in import as well, wonder if it's worth its own method.
$this->migration->isComplete()
Comment #21
mikeryanIgnoring ;-). See ConfigEvents for an example (the one I originally copy-and-pasted from).
Fixed.
It's one-at-a-time in core. $rollbackBatchSize was a relic of D7 migrate, used to determine how big a batch to pass to deleteMultiple(), but D8 entities only have delete() so no batching.
Sigh, ok. https://www.drupal.org/coding-standards#linelength obviously means nothing in D8...
Fixed.
Definitely out-of-scope here.
When/if #2545632: [PP1] Move memory reclamation out of migrate executable is done, the memory handling should use interruptMigration() and the checkStatus() part here will go away.
Nope. For one thing, $return hasn't yet been passed to setMigrationResult(). For another, basing isComplete() on the result/status is wrong: #2554003: isComplete() should not rely on RESULT_COMPLETED
Thanks!
Comment #24
mikeryanHrrrm, retest did not reset the status...
Comment #25
benjy CreditAttribution: benjy at PreviousNext commentedHow I usually format long lines with an array is like below, passes phpcs.
If you set the result a few lines earlier then isComplete() would work? Thanks for pointing me to the other issue, i'll leave some thoughts over there as well.
Comment #26
mikeryanShould I reroll?
isComplete() is still wrong. Wrong, wrong, wrong!
Comment #27
benjy CreditAttribution: benjy at PreviousNext commentedI've commented on the other issue about the result / isComplete DX.
It may be "wrong" from a technical sense but I think it's more poor naming, isComplete doesn't check RESULT_COMPLETE, now that's wrong!
Comment #28
mikeryanCommented over there, I'm fine with renaming isComplete().
But, can I get an RTBC on this issue? What isComplete() (under any name) is meant to do is irrelevant to the RESULT_COMPLETED check here.
Comment #29
benjy CreditAttribution: benjy at PreviousNext commentedSure!
Comment #31
webchickAsked about this. This is a holdover from D7, where we had the ability to delete multiple, and batch them. This was removed in D8.
Walked through this with @mikeryan and @phenaproxima, all looks good to me. The API's clear, well-documented (we added a few more comments to MigrateExecutable::rollback() as we went through), and useful functionality to have in core.
Committed and pushed to 8.0.x. Thanks! :D
Comment #34
benjy CreditAttribution: benjy at PreviousNext commentedComment #35
dawehnerOne thing I observed on some custom update code is that IDs explicit mapping in the migration after this issue doesn't stick anymore, so something like:
used to work exactly how expected. This issue kinda broke that so I needed something like this:
Comment #36
benjy CreditAttribution: benjy at PreviousNext commentedDo we know which part of this issue broke that? We definitely need a follow-up to fix that, keeping Ids is pretty essential to the upgrade path.
Comment #37
mikeryanI discussed some with dawehner in #drupal-contribute, and asked for a distinct issue with steps to reproduce. He said it broke for him after RC...3? I can't see how the rollback patch would be involved, it didn't touch getEntity() (the stub patch would be more likely). IDs are preserved for me in a straightforward D6->D8 upgrade. I should have asked more about what "custom update code" meant... Not clear to me if this was reimporting already-migrated content, or running a migration intended to update existing content (not from migration).