mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-07-02 05:38:12 +00:00
Extract duplicated Redis URL parsing into a shared cache_config utility. Introduce ValkeyCache as a lightweight async key/value cache using valkey-glide. Wire it into A2A task handling, agent card caching, and file upload caching. Part 1/4 of Valkey storage implementation. fix: async-safe embeddings and resilient drain_writes Add bytes→float validators on MemoryRecord and ItemState to handle Valkey returning embeddings as raw bytes. Make embed_texts() safe when called from an async context by using a thread pool. Improve drain_writes() with per-save timeouts and error logging instead of raising on failure. Part 3/4 of Valkey storage implementation. feat(valkey): ValkeyStorage vector memory backend Add ValkeyStorage, a distributed StorageBackend implementation using Valkey-GLIDE with Valkey Search for vector similarity. Wire it into Memory as the 'valkey' storage option. Pin scrapegraph-py<2 to fix unrelated upstream breakage. Part 4/4 of Valkey storage implementation. fix: use datetime.utcnow() for last_accessed consistency MemoryRecord defaults use utcnow() for created_at and last_accessed. Match that in ValkeyStorage.update_record() to avoid timezone inconsistency in recency scoring. feat(valkey): shared cache config + ValkeyCache for A2A and file uploads Extract duplicated Redis URL parsing into a shared cache_config utility. Introduce ValkeyCache as a lightweight async key/value cache using valkey-glide. Wire it into A2A task handling, agent card caching, and file upload caching. Part 1/4 of Valkey storage implementation. fix: handle non-numeric database path in cache URL parsing Extract _parse_db_from_path() helper that catches ValueError for paths like /mydb and defaults to 0 with a warning, instead of crashing. fix: async-safe embeddings and resilient drain_writes Add bytes→float validators on MemoryRecord and ItemState to handle Valkey returning embeddings as raw bytes. Make embed_texts() safe when called from an async context by using a thread pool. Improve drain_writes() with per-save timeouts and error logging instead of raising on failure. Part 3/4 of Valkey storage implementation. fix: catch concurrent.futures.TimeoutError for Python 3.10 compat In Python <3.11, concurrent.futures.TimeoutError is distinct from the builtin TimeoutError. Catch both so the timeout warning path works on all supported Python versions.
126 lines
4.1 KiB
Python
126 lines
4.1 KiB
Python
"""Tests for shared cache configuration helpers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from crewai.utilities.cache_config import (
|
|
get_aiocache_config,
|
|
parse_cache_url,
|
|
use_valkey_cache,
|
|
)
|
|
|
|
|
|
class TestParseCacheUrl:
|
|
"""Tests for parse_cache_url()."""
|
|
|
|
def test_returns_none_when_no_env_vars(self) -> None:
|
|
with patch.dict(os.environ, {}, clear=True):
|
|
assert parse_cache_url() is None
|
|
|
|
def test_parses_valkey_url(self) -> None:
|
|
with patch.dict(
|
|
os.environ, {"VALKEY_URL": "redis://myhost:6380/2"}, clear=True
|
|
):
|
|
result = parse_cache_url()
|
|
assert result is not None
|
|
assert result["host"] == "myhost"
|
|
assert result["port"] == 6380
|
|
assert result["db"] == 2
|
|
assert result["password"] is None
|
|
|
|
def test_parses_redis_url(self) -> None:
|
|
with patch.dict(
|
|
os.environ, {"REDIS_URL": "redis://localhost:6379/0"}, clear=True
|
|
):
|
|
result = parse_cache_url()
|
|
assert result is not None
|
|
assert result["host"] == "localhost"
|
|
assert result["port"] == 6379
|
|
assert result["db"] == 0
|
|
|
|
def test_valkey_url_takes_priority_over_redis_url(self) -> None:
|
|
with patch.dict(
|
|
os.environ,
|
|
{
|
|
"VALKEY_URL": "redis://valkey-host:6380/1",
|
|
"REDIS_URL": "redis://redis-host:6379/0",
|
|
},
|
|
clear=True,
|
|
):
|
|
result = parse_cache_url()
|
|
assert result is not None
|
|
assert result["host"] == "valkey-host"
|
|
assert result["port"] == 6380
|
|
|
|
def test_parses_password(self) -> None:
|
|
with patch.dict(
|
|
os.environ,
|
|
{"VALKEY_URL": "redis://:s3cret@myhost:6379/0"},
|
|
clear=True,
|
|
):
|
|
result = parse_cache_url()
|
|
assert result is not None
|
|
assert result["password"] == "s3cret"
|
|
|
|
def test_defaults_for_minimal_url(self) -> None:
|
|
with patch.dict(
|
|
os.environ, {"VALKEY_URL": "redis://myhost"}, clear=True
|
|
):
|
|
result = parse_cache_url()
|
|
assert result is not None
|
|
assert result["host"] == "myhost"
|
|
assert result["port"] == 6379
|
|
assert result["db"] == 0
|
|
assert result["password"] is None
|
|
|
|
def test_non_numeric_db_path_defaults_to_zero(self) -> None:
|
|
with patch.dict(
|
|
os.environ, {"VALKEY_URL": "redis://myhost:6379/mydb"}, clear=True
|
|
):
|
|
result = parse_cache_url()
|
|
assert result is not None
|
|
assert result["db"] == 0
|
|
|
|
|
|
class TestGetAiocacheConfig:
|
|
"""Tests for get_aiocache_config()."""
|
|
|
|
def test_returns_memory_cache_when_no_url(self) -> None:
|
|
with patch.dict(os.environ, {}, clear=True):
|
|
config = get_aiocache_config()
|
|
assert config["default"]["cache"] == "aiocache.SimpleMemoryCache"
|
|
|
|
def test_returns_redis_cache_when_url_set(self) -> None:
|
|
with patch.dict(
|
|
os.environ, {"VALKEY_URL": "redis://myhost:6380/2"}, clear=True
|
|
):
|
|
config = get_aiocache_config()
|
|
assert config["default"]["cache"] == "aiocache.RedisCache"
|
|
assert config["default"]["endpoint"] == "myhost"
|
|
assert config["default"]["port"] == 6380
|
|
assert config["default"]["db"] == 2
|
|
|
|
|
|
class TestUseValkeyCache:
|
|
"""Tests for use_valkey_cache()."""
|
|
|
|
def test_returns_false_when_not_set(self) -> None:
|
|
with patch.dict(os.environ, {}, clear=True):
|
|
assert use_valkey_cache() is False
|
|
|
|
def test_returns_true_when_set(self) -> None:
|
|
with patch.dict(
|
|
os.environ, {"VALKEY_URL": "redis://localhost:6379"}, clear=True
|
|
):
|
|
assert use_valkey_cache() is True
|
|
|
|
def test_returns_false_when_only_redis_url_set(self) -> None:
|
|
with patch.dict(
|
|
os.environ, {"REDIS_URL": "redis://localhost:6379"}, clear=True
|
|
):
|
|
assert use_valkey_cache() is False
|