Closed (fixed)
Project:
Feeds
Version:
8.x-3.x-dev
Component:
Code
Priority:
Major
Category:
Bug report
Assigned:
Unassigned
Reporter:
Created:
23 Jul 2019 at 18:41 UTC
Updated:
27 Feb 2020 at 14:59 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
megachrizThat sounds pretty serious, so bumping to major.
Can you demonstrate this bug with an automated test? Because deleting the item from the clean list happens before validation. But there could be a case I hadn't thought of. Because in an other issue it is reported Feeds sometimes seems to clean more items than it should: #3068129: Issue Unpublishing non-existent nodes on Cron. (Theory not proven yet.)
From EntityProcessorBase::process():Comment #3
damondt commentedI'm looking into it further, the entities failing may be unrelated. It appears to be happening only when the feed is run in the queue, and not via batch.
Comment #4
damondt commentedI had a database backup that when cron was run this problem would occur on two feeds. Not only would the problem not occur when the feed was run through a batch process, but every subsequent queue-run after that would not exhibit the problem. I do think broken entity references are related.
Comment #5
megachriz@damondt
I'm thankful if you manage to find the cause of the issue. :)
I suspect that #3068129: Issue Unpublishing non-existent nodes on Cron is exact the same issue. In there I say:
But veronicaSeveryn says:
My suspicion is that
$clean_stateeither isn't properly saved after processing an item - under certain circumstances - or it is sometimes not properly reloaded when processing the next item. There is a queue task for each item to be processed. And during cron runs, a limited amount of these queue tasks are processed. It's interesting to know that on a single cron run, if an item unexpectly stays on the clean list when the first queue task is being picked up, when the last queue task is being picked up or just somewhere in the middle.Comment #6
damondt commentedThis continues to happen, and the intermittent nature has lead me to come to a few incorrect conclusions, but I think the problem may actually be related to this core bug:
https://www.drupal.org/project/drupal/issues/1803886
It seems to occur when a lot of content is being modified, with other comments mentioning VBO and feeds. Do you know how the solution in that issue of wrapping the query in a try catch would affect a feed import?
Comment #7
megachriz@damondt
I don't see these kind of errors in the logs on a site where I'm using the "missing items" feature (and I remember having seen in the log lots of items getting unpublished and republished on the next import again). But maybe the last time the error occurred on that site is longer than two months ago.
A PDO Exception does disrupt the process, but Feeds does catch all exceptions in
process(). So in theory, this should not prevent$clean_statefrom being saved.I see that an exception may not be catched when it occurs while loading an existing entity, because Feeds didn't wrap that in a try-catch block.
So could that be it? Does the exception occur during loading?
The last patch from #1803886: PDOException: Syntax error or access violation: 1305 SAVEPOINT savepoint_1 does not exist seems to want to ignore a specific PDO Exception and just let operations continue.
Comment #8
damondt commentedI realized the frequency that cron runs at had been lowered from every 5 minutes to every minute around the time the problem started occurring. After setting cron to run every 5 minutes again the problem stopped. The feeds queue tasks run for a minute I believe, so perhaps there was overlap that caused a problem? I don't know if that would be considered a bug, or just something to keep in mind.
Comment #9
megachriz@damondt
That's a nice theory. I thought cron couldn't run another time while it was still running, but apparently that doesn't count for queues.
From \Drupal\Core\Cron:
The cron lock is released before queues are processed.
Comment #10
megachriz@damondt
In #3068129: Issue Unpublishing non-existent nodes on Cron, @veronicaSeveryn says that it can also happen even if cron runs only once a day.
But nevertheless, it would be good to prevent
$clean_statefrom missing things if two queue tasks are run simultaneously. Thinking how we could write a test for this case: I think we would need to start two asynchronous queue tasks and then wait for both to finish. Then check for the expected contents for$clean_state.Comment #11
megachrizAnother way of testing this is as follows:
What I proposed in #10 is also possible, but requires juggling with
sleep()calls. So what I propose here is definitely simpler, but it covers slightly less from the real situation.Comment #12
agn507 commentedRan into a similar problem which @damondt pointed me to this issue. I've continually had issues with a rather large import intermittently deleting items that were actually in the feed source data. I suspected this was due to feed importers overlapping or the queue not finishing properly. On an importer of ~4000 entries we were seeing anywhere from 30-90 items being marked for deletion when they were in the feed. These items were always in a group in the source data but the importer would continue on and reported no errors. What ultimately resolved our problem was setting up a scheduled job in acquia which seems to more reliably process the import.
Comment #13
damondt commented@MegaChriz With a second confirmed case of concurrent feed processes causing issues with the clean list can we open a new issue for this? This ticket started off with an assumption that a different problem was to blame and so is named misleadingly.
Comment #14
megachriz@damondt
We can also just adjust the title of this issue and update the issue summary, as this issue contains useful information.
Or, alternatively, we could continue in #3068129: Issue Unpublishing non-existent nodes on Cron, I think it's the same problem.
Comment #15
megachriz@damondt
Slightly related to this issue: I've been working to refactor the four different import methods (import all at once, batch in UI, cron import/queue, push import) to make them all operate in the same way. For example, switching user accounts only happened during cron imports. Perhaps this issue is easier to tackle after that refactoring has been finalized. Maybe you want to review the refactoring globally?
#2811429: Switch to feed owner during manual import.
Comment #16
danielvezaI'm seeing this on a site as well. Only 1 feed running on the entire site, once per day and once per hour has led to the same results. I random amount ~50-100 being 'cleaned' then reimported later.
Comment #17
megachrizRetitling as validation has nothing to do with the issue.
Comment #18
megachrizComment #19
megachrizHad done the retitling in the "Commit message" field instead of in the "Title" field :D.
Comment #20
megachrizI've worked on a test for this issue today.
The test implements what I proposed in #11:
Comment #21
megachrizThis patch could fix the issue.
The list of items to clean is moved to the database. This should fix the issue of having outdated lists overwrite newer lists, because the entire clean list is managed in the database instead of in a serialized array. I'm not sure if this would cause issues with a huge dataset though (when there are millions of items to import).
I did create the patch on top of #2811429: Switch to feed owner during manual import., so there is a chance that the patch won't apply properly.
Comment #22
megachrizLots of the kernel tests are missing the "feeds_clean_list" table. Let's add that table for all tests and see if that fixes the test failures.
Also fixed two coding standard issues.
Comment #23
megachrizThis adds dependency injection for the CleanState class. Hopefully, this fixes the remaining test failures.
Comment #24
megachrizThe patch in #23 was based on the latest patch in #2811429: Switch to feed owner during manual import..
This one is based on the latest 8.x-3.x-dev.
Comment #25
megachriz#2811429: Switch to feed owner during manual import. was committed, which makes the patch in #23 the one to test now and patch #24 can be ignored.
After doing a self-review, I think that when
$feed->clearStates()is called that the clean list in the database need to be cleaned up. Now this happens on the next import (seeCleanState::setList()). But if you decide to stop importing a feed, you'll have some redundant rows in the database table "feeds_clean_list".Comment #26
megachrizI inspected the code again and did a manual test where nodes got cleaned on an import. It appeared that the table "feeds_clean_list" became empty after cleaning was done. This is because when cleaning each item, the corresponding record is already removed from the table. From
CleanState::nextEntity():Anyway, it would be good to clean up the clean list anyway when calling
$feed->clearStates().Also, orphaned items can still exist when an import ends abruptly.
$feed->clearStates()won't be reached when an import fails with a fatal error. So I think an other moment for cleaning up redundant rows is when deleting the feed.Patch attached with additional tests.
Comment #28
megachrizI looked through the code one more time, didn't have any concerns anymore.
Committed #26.