Repository: redis/redis-py
File: redis/auth/token_manager.py (Python)

Code before:
        self._init_timer = None
        self._retries = 0

    def __del__(self):
        logger.info("Token manager are disposed")
        self.stop()

    def start(
        self,
        listener: CredentialsListener,
        skip_initial: bool = False,
    ) -> Callable[[], None]:
        self._listener = listener

        try:
            loop = asyncio.get_running_loop()
        except RuntimeError:
            # Run loop in a separate thread to unblock main thread.
            loop = asyncio.new_event_loop()

            # Use threading.Event to signal when loop is ready
            loop_ready = threading.Event()

            def start_loop():
                asyncio.set_event_loop(loop)
                loop_ready.set()  # Signal that loop is ready
                loop.run_forever()

            thread = threading.Thread(target=start_loop, daemon=True)
            thread.start()

            # Wait for the loop to be ready before scheduling
            loop_ready.wait()

        # Use thread-safe Event for cross-thread synchronization
        init_done = threading.Event()

        def renew_with_callback():
            try:
                self._renew_token(skip_initial)
            finally:
                init_done.set()

        # Schedule using call_soon_threadsafe for thread-safe scheduling
        loop.call_soon_threadsafe(renew_with_callback)
        logger.info("Token manager started")

        # Blocks using thread-safe Event
        init_done.wait()
        return self.stop


Review comment (suggestion):
The inline function `start_loop` replaces the previous `_start_event_loop_in_thread` function but lacks documentation. Consider adding a docstring or inline comment explaining its purpose, especially the significance of signaling `loop_ready` before starting the event loop. This would improve code maintainability and help future developers understand the synchronization mechanism.
```suggestion
                # This runs in the background thread. First, bind the event loop to
                # this thread, then signal that the loop is ready so the calling
                # thread can safely schedule work (via call_soon_threadsafe) before
                # we block in run_forever().
                asyncio.set_event_loop(loop)
                loop_ready.set()  # Signal that loop is ready for cross-thread use
```

Code after:
        self._init_timer = None
        self._retries = 0

    def __del__(self):
        logger.info("Token manager are disposed")
        self.stop()

    def start(
        self,
        listener: CredentialsListener,
        skip_initial: bool = False,
    ) -> Callable[[], None]:
        self._listener = listener

        try:
            loop = asyncio.get_running_loop()
        except RuntimeError:
            # Run loop in a separate thread to unblock main thread.
            loop = asyncio.new_event_loop()

            # Use threading.Event to signal when loop is ready
            loop_ready = threading.Event()

            def start_loop():
                # This runs in the background thread. First, bind the event loop to
                # this thread, then signal that the loop is ready so the calling
                # thread can safely schedule work (via call_soon_threadsafe) before
                # we block in run_forever().
                asyncio.set_event_loop(loop)
                loop_ready.set()  # Signal that loop is ready for cross-thread use
                loop.run_forever()

            thread = threading.Thread(target=start_loop, daemon=True)
            thread.start()

            # Wait for the loop to be ready before scheduling
            loop_ready.wait()

        # Use thread-safe Event for cross-thread synchronization
        init_done = threading.Event()

        def renew_with_callback():
            try:
                self._renew_token(skip_initial)
            finally:
                init_done.set()

        # Schedule using call_soon_threadsafe for thread-safe scheduling
        self._init_timer = loop.call_soon_threadsafe(renew_with_callback)
        logger.info("Token manager started")