Skip to content

Fix race conditions in @fedify/relay follower list management #505

@dahlia

Description

@dahlia

Background

During the review of #490, a race condition issue was identified in the follower list management logic. See the review comment for details.

Problem

The current implementation stores follower IDs in an array under the ["followers"] key and uses a read-modify-write pattern to add or remove followers. This pattern is susceptible to race conditions when multiple activities are processed concurrently—one process can overwrite changes made by another, resulting in followers being incorrectly added or removed.

Scenario 1: Adding followers concurrently

  1. Process A reads followers [A, B]
  2. Process B reads followers [A, B]
  3. Process A adds C and writes [A, B, C]
  4. Process B adds D and writes [A, B, D], overwriting A's change

Result: Follower C is lost.

Scenario 2: Removing followers concurrently

  1. Process A reads followers [A, B, C]
  2. Process B reads followers [A, B, C]
  3. Process A removes B and writes [A, C]
  4. Process B removes C and writes [A, B], overwriting A's change

Result: Follower B is incorrectly restored, and C is incorrectly restored.

The affected files are:

  • packages/relay/src/mastodon.ts
  • packages/relay/src/litepub.ts
  • packages/relay/src/follow.ts
  • packages/relay/src/builder.ts

Suggested approach

Since KvStore.list() will be a required operation in Fedify 2.0.0 (#499), we can eliminate the ["followers"] array and instead rely on the list(["follower"]) operation to enumerate followers. This way, adding or removing a follower becomes a single atomic set() or delete() call on the individual ["follower", actorId] key, avoiding the race condition entirely.

Related

Metadata

Metadata

Assignees

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions