diff --git a/slack_sdk/socket_mode/builtin/connection.py b/slack_sdk/socket_mode/builtin/connection.py index 588f50497..f724ffaa0 100644 --- a/slack_sdk/socket_mode/builtin/connection.py +++ b/slack_sdk/socket_mode/builtin/connection.py @@ -249,7 +249,11 @@ def check_state(self) -> None: try: if self.sock is not None: try: - self.ping(f"{self.session_id}:{time.time()}") + ping_time = time.time() + self.ping(f"{self.session_id}:{ping_time}") + # Seed on first ping so the stale check fires even if no pong ever arrives. + if self.last_ping_pong_time is None: + self.last_ping_pong_time = ping_time except ssl.SSLZeroReturnError as e: self.logger.info( "Unable to send a ping message. Closing the connection..." diff --git a/tests/slack_sdk/socket_mode/test_builtin.py b/tests/slack_sdk/socket_mode/test_builtin.py index 6ba64c9a3..7ade10f7c 100644 --- a/tests/slack_sdk/socket_mode/test_builtin.py +++ b/tests/slack_sdk/socket_mode/test_builtin.py @@ -3,7 +3,7 @@ import ssl import time import unittest -from unittest.mock import patch, sentinel +from unittest.mock import MagicMock, patch, sentinel from threading import Thread from slack_sdk import WebClient @@ -126,6 +126,23 @@ def run(): self.assertIsNotNone(conn) + def test_check_state_seeds_last_ping_pong_time_on_first_ping(self): + conn = Connection(url="wss://example.com", logger=self.logger) + conn.sock = MagicMock() + self.assertIsNone(conn.last_ping_pong_time) + with patch.object(conn, "ping"): + conn.check_state() + self.assertIsNotNone(conn.last_ping_pong_time) + + def test_check_state_does_not_overwrite_existing_last_ping_pong_time(self): + conn = Connection(url="wss://example.com", logger=self.logger) + conn.sock = MagicMock() + existing_time = time.time() - 1 + conn.last_ping_pong_time = existing_time + with patch.object(conn, "ping"): + conn.check_state() + self.assertEqual(conn.last_ping_pong_time, existing_time) + # ---------------------------------- # FrameHeader