Skip to content

Commit 01ec8b2

Browse files
Fix module version checks (#227)
Fixes issue: #226 related to the search module version checks. Also introduces a clean exception module for adding RedisVL specific exceptions.
1 parent 42e33a3 commit 01ec8b2

File tree

7 files changed

+63
-11
lines changed

7 files changed

+63
-11
lines changed

redisvl/exceptions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class RedisVLException(Exception):
2+
"""Base RedisVL exception"""
3+
4+
5+
class RedisModuleVersionError(RedisVLException):
6+
"""Invalid module versions installed"""

redisvl/index/index.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import redis.asyncio as aredis
2626
from redis.commands.search.indexDefinition import IndexDefinition
2727

28+
from redisvl.exceptions import RedisModuleVersionError
2829
from redisvl.index.storage import BaseStorage, HashStorage, JsonStorage
2930
from redisvl.query import BaseQuery, CountQuery, FilterQuery
3031
from redisvl.query.filter import FilterExpression
@@ -354,7 +355,17 @@ def from_existing(
354355

355356
# Validate modules
356357
installed_modules = RedisConnectionFactory.get_modules(redis_client)
357-
validate_modules(installed_modules, [{"name": "search", "ver": 20810}])
358+
359+
try:
360+
required_modules = [
361+
{"name": "search", "ver": 20810},
362+
{"name": "searchlight", "ver": 20810},
363+
]
364+
validate_modules(installed_modules, required_modules)
365+
except RedisModuleVersionError as e:
366+
raise RedisModuleVersionError(
367+
f"Loading from existing index failed. {str(e)}"
368+
)
358369

359370
# Fetch index info and convert to schema
360371
index_info = cls._info(name, redis_client)
@@ -860,7 +871,17 @@ async def from_existing(
860871

861872
# Validate modules
862873
installed_modules = await RedisConnectionFactory.get_modules_async(redis_client)
863-
validate_modules(installed_modules, [{"name": "search", "ver": 20810}])
874+
875+
try:
876+
required_modules = [
877+
{"name": "search", "ver": 20810},
878+
{"name": "searchlight", "ver": 20810},
879+
]
880+
validate_modules(installed_modules, required_modules)
881+
except RedisModuleVersionError as e:
882+
raise RedisModuleVersionError(
883+
f"Loading from existing index failed. {str(e)}"
884+
) from e
864885

865886
# Fetch index info and convert to schema
866887
index_info = await cls._info(name, redis_client)

redisvl/redis/connection.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from redis.connection import AbstractConnection, SSLConnection
1010
from redis.exceptions import ResponseError
1111

12+
from redisvl.exceptions import RedisModuleVersionError
1213
from redisvl.redis.constants import DEFAULT_REQUIRED_MODULES
1314
from redisvl.redis.utils import convert_bytes
1415
from redisvl.version import __version__
@@ -143,10 +144,16 @@ def validate_modules(
143144
if int(installed_version) >= int(required_module["ver"]): # type: ignore
144145
return
145146

146-
raise ValueError(
147-
f"Required Redis database module {required_module['name']} with version >= {required_module['ver']} not installed. "
148-
"See Redis Stack documentation: https://redis.io/docs/stack/"
147+
# Build the error message dynamically
148+
required_modules_str = " OR ".join(
149+
[f'{module["name"]} >= {module["ver"]}' for module in required_modules]
149150
)
151+
error_message = (
152+
f"Required Redis db module {required_modules_str} not installed. "
153+
"See Redis Stack docs at https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/."
154+
)
155+
156+
raise RedisModuleVersionError(error_message)
150157

151158

152159
class RedisConnectionFactory:

tests/integration/test_connection.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from redis.asyncio import Redis as AsyncRedis
66
from redis.exceptions import ConnectionError
77

8+
from redisvl.exceptions import RedisModuleVersionError
89
from redisvl.redis.connection import (
910
RedisConnectionFactory,
1011
compare_versions,
@@ -102,7 +103,7 @@ def test_convert_index_info_to_schema():
102103
assert schema.index.name == index_info["index_name"]
103104

104105

105-
def test_validate_modules_exist():
106+
def test_validate_modules_exist_search():
106107
validate_modules(
107108
installed_modules={"search": 20811},
108109
required_modules=[
@@ -112,8 +113,18 @@ def test_validate_modules_exist():
112113
)
113114

114115

116+
def test_validate_modules_exist_searchlight():
117+
validate_modules(
118+
installed_modules={"searchlight": 20819},
119+
required_modules=[
120+
{"name": "search", "ver": 20810},
121+
{"name": "searchlight", "ver": 20810},
122+
],
123+
)
124+
125+
115126
def test_validate_modules_not_exist():
116-
with pytest.raises(ValueError):
127+
with pytest.raises(RedisModuleVersionError):
117128
validate_modules(
118129
installed_modules={"search": 20811},
119130
required_modules=[

tests/integration/test_llmcache.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from pydantic.v1 import ValidationError
88
from redis.exceptions import ConnectionError
99

10+
from redisvl.exceptions import RedisModuleVersionError
1011
from redisvl.extensions.llmcache import SemanticCache
1112
from redisvl.index.index import AsyncSearchIndex, SearchIndex
1213
from redisvl.query.filter import Num, Tag, Text
@@ -782,7 +783,8 @@ def test_index_updating(redis_url):
782783
)
783784
assert response == []
784785

785-
with pytest.raises(ValueError):
786+
with pytest.raises((RedisModuleVersionError, ValueError)):
787+
786788
cache_with_tags = SemanticCache(
787789
name="test_cache",
788790
redis_url=redis_url,
@@ -870,7 +872,8 @@ def test_bad_dtype_connecting_to_existing_cache():
870872
try:
871873
cache = SemanticCache(name="float64_cache", dtype="float64")
872874
same_type = SemanticCache(name="float64_cache", dtype="float64")
873-
except ValueError:
875+
# under the hood uses from_existing
876+
except RedisModuleVersionError:
874877
pytest.skip("Not using a late enough version of Redis")
875878

876879
with pytest.raises(ValueError):

tests/integration/test_semantic_router.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pytest
55
from redis.exceptions import ConnectionError
66

7+
from redisvl.exceptions import RedisModuleVersionError
78
from redisvl.extensions.router import SemanticRouter
89
from redisvl.extensions.router.schema import Route, RoutingConfig
910
from redisvl.redis.connection import compare_versions
@@ -285,7 +286,8 @@ def test_bad_dtype_connecting_to_exiting_router(routes):
285286
routes=routes,
286287
dtype="float64",
287288
)
288-
except ValueError:
289+
# under the hood uses from_existing
290+
except RedisModuleVersionError:
289291
pytest.skip("Not using a late enough version of Redis")
290292

291293
with pytest.raises(ValueError):

tests/integration/test_session_manager.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pytest
44
from redis.exceptions import ConnectionError
55

6+
from redisvl.exceptions import RedisModuleVersionError
67
from redisvl.extensions.constants import ID_FIELD_NAME
78
from redisvl.extensions.session_manager import (
89
SemanticSessionManager,
@@ -566,7 +567,8 @@ def test_bad_dtype_connecting_to_exiting_session():
566567
try:
567568
session = SemanticSessionManager(name="float64 session", dtype="float64")
568569
same_type = SemanticSessionManager(name="float64 session", dtype="float64")
569-
except ValueError:
570+
# under the hood uses from_existing
571+
except RedisModuleVersionError:
570572
pytest.skip("Not using a late enough version of Redis")
571573

572574
with pytest.raises(ValueError):

0 commit comments

Comments
 (0)