Postponed on #1853144: Store created date/time.
Problem/Motivation
When the option 'Delete redirects that have not been accessed for' is not set to 'Never', manually created redirects are deleted on the next cron run. This is because during cron 'inactive' redirects are cleaned up. This are redirects that haven't been accessed for a defined period of time. Just created redirects have never been accessed, so they are removed because the value for 'access' is 0.
Proposed resolution
Keep track of when a redirect is created. When purging inactive redirects, besides checking if they haven't been accessed for some time, also check if they haven't been created recently. The patch for adding the 'created' column is in #1853144: Store created date/time.
Remaining tasks
- Review and improve #1853144: Store created date/time.
- Update this issue after #1853144: Store created date/time is committed.
- Maybe create an issue for adding a drush command to set a value for 'created' on existing redirects. See #21.
User interface changes
On the overview page of redirects, a column 'Created' is added.
API changes
None.
Data model changes
A column called 'created' is added to the redirect table.
Original report by danst0
Hi,
I just installed the Redirect module and added several redirects which were in the .htaccess before.
After adding some stuff, Redirect just deleted a bunch of them (not all but most).
I have the auto deletion set to six month.
I think the screenshots show what I mean...
Did I do something wrong?
Daniel
Comments
Comment #1
jaydub commentedI think the issue here might be when redirects you've entered haven't been accessed yet ({redirect}.access field is 0). This would certainly be the case with redirects you've just created although also could be redirects you created months ago that just happen to not have been ever hit.
The query that purges inactive redirects simply looks for redirect rows where the access field is less than the current time minus the auto deletion interval
$query->condition('access', REQUEST_TIME - $interval, '<');
Because we can't distinguish between newly created redirects (with access of 0) and old redirects that just happen to never have been hit (access of 0) I think the solution should be to set the access field to the current timestamp when a redirect is first added. Let me try rolling a patch.
Comment #2
jaydub commentedI think that just adding another condition to the query to pull inactive redirects to check that the count field is greater than 0 will fix this. A newly created redirect as noted above will have an access time of 0 and so will get caught up in the query noted above. Adding a condition that the count of accesses of the redirect be greater than 0 should address this.
Comment #3
juliangb commentedI've had this problem too. I created a load of redirects, which were deleted by cron before they were used. I've temporarily fixed by disabling the auto-delete setting.
Instead of checking that the redirect has been accessed though, which could mean that redirects are never deleted if not accessed, why not simply set an access when the redirect is first created? That will effectively give the redirect 6 months (or whatever has been set) to be used.
Comment #4
torotil commentedHere is a patch that makes the access time default to the current timestamp instead of 0.
Comment #6
torotil commentedThis patch also changes the previously failing test-assumption (it was assuming $redirect->access = 0).
Comment #7
basillic commented#6 works for me. Thanks @torotil !
Comment #8
pere orgaI marked #1747500: Delete never accessed redirects after the set purge period (like in D6) as a duplicate of this one.
I think the patch should use
REQUEST_TIMEinstead oftime().Comment #9
pere orgaClosed #2025525: Redirect Expiration Feature Deletes New Redirects as a duplicate of this one
Comment #10
pere orgaWe could use solution in #1853144: Store created date/time if gets merged
Comment #11
mvcWhat about existing redirects? Should this patch fix those in an update hook?
For sites which expire redirects after a set time, trying to delete a massive number of redirects at once could cause a problem. emsearcy suggested the following which would space the deletions across 180 days:
UPDATE redirect SET access=UNIX_TIMESTAMP()+FLOOR(RAND()*15552000) WHERE access=0;Comment #12
megachrizHere is solution based on the patch from #1853144: Store created date/time. The date that a redirect is created is now also taken into account when purging redirects.
Explanation of the patches:
For the testbot, to demonstrate the problem.
The fix based on #1853144: Store created date/time. Should not been evaluated by the testbot while #1853144: Store created date/time has not been committed yet.
For the testbot, to demonstrate that the change fixes the issue. This includes the changes from #1853144: Store created date/time.
Comment #13
megachrizComment #18
frank.schalkwijk commentedI modified @MegaChriz's patch to work with the current rc3 release
Comment #19
mvcAs mentioned above the solution in #18 does not permit expiring redirects which were never accessed. I still feel this patch should do that, and include a fix for existing redirects in an update hook.
Comment #20
sokrplare commentedUpgrading to Major as unexpected data deletion is kinda sorta a big deal :)
Comment #21
Tschet commentedI also took the "created" date approach. I used @MegaChriz's patch on https://www.drupal.org/node/1853144, then @frank.schalkwijk's #18 above. This combination adds a "created" column in the redirect table and a hook_update sets the value as "0" for existing redirects.
I realize I added code from another existing ticket but, in my opinion, that solution would be the answer to this problem even if the other ticket didn't exist.
Comment #22
Tschet commentedSetting to needs review after adding patch.
Comment #25
Tschet commentedMy patch was against 7.x-1.0-rc3. Should it have been against 7.x-1.x-dev?
Comment #26
mvc@Tschet yes, please post a patch against the latest HEAD of 7.x-1.x-dev.
Comment #27
kreynen commented@Tschet patch for #21 appears to resolve the issue for us when applied to 7.x-1.0-rc3, but I'm reluctant to apply a patch in prod for 4+ year old issue without some feedback from the project maintainers. I've attempted to refactor the patch so it can apply to 7.x-1.x-dev to keep this conversation moving forward.
Comment #28
kreynen commentedComment #31
kreynen commentedI think the existing test of the deletion of the redirect when cron was run is actually confirming the bug and is now failing because the redirect isn't being deleted. Please correct me if I'm wrong, but when redirect is configured to delete unused redirect that are more than a week old in http://cgit.drupalcode.org/redirect/tree/redirect.test?h=7.x-1.x#n191 and then a redirect is created http://cgit.drupalcode.org/redirect/tree/redirect.test?h=7.x-1.x#n197, it shouldn't have been deleted in http://cgit.drupalcode.org/redirect/tree/redirect.test?h=7.x-1.x#n220 because it wasn't > 1 week old.
I think the test is only failing because it was written in a way that exploited this bug.
Comment #32
mvcAlso, the comment on the new function redirect_created_zero_find() says "Find baby name nodes based on supplied criteria.", which I'm guessing was copied from some sample code. This should be updated.
Comment #33
Tschet commentedI believe this incorporates all of the important changes from # 21, without the errors. It should work on the 7.x-1.x-dev.
Comment #36
kreynen commentedFatal error: Cannot redeclare drush_redirect_set_created() (previously declared in /var/www/html/sites/all/modules/redirect/redirect.drush.inc:51) in /var/www/html/sites/all/modules/redirect/redirect.drush.inc on line 104
This function was added to redirect.drush.inc twice in the patch from #33.
Comment #37
kreynen commentedComment #40
kreynen commentedSame issue with redirect_created_zero_find(). Really hoping the tests to run now.
Comment #43
kreynen commentedI've fixed @Tschet's patch so the tests run again, but this fails the same test as it did #28. Like I said in #31, I believe that test is now wrong.
Comment #44
megachrizI suppose it would be easier if #1853144: Store created date/time is done first. Now are we trying here to fix two issues at once, which I think makes it harder to review. It seems to me that the feature for the Drush command should be a seperate issue.
So please review and improve #1853144: Store created date/time and get that one committed. Then return back to this issue.
I updated the issue summary and set the status of this issue to "postponed".
Comment #45
mvcComment #46
mvcComment #47
lukedekker commentedThis patch is a modification of @Kreynen's. I've removed all of the duplicate code from #1853144: Store created date/time. I've also removed the Drush integration so that it can be handled in its own case.
There were some use cases not covered in original purge query modifications, that I've added. This patch assumes that that redirects where
access and created = 0should be kept. This is to be compatible with any existing redirects that have been created. (Such as a scenario where someone has turned off purging until these issues are resolved.)This patch is dependent on the patch from #1853144: Store created date/time as indicated in the issue status
Comment #48
lukedekker commentedJust realized the patch from #47 is made relative to drupal root. Oops.
Comment #49
rooby commentedThis is critical because it causes data corruption that is not recoverable without manually recreating that data.
Comment #50
azovsky commentedI created a combined patch from two patches: issues #1396446: Redirects deleted too early + #1853144: Store created date/time, but without tests.
Just apply the patch and execute
drush updb -y.Comment #52
tomsegarra commentedIt seems the patch in #50 was created with respect to the user's Drupal root, rather than within the Redirect directory. I've updated the file paths to make it apply properly.
Comment #54
tomsegarra commentedThe patch from #50 caused testPageCache to fail. I've updated that test to accommodate this new feature, and added another test to make sure these cron purges are behaving correctly.
This passes manual testing and looks great to me.
Comment #55
jyraya commentedHello,
I tested the patch #54 and it works for me.
I think it is ready to be merged.
I am just wondering how we deal this with #1853144: Store created date/time?
Comment #56
kreynen commented#1853144: Store created date/time has been RTBC with no action from maintainers for years, but never merged. I'm really hoping that because this patch now fixes the bug in the testing used to confirm the functionality in previous releases that contributed to data loss, it will actually get reviewed by the maintainers and merged.
Comment #57
rooby commentedI don't really see why this issue would get committed if the other one didn't. But anything to make it easier for this to be committed.
I think Berdir hangs out in slack so it might be possible to ping him there and see if anyone can look at this.
Comment #58
berdirBerdir is plenty busy with about a million other things and has no intention of getting involved in the 7.x-1.x version of this project, sorry :) I only maintain the 8.x-1.x version.
Comment #59
rooby commented@Berdir:
Haha, no worries.
Comment #60
rooby commentedThat leaves Dave Reid. The relevant master issue, which he opened previously, is #2514278: Evaluate adding a comaintainer
Comment #62
dalinHere's a new patch that should fix the failed test due
Cannot redeclare redirect_update_7103()Comment #63
dalinIf and when this gets committed, we should make sure to also credit anyone who worked on #1853144: Store created date/time which at one point was a separate issue, but then was rolled into this one.
Comment #64
chris matthews commentedComment #65
Delphine Lepers commentedComment #66
Delphine Lepers commentedComment #67
Delphine Lepers commentedComment #68
Delphine Lepers commentedComment #69
kreynen commented@Delphine Lepers what problems did you find that resulted in moving the status from RTBC->Need Work? Adding the interdiff to make it easier to view the changes between the patches.
Comment #70
euk commentedHello!
Just tested the patch in #67: newly created redirects, with count = 0 are being retained during then cron run. I believe it is good to go.
Comment #71
ulethjay commentedI should begin by saying that I initially didn't know the redirect module had this feature. I had simply written something to put in my own
hook_cron, using my own query. Only when I started to dig into the redirect module looking forredirect_deletedid I stumble uponredirect_purge_inactive_redirects. When I looked at the code I saw what it would do to new items, which brought me to this issue. I wrote this without any knowledge of this issue, the existing patches, proposedcreatedcolumn, etc...This patch is in no way attempting to detract from adding a
createdcolumn to theredirecttable. That is a column I would very much like to see added.Having said that,
This patch doesn't make any schema changes, nor does it require retroactively assigning values to existing records. The basic premise is that in addition to purging any records where
accessis not zero andaccessis less than the interval limit, it will also purge records whereaccessis zero andridis less than that of the most recent accessed stale record. The idea being that if theridis a lower number it must be older.The only issue I can think of, should somebody, within the interval window, edit a record that is older than the interval and has not yet been accessed, that record will be purged. Maybe that problem has been solved already, don't know, didn't look, but at the moment I can't think of how a
createdcolumn would fix that with out the addition of anupdatedcolumn.Even though I intend to use this patch on my site in the coming days, I wouldn't recommend others do the same. It suits my needs, it may not suit yours.
Anyways, submitted for your consideration...
Comment #72
den tweed commentedUsed patch #67, can confirm redirects are not being deleted too early now (access = 0) and newly created redirects are getting the current time in the created field
Comment #73
ralphvdhoudt commentedUpdated patch #67 to the latest code and added a check if the created column does not exists yet before adding it
Comment #74
vchen commentedTried patch #73 with Redirect 7.x-1.0-rc4. It seemed to have fixed the problem at first. It passed multiple tests on different environments including prod, but then it happened again.
In my redirect settings, I have it to Delete redirects that have not been accessed for 1 yr and delete a max of 10 redirects per cron run.
The patch was applied, cleared cache, updated the db, which applied the db updates (Redirect 7105 Adds the {redirect}.created field.).
When I ran cron manually via drush, the redirects with count = 0 stayed.
When the cron ran automatically as scheduled, the redirects with count = 0 are gone again.
Not sure if the patch was meant for 7.x-1.x-dev?
Comment #75
steinmb commentedWe always roll patches against dev. to make sure it safely can be applied and works with the latest changes.
Comment #76
xorunaI applied the patch in #73 on 7.x-1.x-dev some days ago and the issue seems to be solved, thanks!
Comment #77
wylbur commentedClosing this as Outdated as Drupal 7 is EOL.