Skip to content

Make persistSharingPost idempotent for duplicate Announces #444

@dahlia

Description

@dahlia

persistSharingPost currently checks for an existing share by the Announce activity IRI before inserting a new sharing post. That is not enough to make share handling idempotent.

The same actor can announce the same original post more than once, either because of duplicate delivery, retries, or different Announce activity IRIs for the same (actor, object) pair. In that case, Hollo may fail on the posts_actor_id_sharing_id_unique constraint after it has already called persistPost() for the original object.

That matters because persistPost() can fetch and walk the remote replies collection. A duplicate Announce should be a cheap no-op, but today it can still trigger remote fetches before the database constraint rejects the insert.

This issue tracks only the idempotency part of #443. The broader question of whether persistPost() should eagerly scrape remote replies should be handled separately.

Expected behavior

When Hollo receives an Announce, persistSharingPost should treat an existing (actor_id, sharing_id) pair as an already persisted share and return that existing post instead of attempting another insert.

Possible approaches

  • After resolving the announcing actor and original post, look up an existing post with the same accountId and sharingId, including the same relations returned by the current existingPost query.
  • Alternatively, use onConflictDoNothing() for the unique constraint and perform a follow-up lookup when the insert is skipped.

Acceptance criteria

  • Duplicate Announces for the same actor and original post do not raise a unique-constraint error.
  • Duplicate Announces return the existing sharing post.
  • The duplicate path does not append another share to timelines.
  • The duplicate path does not increment the original post's sharesCount again.
  • There is a regression test covering duplicate Announces with different Announce IRIs but the same actor and original object.

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions