rive-app / rive-app/rive-docs

Docs suggestion: call out actor-reentrancy pitfall in the "caching a Worker" migration guide

Open Beginner friendly
#773 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
MDX
Stars
30
Forks
56
Avg merge
1d 17h
Merged PRs (30d)
44

Description

Summary

The Caching a Rive File / Worker guide recommends lazily creating and caching a single Worker behind an actor

https://github.com/rive-app/rive-docs/blob/3fe8efc468acc290763be1535a8b59b7ae1c513b/runtimes/apple/migrating-from-legacy.mdx?plain=1#L64-L82

This pattern is a check-then-await-then-write sequence. Because await Worker() is a suspension point, two callers racing worker() can both observe cachedWorker == nil before either has written the result, leading to Worker() being constructed twice (wasted init cost, and briefly two live Worker/CommandServer instances). actor/@MainActor isolation prevents data races here, but not this logic race (reentrancy across an await), so neither the compiler nor Thread Sanitizer catches it.

We ran into exactly this in our app and ended up caching the in-flight Task instead of the value:

actor WorkerProvider {
    @MainActor private var cachedWorker: Worker?
    @MainActor private var loadingTask: Task<Void, Error>?

    @MainActor
    func worker() async throws -> Worker {
        if let cachedWorker { return cachedWorker }

        let task = loadingTask ?? Task {
            cachedWorker = try await Worker()
        }
        loadingTask = task

        try await task.value
        return cachedWorker!
    }
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with runtimes/apple/migrating-from-legacy.mdx, especially the linked lines in the “Caching a Rive File / Worker” guide. Explain that caching a Worker behind an actor can still construct it twice when initialization suspends, and document the in-flight Task approach shown in the issue. Done means the migration guide clearly calls out the reentrancy pitfall and its suggested mitigation.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
documentation
Issue type
Documentation
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.