Python: Add Azure Managed Redis Support with Credential Provider (#2887)

* azure redis support

* small fixes

* azure managed redis sample

* fixes
This commit is contained in:
Giles Odigwe
2025-12-18 09:10:55 -08:00
committed by GitHub
Unverified
parent ff9343d7cc
commit 37b4cfd024
5 changed files with 297 additions and 16 deletions
@@ -93,11 +93,118 @@ class TestRedisChatMessageStore:
assert store.max_messages == 100
def test_init_with_redis_url_required(self):
"""Test that redis_url is required for initialization."""
with pytest.raises(ValueError, match="redis_url is required for Redis connection"):
# Should raise an exception since redis_url is required
"""Test that either redis_url or credential_provider is required."""
with pytest.raises(ValueError, match="Either redis_url or credential_provider must be provided"):
RedisChatMessageStore(thread_id="test123")
def test_init_with_credential_provider(self):
"""Test initialization with credential_provider."""
mock_credential_provider = MagicMock()
with patch("agent_framework_redis._chat_message_store.redis.Redis") as mock_redis_class:
mock_redis_instance = MagicMock()
mock_redis_class.return_value = mock_redis_instance
store = RedisChatMessageStore(
credential_provider=mock_credential_provider,
host="myredis.redis.cache.windows.net",
thread_id="test123",
)
# Verify Redis.Redis was called with correct parameters
mock_redis_class.assert_called_once_with(
host="myredis.redis.cache.windows.net",
port=6380,
ssl=True,
username=None,
credential_provider=mock_credential_provider,
decode_responses=True,
)
# Verify store instance is properly initialized
assert store.thread_id == "test123"
assert store.redis_url is None # Should be None for credential provider auth
assert store.key_prefix == "chat_messages"
assert store.max_messages is None
def test_init_with_credential_provider_custom_port(self):
"""Test initialization with credential_provider and custom port."""
mock_credential_provider = MagicMock()
with patch("agent_framework_redis._chat_message_store.redis.Redis") as mock_redis_class:
mock_redis_instance = MagicMock()
mock_redis_class.return_value = mock_redis_instance
store = RedisChatMessageStore(
credential_provider=mock_credential_provider,
host="myredis.redis.cache.windows.net",
port=6379,
ssl=False,
username="admin",
thread_id="test123",
)
# Verify custom parameters were passed
mock_redis_class.assert_called_once_with(
host="myredis.redis.cache.windows.net",
port=6379,
ssl=False,
username="admin",
credential_provider=mock_credential_provider,
decode_responses=True,
)
# Verify store instance is properly initialized
assert store.thread_id == "test123"
assert store.redis_url is None # Should be None for credential provider auth
assert store.key_prefix == "chat_messages"
def test_init_credential_provider_requires_host(self):
"""Test that credential_provider requires host parameter."""
mock_credential_provider = MagicMock()
with pytest.raises(ValueError, match="host is required when using credential_provider"):
RedisChatMessageStore(
credential_provider=mock_credential_provider,
thread_id="test123",
)
def test_init_mutually_exclusive_params(self):
"""Test that redis_url and credential_provider are mutually exclusive."""
mock_credential_provider = MagicMock()
with pytest.raises(ValueError, match="redis_url and credential_provider are mutually exclusive"):
RedisChatMessageStore(
redis_url="redis://localhost:6379",
credential_provider=mock_credential_provider,
host="myredis.redis.cache.windows.net",
thread_id="test123",
)
async def test_serialize_with_credential_provider(self):
"""Test that serialization works correctly with credential provider authentication."""
mock_credential_provider = MagicMock()
with patch("agent_framework_redis._chat_message_store.redis.Redis") as mock_redis_class:
mock_redis_instance = MagicMock()
mock_redis_class.return_value = mock_redis_instance
store = RedisChatMessageStore(
credential_provider=mock_credential_provider,
host="myredis.redis.cache.windows.net",
thread_id="test123",
key_prefix="custom_prefix",
max_messages=100,
)
# Serialize the store state
state = await store.serialize()
# Verify serialization includes correct values
assert state["thread_id"] == "test123"
assert state["redis_url"] is None # Should be None for credential provider auth
assert state["key_prefix"] == "custom_prefix"
assert state["max_messages"] == 100
assert state["type"] == "redis_store_state"
def test_init_with_initial_messages(self, sample_messages):
"""Test initialization with initial messages."""
with patch("agent_framework_redis._chat_message_store.redis.from_url"):