Issue 5517#3
Conversation
rileydes-improving
left a comment
There was a problem hiding this comment.
Just a couple nits and clarifications that may be worth adding, otherwise LGTM
There was a problem hiding this comment.
Splitting into a separate commit would be a bit cleaner.
| ] | ||
| dependencies = [ | ||
| "agent-framework-core>=1.2.0,<2", | ||
| "valkey-glide>=2.1.0,<3; sys_platform != 'win32'", |
There was a problem hiding this comment.
Adding a comment why the window's exclusion is deliberate (i.e. not supported by valkey-glide) is probably worth explaining.
| return val.decode() if isinstance(val, bytes) else str(val) | ||
|
|
||
|
|
||
| def _fields_list_to_dict(fields_list: list[list[bytes]]) -> dict[bytes, bytes]: |
There was a problem hiding this comment.
The type signature does assume xread will always return the inner entries as list[list[bytes], the risk of this changing with minor glide version bumps is minimal but adding an @pytest.mark.integration test that does a round trip write_chunk to read_stream against a real server would likely be good practice just to ensure any depend-a-bot etc automated version bumps would have real tests to catch any regression.
It may be excessive to implement the proper integration testing just for that though.
| fields: list[tuple[str, str]], | ||
| ) -> None: | ||
| """Append an entry to a stream and refresh its TTL.""" | ||
| await self._client.xadd(stream_key, fields) # type: ignore[union-attr] |
There was a problem hiding this comment.
May be worth a comment explaining why it is ok to have the xadd and expire as separate commands, even if the process crashes etc between the commands.
i.e. "Note: xadd and expire are issued as two separate commands, so a crash between them could leave a key without a TTL. In practice this is self-healing, the TTL is refreshed on every subsequent write, and Valkey's memory eviction policy covers the final-write edge case."
13606f8 to
37b7330
Compare
37b7330 to
4332de6
Compare
Motivation and Context
The Agent Framework currently has no Valkey-native streaming component. The existing resumable streaming samples (python/samples/04-hosting/azure_functions/03_reliable_streaming/) use a RedisStreamResponseHandler built on redis-py — a sample-level implementation that isn't packaged for reuse and creates a dependency mismatch for Valkey users.
This PR delivers ValkeyStreamBuffer, a first-party, reusable streaming buffer backed by Valkey Streams using the valkey-glide client. It enables durable agents to persist response chunks so clients can disconnect and reconnect mid-stream without data loss.
Related issue: [Python] Add ValkeyStreamBuffer — resumable streaming via Valkey Streams for agent-framework-valkey microsoft#5517
Description
Adds the agent-framework-valkey Python package with a single component: ValkeyStreamBuffer.
###Core implementation (_stream_buffer.py):
Package scaffolding:
Tests (test_stream_buffer.py — 31 tests):
Files changed:
init.py (new)
_stream_buffer.py (new)
test_stream_buffer.py (new)
pyproject.toml (new)
python/packages/valkey/LICENSE (new)
README.md (new)
pyproject.toml (workspace registration)
Contribution Checklist