Skip to content

Commit 06c0ac6

Browse files
committed
removed socket timeout on redis clients as this is a dangerous setting
1 parent 7c2364e commit 06c0ac6

File tree

12 files changed

+12
-63
lines changed

12 files changed

+12
-63
lines changed

packages/pytest-simcore/src/pytest_simcore/redis_service.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import logging
66
from collections.abc import AsyncIterator
7-
from datetime import timedelta
87

98
import pytest
109
import tenacity
@@ -116,14 +115,6 @@ async def wait_till_redis_responsive(redis_url: URL | str) -> None:
116115
await client.aclose(close_connection_pool=True)
117116

118117

119-
@pytest.fixture
120-
def mock_redis_socket_timeout(mocker: MockerFixture) -> None:
121-
# lowered to allow CI to properly shutdown RedisClientSDK instances
122-
mocker.patch(
123-
"servicelib.redis._client.DEFAULT_SOCKET_TIMEOUT", timedelta(seconds=0.25)
124-
)
125-
126-
127118
@pytest.fixture
128119
async def use_in_memory_redis(mocker: MockerFixture) -> RedisSettings:
129120
mocker.patch("redis.asyncio.from_url", FakeAsyncRedis)

packages/service-library/src/servicelib/redis/_client.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
DEFAULT_DECODE_RESPONSES,
2121
DEFAULT_HEALTH_CHECK_INTERVAL,
2222
DEFAULT_LOCK_TTL,
23-
DEFAULT_SOCKET_TIMEOUT,
2423
)
2524

2625
_logger = logging.getLogger(__name__)
@@ -65,7 +64,7 @@ def __post_init__(self) -> None:
6564
redis.exceptions.ConnectionError,
6665
],
6766
retry_on_timeout=True,
68-
socket_timeout=DEFAULT_SOCKET_TIMEOUT.total_seconds(),
67+
socket_timeout=None, # NOTE: setting a timeout here can lead to issues with long running commands
6968
encoding="utf-8",
7069
decode_responses=self.decode_responses,
7170
client_name=self.client_name,

packages/service-library/src/servicelib/redis/_constants.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
seconds=30
88
)
99
DEFAULT_LOCK_TTL: Final[datetime.timedelta] = datetime.timedelta(seconds=10)
10-
DEFAULT_SOCKET_TIMEOUT: Final[datetime.timedelta] = datetime.timedelta(seconds=30)
1110

11+
DEFAULT_SEMAPHORE_BLOCK_TIMEOUT: Final[datetime.timedelta] = datetime.timedelta(
12+
seconds=30
13+
)
1214
DEFAULT_SEMAPHORE_TTL: Final[datetime.timedelta] = datetime.timedelta(seconds=10)
1315
SEMAPHORE_KEY_PREFIX: Final[str] = "semaphores:"
1416

packages/service-library/src/servicelib/redis/_semaphore.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
from ._constants import (
3232
DEFAULT_EXPECTED_LOCK_OVERALL_TIME,
3333
DEFAULT_SEMAPHORE_TTL,
34-
DEFAULT_SOCKET_TIMEOUT,
3534
SEMAPHORE_KEY_PREFIX,
3635
)
3736
from ._errors import (
@@ -97,7 +96,7 @@ class DistributedSemaphore(BaseModel):
9796
blocking_timeout: Annotated[
9897
datetime.timedelta | None,
9998
Field(description="Maximum time to wait when blocking"),
100-
] = DEFAULT_SOCKET_TIMEOUT
99+
] = None
101100
instance_id: Annotated[
102101
str,
103102
Field(
@@ -208,7 +207,7 @@ async def _acquire_forever_on_socket_timeout() -> list[str] | None:
208207
return tokens_key_token
209208

210209
try:
211-
# NOTE: redis-py library timeouts when the defined socket timeout triggers (e.g. DEFAULT_SOCKET_TIMEOUT)
210+
# NOTE: redis-py library timeouts when the defined socket timeout triggers
212211
# The BRPOP command itself could timeout but the redis-py socket timeout defeats the purpose
213212
# so we always block forever on BRPOP, tenacity takes care of retrying when a socket timeout happens
214213
# and we use asyncio.timeout to enforce the blocking_timeout if defined
@@ -424,7 +423,7 @@ async def distributed_semaphore( # noqa: C901
424423
capacity: PositiveInt,
425424
ttl: datetime.timedelta = DEFAULT_SEMAPHORE_TTL,
426425
blocking: bool = True,
427-
blocking_timeout: datetime.timedelta | None = DEFAULT_SOCKET_TIMEOUT,
426+
blocking_timeout: datetime.timedelta | None = None,
428427
expected_lock_overall_time: datetime.timedelta = DEFAULT_EXPECTED_LOCK_OVERALL_TIME,
429428
) -> AsyncIterator[DistributedSemaphore]:
430429
"""

packages/service-library/src/servicelib/redis/_semaphore_decorator.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from ._constants import (
1010
DEFAULT_EXPECTED_LOCK_OVERALL_TIME,
1111
DEFAULT_SEMAPHORE_TTL,
12-
DEFAULT_SOCKET_TIMEOUT,
1312
)
1413
from ._semaphore import distributed_semaphore
1514

@@ -27,7 +26,7 @@ def with_limited_concurrency(
2726
capacity: int | Callable[..., int],
2827
ttl: datetime.timedelta = DEFAULT_SEMAPHORE_TTL,
2928
blocking: bool = True,
30-
blocking_timeout: datetime.timedelta | None = DEFAULT_SOCKET_TIMEOUT,
29+
blocking_timeout: datetime.timedelta | None = None,
3130
expected_lock_overall_time: datetime.timedelta = DEFAULT_EXPECTED_LOCK_OVERALL_TIME,
3231
) -> Callable[
3332
[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]
@@ -107,7 +106,7 @@ def with_limited_concurrency_cm(
107106
capacity: int | Callable[..., int],
108107
ttl: datetime.timedelta = DEFAULT_SEMAPHORE_TTL,
109108
blocking: bool = True,
110-
blocking_timeout: datetime.timedelta | None = DEFAULT_SOCKET_TIMEOUT,
109+
blocking_timeout: datetime.timedelta | None = None,
111110
expected_lock_overall_time: datetime.timedelta = DEFAULT_EXPECTED_LOCK_OVERALL_TIME,
112111
) -> Callable[
113112
[Callable[P, AbstractAsyncContextManager[R]]],

packages/service-library/tests/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ async def _cleanup_redis_data(clients_manager: RedisClientsManager) -> None:
112112

113113
@pytest.fixture
114114
async def get_redis_client_sdk(
115-
mock_redis_socket_timeout: None, use_in_memory_redis: RedisSettings
115+
use_in_memory_redis: RedisSettings,
116116
) -> AsyncIterable[
117117
Callable[[RedisDatabase], AbstractAsyncContextManager[RedisClientSDK]]
118118
]:
@@ -122,7 +122,7 @@ async def get_redis_client_sdk(
122122

123123
@pytest.fixture
124124
async def get_in_process_redis_client_sdk(
125-
mock_redis_socket_timeout: None, redis_service: RedisSettings
125+
redis_service: RedisSettings,
126126
) -> AsyncIterable[
127127
Callable[[RedisDatabase], AbstractAsyncContextManager[RedisClientSDK]]
128128
]:

packages/service-library/tests/deferred_tasks/test_deferred_tasks.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
import asyncio
55
import contextlib
6-
import datetime
76
import itertools
87
import json
98
import random
@@ -19,7 +18,6 @@
1918
from common_library.json_serialization import json_dumps
2019
from common_library.serialization import model_dump_with_secrets
2120
from pydantic import NonNegativeFloat, NonNegativeInt
22-
from pytest_mock import MockerFixture
2321
from servicelib.rabbitmq import RabbitMQClient
2422
from servicelib.redis import RedisClientSDK
2523
from servicelib.sequences_utils import partition_gen
@@ -385,19 +383,10 @@ async def pause_redis(self) -> AsyncIterator[None]:
385383
yield
386384

387385

388-
@pytest.fixture
389-
def mock_default_socket_timeout(mocker: MockerFixture) -> None:
390-
mocker.patch(
391-
"servicelib.redis._client.DEFAULT_SOCKET_TIMEOUT",
392-
datetime.timedelta(seconds=0.25),
393-
)
394-
395-
396386
@pytest.mark.parametrize("max_workers", [10])
397387
@pytest.mark.parametrize("deferred_tasks_to_start", [100])
398388
@pytest.mark.parametrize("service", ["rabbit", "redis"])
399389
async def test_workflow_with_third_party_services_outages(
400-
mock_default_socket_timeout: None,
401390
paused_container: Callable[[str], AbstractAsyncContextManager[None]],
402391
redis_client_sdk_deferred_tasks: RedisClientSDK,
403392
rabbit_client: RabbitMQClient,

packages/service-library/tests/redis/test_client.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,7 @@ async def test_redis_lock_with_ttl(
104104
assert not await ttl_lock.locked()
105105

106106

107-
async def test_redis_client_sdk_setup_shutdown(
108-
mock_redis_socket_timeout: None, redis_service: RedisSettings
109-
):
107+
async def test_redis_client_sdk_setup_shutdown(redis_service: RedisSettings):
110108
# setup
111109
redis_resources_dns = redis_service.build_redis_dsn(RedisDatabase.RESOURCES)
112110
client = RedisClientSDK(redis_resources_dns, client_name="pytest")
@@ -130,7 +128,6 @@ async def test_redis_client_sdk_setup_shutdown(
130128

131129

132130
async def test_regression_fails_on_redis_service_outage(
133-
mock_redis_socket_timeout: None,
134131
paused_container: Callable[[str], AbstractAsyncContextManager[None]],
135132
redis_client_sdk: RedisClientSDK,
136133
):

packages/service-library/tests/redis/test_clients_manager.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717

1818
async def test_redis_client_sdks_manager(
19-
mock_redis_socket_timeout: None,
2019
redis_service: RedisSettings,
2120
):
2221
all_redis_configs: set[RedisManagerDBConfig] = {

packages/service-library/tests/redis/test_semaphore.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -354,19 +354,7 @@ async def test_semaphore_multiple_instances_capacity_limit(
354354
await semaphores[2].release()
355355

356356

357-
@pytest.fixture
358-
def with_slow_redis_socket_timeout(
359-
mock_redis_socket_timeout: None, mocker: MockerFixture
360-
) -> None:
361-
# put back to higher value to allow normal operations
362-
mocker.patch(
363-
"servicelib.redis._client.DEFAULT_SOCKET_TIMEOUT",
364-
datetime.timedelta(seconds=30),
365-
)
366-
367-
368357
async def test_semaphore_with_timeout(
369-
with_slow_redis_socket_timeout,
370358
redis_client_sdk: RedisClientSDK,
371359
semaphore_name: str,
372360
):

0 commit comments

Comments
 (0)