Open sigridjineth opened 1 month ago
from typing import Optional, Dict, Any, Union import websocket
class SyncClient: """ SyncClient class for managing real-time connections and authentication.
...
Methods:
sign_out():
Sign out and clean up resources. This method must be called to
terminate WebSocket connections and prevent resource leaks.
"""
def __init__(self, realtime_url: str, supabase_key: str, options: Optional[Dict[str, Any]] = None):
self.realtime_url = realtime_url
self.supabase_key = supabase_key
self.options = options
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]
):
# ...
access_token = session.access_token if session else None
self.realtime.set_auth(access_token)
def sign_out(self):
"""Sign out and clean up resources."""
# Terminate WebSocket connections
if self.realtime:
self.realtime.disconnect()
# Perform other cleanup tasks
# ...
def __enter__(self):
"""Enter the runtime context related to this object."""
return self
def __exit__(self, exc_type, exc_value, traceback):
"""Exit the runtime context related to this object."""
self.sign_out()
class SyncRealtimeClient: def init(self, realtime_url: str, token: str, params: Optional[Dict[str, Any]] = None): self.realtime_url = realtime_url self.token = token self.params = params self._endpointWebSocket = None
def connect(self):
# ...
self._endpointWebSocket = websocket.WebSocketApp(
self.realtime_url,
header={"Authorization": f"Bearer {self.token}"},
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close,
)
self._endpointWebSocket.run_forever()
def disconnect(self):
"""Disconnect the WebSocket connection."""
if self._endpointWebSocket:
self._endpointWebSocket.close()
self._endpointWebSocket = None
def set_auth(self, access_token: Optional[str]):
"""Set the authentication token for the WebSocket connection."""
self.token = access_token
if self._endpointWebSocket:
self.disconnect()
self.connect()
def on_message(self, ws, message):
# Handle incoming messages
pass
def on_error(self, ws, error):
# Handle errors
pass
def on_close(self, ws, close_status_code, close_msg):
# Handle connection close
pass
if name == "main": with SyncClient(realtime_url="wss://example.com/socket", supabase_key="your-supabase-key") as client:
# ...
pass
# The sign_out() method will be called automatically when exiting the context
Full Disclosure, I'm currently learning. Hope the code I provided above helps. Feel free to comment with any advice etc.
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.
Key points:
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.