Skip to content

Replace sorted sets with Redis Search index for session listing (fixes #121)#140

Merged
fcenedes merged 7 commits intoredis:mainfrom
fcenedes:Issue-#121
Feb 17, 2026
Merged

Replace sorted sets with Redis Search index for session listing (fixes #121)#140
fcenedes merged 7 commits intoredis:mainfrom
fcenedes:Issue-#121

Conversation

@fcenedes
Copy link
Collaborator

@fcenedes fcenedes commented Feb 6, 2026

Replace sorted sets with Redis Search index for session listing (fixes #121)

Description

Problem

PR #119 fixed a regression where list_sessions() was reading from a sorted set that was never populated. However, using a sorted set for session indexing has a fundamental flaw: when working memory expires via TTL, the session entry remains in the sorted set as a stale/orphaned entry.

This means list_sessions() could return session IDs for sessions that no longer exist.

Solution

Replace the sorted set approach with a Redis Search index on the working memory JSON documents. This ensures that when TTL expires and the key is deleted, Redis Search automatically removes the document from the index - eliminating stale entries.

Changes

New Files:

  • agent_memory_server/working_memory_index.py - Index creation and management functions

Modified Files:

  • agent_memory_server/config.py - Added index configuration settings
  • agent_memory_server/main.py - Create index on startup
  • agent_memory_server/working_memory.py - Rewrote list_sessions() to use FT.SEARCH, removed zadd/zrem calls
  • agent_memory_server/utils/keys.py - Deprecated sessions_key(), added working_memory_index_name()
  • tests/conftest.py - Added working_memory_index fixture
  • tests/test_working_memory.py - Updated tests for search index approach
  • tests/docker-compose.yml - Fixed ARM Mac compatibility

Benefits

✅ No more stale sessions - Expired sessions are automatically removed from the index
✅ Better filtering - Can now filter by user_id in addition to namespace
✅ Consistent behavior - Index is automatically maintained by Redis
Migration
The old sorted set data will naturally age out. No manual migration required.

Testing

All 647 tests pass
Added new tests for search index behavior and user_id filtering

@jit-ci
Copy link

jit-ci bot commented Feb 6, 2026

Hi, I’m Jit, a friendly security platform designed to help developers build secure applications from day zero with an MVS (Minimal viable security) mindset.

In case there are security findings, they will be communicated to you as a comment inside the PR.

Hope you’ll enjoy using Jit.

Questions? Comments? Want to learn more? Get in touch with us.

@fcenedes fcenedes requested a review from abrookins February 6, 2026 17:24
@nkanu17 nkanu17 self-requested a review February 17, 2026 20:34
Copy link
Contributor

@nkanu17 nkanu17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @fcenedes! This is awesome and exactly what we need!

Before we can merge, we need one change. In our project, using RedisVL query types instead of raw execute_command() calls would keep things standardized. This keeps our abstraction layer consistent and makes the code easier to maintain.

Required changes:

  • Index creation: Use redisvl.index.SearchIndex with schema instead of FT.CREATE
  • Search queries: Use redisvl.query.FilterQuery instead of FT.SEARCH
  • Import placement: Move the import in main.py to the top of the file
  • Type hint: Double check all typehints
  • Some other comments regarding WORKING_MEMORY_INDEX_NAME/PREFIX and exceptions

Finally, would you mind adding warnings.warn() to the deprecated sessions_key() method?

@fcenedes
Copy link
Collaborator Author

is this better ?

@fcenedes fcenedes requested a review from nkanu17 February 17, 2026 21:37
Copy link
Contributor

@nkanu17 nkanu17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

Comment on lines +309 to +312
except Exception as e:
logger.error(f"Error listing sessions: {e}")
# Return empty results on error
return 0, []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would prefer not to have silent errors. This can mask real issues, consider using logger.exception() to include the traceback, or re-raise the exception after logging.

Comment on lines 41 to 47
"""Get the sessions key for a namespace.

DEPRECATED: This method is deprecated. Session listing now uses
Redis Search index on working memory JSON documents instead of
sorted sets. The index automatically handles TTL expiration.
"""
return f"sessions:{namespace}" if namespace else "sessions"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: raise a deprecated warning

Comment on lines 19 to 20
WORKING_MEMORY_INDEX_NAME = settings.working_memory_index_name
WORKING_MEMORY_INDEX_PREFIX = settings.working_memory_index_prefix
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to just import it directly something like:
from agent_memory_server.confi.settings import working_memory_index_name

And then use it later on

Returns:
True if index was dropped, False if it didn't exist
"""
index_name = WORKING_MEMORY_INDEX_NAME
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove WORKING_MEMORY_INDEX_NAME and use imported variable

# Calculate start and end indices (0-indexed start, inclusive end)
start = offset
end = offset + limit - 1
from agent_memory_server.working_memory_index import get_working_memory_index
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would move this to the top

@fcenedes fcenedes merged commit d5719b2 into redis:main Feb 17, 2026
25 of 28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace sessions sorted set with Redis Search index

2 participants

Comments