Skip to content

Supabase Client Requires Explicit sign_out() to Terminate Properly #926

Open
@sigridjineth

Description

@sigridjineth

Summary

The Supabase client currently requires an explicit call to client.auth.sign_out() for processes to terminate correctly. Without this, background WebSocket connections and other resources may remain active, leading to incomplete shutdowns and potential resource leaks.

Problem Explanation:

The current behavior of the Supabase client involves establishing WebSocket connections and listening for authentication events. These processes, especially those involving real-time functionality, do not automatically terminate upon the program’s end. Explicitly calling client.auth.sign_out() is necessary to clean up these resources and ensure proper process termination.

# From SyncClient class in SyncClient.py
class SyncClient:
    def __init__(self, ...):
        # ...
        self.realtime = self._init_realtime_client(
            realtime_url=self.realtime_url,
            supabase_key=self.supabase_key,
            options=options.realtime if options else None,
        )
        # ...

    @staticmethod
    def _init_realtime_client(
        realtime_url: str, supabase_key: str, options: Optional[Dict[str, Any]]
    ) -> SyncRealtimeClient:
        """Private method for creating an instance of the realtime-py client."""
        return SyncRealtimeClient(
            realtime_url, token=supabase_key, params=options or {}
        )

    def _listen_to_auth_events(
        self, event: AuthChangeEvent, session: Union[Session, None]
    ):
        # ...
        self.realtime.set_auth(access_token)

# From SyncRealtimeClient in realtime-py
class SyncRealtimeClient:
    def __init__(self, ...):
        # ...
        self._endpointWebSocket = None
        # ...

    def connect(self):
        # ...
        self._endpointWebSocket = websocket.WebSocketApp(
            # ...
        )
        # ...

    def set_auth(self, token):
        # ...
        self.connect()  # This might create a new WebSocket connection

# From GoTrueClient in gotrue-py
class SyncGoTrueClient:
    def sign_out(self, options: SignOutOptions = {"scope": "global"}) -> None:
        # ...
        self._remove_session()
        self._notify_all_subscribers("SIGNED_OUT", None)

Key points:

  1. Real-time Connections: The WebSocket connections created by SyncRealtimeClient continue running in the background and need to be manually terminated.
  2. Authentication Events: Sign-out triggers an event that helps reset real-time client authentication, which won't occur unless sign_out() is called.
  3. Resource Management: The sign_out() function ensures proper cleanup of sessions and network connections, preventing potential memory leaks or resource hogging.
  4. Daemon Threads: Real-time connections might be running as daemon threads, which do not automatically terminate, leading to hanging processes unless explicitly stopped with sign_out().

Given this behavior, the necessity of an explicit client.auth.sign_out() call should be clearly documented and potentially re-evaluated for a more intuitive shutdown process.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions