I couldn't find a similar issue and think there might be a serious bug unreported as yet. Would be nice, if a developer could assist.

It's about a kind of addressbook implemented with flags. Users may be flagged as a friend to be remembered for later contact. Each user can see how often he's flagged as a friend, i.e. "You've been added to 30 contact lists". Today a user told me his friend-count dropped from 30 to 5 within a couple of days or maybe just a day... you know how precise such reports are...

I started to investigate and found a huge gap between the actual flag_content and the flag_counts table. The flag_content table still shows 30 flags of this type attached to that user. The flag_counts table tells there are only 5 flags.

We recently deleted a bunch of users, and it is very likely some of them were his "friends". So my best guess is, something went wrong when removing these users. Maybe his flag_counts value was deleted and he found 5 new friends afterwards.

Any ideas?

Comments

joachim’s picture

Status: Active » Postponed (maintainer needs more info)

I would have more expected the flag_counts table to be the one with the higher count, as I seem to remember there's an issue about how that doesn't get handled when users are deleted.

Could you try to reproduce this on a dev copy and report your finding & the steps to take please?

boobaa’s picture

This issue looks like a copy of #1931170: The {flag_counts} table got out of sync, which does have some code to get the tables in sync again – anyway, I don't know how to reproduce the bug, either. Repeating here: I have proof-read all the code grepping for all the occurences where {flag_counts} table gets touched, and found nothing that can yield this result.

boobaa’s picture

Category: support » bug
Status: Postponed (maintainer needs more info) » Needs review
StatusFileSize
new594 bytes

I have found the root of the problem. It was suspicious that the {flag_counts} table had the same count value for two different fid values (but the same content_type and content_id values). So the bug does not exist if there's only one flag type. What's triggering it? Having a close look on what happens on the site when the bug is triggered (and having a great bunch of related d.o issues in my mind) revealed that the problem arises when deleting a user who does have flagged anything, and there's more than one type of flags. So I had another close look on the code, and found the culprit: hook_user_cancel() (and hook_user_delete(), too) calls flag_user_account_removal(), which starts by a left-joined SELECT on the related tables, but the ON clause contains only two of the three indexes: content_id and content_type. In other words, fid is missing from the SELECT of flag_user_account_removal(), which means both (all) the flag types will have the same count values when the function returns. This means the counters will definitely be screwed up: two (all) of the counters will have the same value, which belongs to only one of them.

Stepping a bit back shows that the content_type index is not needed at all in the ON clause, since a flag type may belong to only one content_type, which can be clearly seen from the other parts of code of the affected function.

Attached is a patch against today's 7.x-2.x git, which applies to 7.x-2.0 (the latest stable release) with some offset, and has been tested locally with satisfying results.

joachim’s picture

Version: 7.x-2.x-dev » 7.x-3.x-dev
Status: Needs review » Needs work

Nice job tracking down the bug! :)

Indeed, if you have multiple flags on the same entity type then this join could produce multiple rows, as there will be multiple rows in flag_counts for a given entity type and id!

> $query->leftJoin('flag_counts', 'c', 'fc.entity_id = c.entity_id AND fc.entity_type = c.entity_type');

This does however need fixing on 3.x first, where the table names are different. If you could reroll this on 3.x that would be super :)

Anonymous’s picture

Version: 7.x-3.x-dev » 7.x-2.x-dev
Status: Needs work » Needs review

Thank you Boobaa, you're a hero!

It's very likely this patch helps in my scenario. We're using round about 15 different flags of all kinds and the issue occurred right after mass user deletion. The patch looks sound enough to be put to production server. I've no opportunity to test it, but will report in case of any side effects.

Anonymous’s picture

BTW, there should be tests for every code changing flag counts. If one update brings the count out of sync, each subsequent update will result in a wrong count, too. What if the count drops below 1?

A "Refresh all flag counts" option in Flag administration would be great, too. Triggering the code of #1931170: The {flag_counts} table got out of sync.

joachim’s picture

Version: 7.x-2.x-dev » 7.x-3.x-dev
Status: Needs review » Needs work

Resetting issue statuses.

enricotersi’s picture

Great work!

flocondetoile’s picture

Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new620 bytes

Thanks Boobaa,

Same issue with two flags on the same node. the request called when a user is deleted iterate on the two count of the two flag but with the same fid. And then one of the flag is decrease twice (but on each with a starting value which correspond to the count value of the two flag).

Attached the patch port on 7.x-3.x

socketwench’s picture

Status: Needs review » Reviewed & tested by the community

I've tested it against 3.3. There seems to be something wrong in HEAD that's causing the automated tests to fail. Not sure if that's just my system.

stevenx’s picture

#9 works for me
running 7.x-3.2+7-dev

joachim’s picture

Longer term idea for the flag count system: #2157157: Change {flag_counts} table to be a cache. I'd appreciate the opinions of users of the flag count functionality!

joachim’s picture

Status: Reviewed & tested by the community » Fixed

Committed to 3.x. Thanks everyone!

git commit -m "Issue #1930320 by flocondetoile, Boobaa: Fixed error in flag counts caused when a user is deleted and multiple flags are present on the same entities." --author="boobaa "

Status: Fixed » Closed (fixed)

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