jointakahe / takahe

An ActivityPub/Fediverse server
BSD 3-Clause "New" or "Revised" License
1.11k stars 85 forks source link

Occasionally run into TimelineEvent.MultipleObjectsReturned get() returned more than one #717

Open alphatownsman opened 1 month ago

alphatownsman commented 1 month ago

from

    @classmethod
    def add_post(cls, identity, post):
        """
        Adds a post to the timeline if it's not there already
        """
        event, created = cls.objects.get_or_create(
            identity=identity,
            type=cls.Types.post,
            subject_post=post,
            subject_identity=post.author,
            defaults={"published": post.published or post.created},

It's hard to avoid race condition I think, so it's better to just add a unique constraint

DELETE FROM activities_timelineevent a
USING activities_timelineevent b 
WHERE a.ctid < b.ctid
AND a.identity_id=b.identity_id
AND a.type=b.type
AND a.type='post'
AND a.subject_post_id=b.subject_post_id
AND a.subject_identity_id=b.subject_identity_id;

CREATE UNIQUE INDEX idx_uniq_timelineevent_post ON activities_timelineevent(identity_id, subject_post_id, subject_identity_id) WHERE type='post';

it can be added to model, but would like to see if anyone has other suggestions before I create a PR.