Skip to content

Auth: replace the global Dependencies registry with instance-stored dependencies #1175

Description

@grdsdev

Background

#1174 identified that every AuthClient registers its Dependencies (APIClient,
SessionManager, event emitter, etc.) into a process-global dictionary
(Dependencies.instances in Sources/Auth/Internal/Dependencies.swift) keyed by an
ever-incrementing clientID, with nothing ever removing entries.

The immediate leak (point 1 from #1174) and the self-referential lifecycle-observer
retain cycle (point 3) were fixed directly:

  • AuthClient now has a deinit that removes its entry from Dependencies.instances.
  • The app-lifecycle Combine subscriptions are now stored on an instance property
    (appLifecycleCancellables) instead of a local var kept alive by a
    self-referential closure, so they're released deterministically when the client
    deallocates.

Remaining work (point 2 from #1174)

The registry pattern itself is still architecturally awkward: Dependencies is
looked up by clientID through a global LockIsolated<[AuthClientID: Dependencies]>
dictionary rather than being held directly by the AuthClient instance. This exists
so that several nonisolated computed properties on the actor AuthClient
(api, sessionManager, eventEmitter, sessionStorage, pkce, etc., see
Sources/Auth/AuthClient.swift) can synchronously resolve their dependencies without
actor isolation — introduced in #445 ("add support for multiple auth instances").

Now that entries are cleaned up in deinit, the memory-leak angle is resolved, but it
would be cleaner and less error-prone long-term to store Dependencies directly on
AuthClient (e.g. behind a nonisolated(unsafe) stored property protected the same
way _globalClientID is, or restructuring so those computed properties don't need
process-global lookup at all) rather than relying on a global keyed registry + manual
teardown. This would remove an entire class of "forgot to clean up the registry" bugs
by construction.

This is a refactor, not a correctness bug — no user-facing impact expected.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions