Skip to content

feat: Adds CRUD operations to CacheAdapters and implements initial SessionManager (part 1: Adapter level)#2077

Merged
hajdul88 merged 40 commits intodevfrom
feature/cog-3879-enable-crud-in-session-and-implement-sessionmanager
Feb 9, 2026
Merged

feat: Adds CRUD operations to CacheAdapters and implements initial SessionManager (part 1: Adapter level)#2077
hajdul88 merged 40 commits intodevfrom
feature/cog-3879-enable-crud-in-session-and-implement-sessionmanager

Conversation

@hajdul88
Copy link
Collaborator

@hajdul88 hajdul88 commented Feb 2, 2026

Description

Taks:
This PR adds CRUD operations and a centralized SessionManager to manage session QAs. Each QA now has a stable ID and can store optional feedback. The goal is to make session data easier to work with and prepare the ground for future feedback-related features, without changing existing behavior.

PR:
This PR is the first part of the implementation containing the FS and Redis adapter level logic. Due to the size of the PR the rest of the implementation can be found in #2082

Acceptance Criteria

  • The solution is backward compatible with the current session management
  • SessionManager provides full CRUD for session QAs.
  • Stored QAs include qa_id and feedback_text / feedback_score fields.
  • Create: New QAs are stored with a generated qa_id; existing “save after search” behavior is unchanged.
  • Read: Session QAs can be fetched by user_id and session_id, with optional last_n; responses include qa_id and feedback fields when present.
  • Update: A QA can be updated by user_id, session_id, and qa_id without losing any existing QA data.
  • Delete: A single QA or an entire session can be deleted; cache keys and layout remain consistent.
  • Cache interfaces and adapters are extended only where necessary; existing contracts are preserved or explicitly migrated.
  • Tests cover SessionManager CRUD and Adapter changes, and existing session-related flows continue to pass.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Code refactoring
  • Performance improvement
  • Other (please specify):

Screenshots/Videos (if applicable)

None

Pre-submission Checklist

  • I have tested my changes thoroughly before submitting this PR
  • This PR contains minimal changes necessary to address the issue/feature
  • My code follows the project's coding standards and style guidelines
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if applicable)
  • All new and existing tests pass
  • I have searched existing PRs to ensure this change hasn't been submitted already
  • I have linked any relevant issues in the description
  • My commits have clear and descriptive messages

DCO Affirmation

I affirm that all code in every commit of this pull request conforms to the terms of the Topoteretes Developer Certificate of Origin.

Summary by CodeRabbit

  • New Features

    • Full CRUD for cached conversation Q&A: create, update, delete entries; clear per-session feedback; delete entire sessions; prune/clear cache.
    • Validation for feedback scores (must be 1–5).
  • Improvements

    • Backward-compatible wrappers for legacy cache APIs; more consistent behavior across cache backends and stronger error handling.
  • Tests

    • New unit and end-to-end tests covering cache CRUD, validation, and prune behavior.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 2, 2026

Walkthrough

Adds a SessionQAEntry model and extends the cache layer with full session QA CRUD (create/read/update/delete), feedback fields, validation, and prune support. Redis and filesystem adapters implement the new API; cache interface updated with backward-compatible wrappers; tests and prune integration updated.

Changes

Cohort / File(s) Summary
Public API / Exports
cognee/infrastructure/databases/cache/__init__.py
Exported SessionQAEntry in cache package public API.
Session QA Model & Exceptions
cognee/infrastructure/databases/cache/models.py, cognee/infrastructure/databases/exceptions/exceptions.py, cognee/infrastructure/databases/exceptions/__init__.py
Added SessionQAEntry Pydantic model (time, qa_id, feedback_text, feedback_score) with feedback_score validator; added SessionQAEntryValidationError and re-exported it.
Cache Interface
cognee/infrastructure/databases/cache/cache_db_interface.py
Introduced create_qa_entry, get_latest_qa_entries, get_all_qa_entries, update_qa_entry, delete_feedback, delete_qa_entry, delete_session, prune; retained legacy add_qa, get_latest_qa, get_all_qas as wrappers; added uuid import for qa_id generation.
Filesystem Adapter
cognee/infrastructure/databases/cache/fscache/FsCacheAdapter.py
Replaced legacy add/get methods with create/get_* variants; implemented update, delete_feedback, delete_qa_entry, delete_session, prune; validate via SessionQAEntry; improved error handling and updated variable names (cache_directory).
Redis Adapter
cognee/infrastructure/databases/cache/redis/RedisAdapter.py
Renamed add/get methods to create_qa_entry/get_*; implemented update, delete_feedback, delete_qa_entry, delete_session, prune; serialize via SessionQAEntry.model_dump(), validate entries, raise SessionQAEntryValidationError on invalid data.
Prune Integration
cognee/modules/data/deletion/prune_system.py
On cache branch, added cache clearing and invocation of cache_engine.prune() when caching/usage_logging enabled.
Tests — FsCache
cognee/tests/unit/infrastructure/databases/cache/test_fs_adapter_crud.py
Added unit tests covering create, read, update (including validation), delete_feedback, delete_qa_entry, delete_session, prune, and backward-compatible wrappers.
Tests — Redis
cognee/tests/unit/infrastructure/databases/cache/test_redis_adapter_crud.py
Added unit tests with in-memory Redis mock covering same CRUD flows, validation, prune, and backward-compatibility.
E2E Test Update
cognee/tests/test_usage_logger_e2e.py
Adjusted MCP logging test to assert 5 logs before prune and a single "MCP prune" log after prune; removed earlier sleep/prune ordering.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • lxobr
  • pazone
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 74.32% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding CRUD operations to CacheAdapters and implementing SessionManager at the adapter level.
Description check ✅ Passed The PR description is well-structured and addresses all template sections: clear description of changes, acceptance criteria with specific requirements, type of change marked, pre-submission checklist completed, and DCO affirmation provided.
Linked Issues check ✅ Passed All major coding requirements from COG-3879 are addressed: SessionManager model (SessionQAEntry) created with qa_id and feedback fields; create/read/update/delete operations implemented in adapters; backward compatibility maintained through wrapper methods; unit tests added for CRUD operations.
Out of Scope Changes check ✅ Passed All changes align with the stated scope (adapter-level CRUD implementation for part 1). The prune_system.py integration and test_usage_logger_e2e.py updates directly support the new cache pruning functionality introduced by the adapters.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/cog-3879-enable-crud-in-session-and-implement-sessionmanager

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@hajdul88 hajdul88 marked this pull request as draft February 2, 2026 13:42
@hajdul88 hajdul88 self-assigned this Feb 2, 2026
@pull-checklist
Copy link

pull-checklist bot commented Feb 2, 2026

Please make sure all the checkboxes are checked:

  • I have tested these changes locally.
  • I have reviewed the code changes.
  • I have added end-to-end and unit tests (if applicable).
  • I have updated the documentation and README.md file (if necessary).
  • I have removed unnecessary code and debug statements.
  • PR title is clear and follows the convention.
  • I have tagged reviewers or team members for feedback.

@hajdul88 hajdul88 changed the title feat: Adds CRUD operations to CacheAdapters and implements initial SessionManager) WIP feat: Adds CRUD operations to CacheAdapters and implements initial SessionManager (WIP) Feb 2, 2026

logs_after_prune = await cache_engine.get_usage_logs("unknown", limit=50)
mcp_logs_after_prune = [log for log in logs_after_prune if log.get("type") == "mcp_tool"]
assert len(mcp_logs_after_prune) == 1, (
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This test needed to be changed due to the introduction of prune in Redis and FS adapters. Prune now deletes the corresponding cache as well therefore the mcp tool usage logs didn't match

@hajdul88 hajdul88 changed the title feat: Adds CRUD operations to CacheAdapters and implements initial SessionManager (WIP) feat: Adds CRUD operations to CacheAdapters and implements initial SessionManager (part 1.) (WIP) Feb 3, 2026
@hajdul88 hajdul88 changed the title feat: Adds CRUD operations to CacheAdapters and implements initial SessionManager (part 1.) (WIP) feat: Adds CRUD operations to CacheAdapters and implements initial SessionManager (part 1: Adapter level) (WIP) Feb 3, 2026
@hajdul88 hajdul88 marked this pull request as ready for review February 3, 2026 15:23
@hajdul88 hajdul88 changed the title feat: Adds CRUD operations to CacheAdapters and implements initial SessionManager (part 1: Adapter level) (WIP) feat: Adds CRUD operations to CacheAdapters and implements initial SessionManager (part 1: Adapter level) Feb 3, 2026
@hajdul88 hajdul88 requested a review from lxobr February 3, 2026 15:30
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@cognee/infrastructure/databases/cache/fscache/FsCacheAdapter.py`:
- Around line 101-145: The update_qa_entry (and similarly delete_feedback and
delete_qa_entry) currently calls cache.set(..., expire=86400) which overwrites
the original TTL; change each to read the existing TTL for session_key (e.g.,
ttl = self.cache.ttl(session_key) or equivalent), and when calling
cache.set(...) pass the existing ttl if >0, omit/use None for no-expiry (ttl ==
-1 or None depending on client), and treat ttl <=0 as expired (return False) —
ensure you use session_key, cache.get, cache.ttl and cache.set to preserve the
original expiration semantics instead of hard-coding 86400.

In `@cognee/infrastructure/databases/cache/redis/RedisAdapter.py`:
- Around line 273-301: The delete_qa_entry implementation currently deletes and
rebuilds the Redis list which drops any TTL; before calling delete(session_key)
capture the key's TTL via await self.async_redis.ttl(session_key), then after
rebuilding the list call await self.async_redis.expire(session_key, ttl) if ttl
and ttl > 0 to restore expiry. Update the logic in delete_qa_entry (where
session_key is built and entries are popped/re-pushed) to store ttl, perform the
delete and rpush loop as-is, and then restore expiry using expire when ttl is
positive; preserve existing exception handling.
- Around line 396-401: The close method in RedisAdapter currently only closes
self.async_redis and can leak the synchronous client; after awaiting
self.async_redis.aclose() inside the try block (and even if that raises),
call/ensure self.sync_redis.close() is invoked to close the sync client—use the
existing logger to debug any exceptions from both closures (e.g., wrap sync
close in its own try/except or add a finally that calls
self.sync_redis.close()), referencing the RedisAdapter.close method and the
async_redis and sync_redis attributes.

In `@cognee/tests/unit/infrastructure/databases/cache/test_redis_adapter_crud.py`:
- Around line 70-79: The test assumes non-string feedback_text will raise, but
Pydantic v2 coerces ints to strings; either make SessionQAEntry.feedback_text
strict by adding a field_validator(..., mode='strict') on
SessionQAEntry.feedback_text to reject non-str inputs, or update
test_update_invalid_raises to stop expecting an exception for feedback_text:
call adapter.update_qa_entry("u1","s1","id1", feedback_text=5), then retrieve
the entry (e.g., via adapter.get_qa_entry or the adapter's read method) and
assert the stored feedback_text equals the coerced string "5" instead of using
pytest.raises.
🧹 Nitpick comments (4)
cognee/infrastructure/databases/cache/models.py (1)

11-11: Minor docstring inconsistency.

The docstring states qa_id is "required for update/delete", but the field is declared as Optional[str] = None (line 23). Consider updating the docstring to clarify that qa_id is optional during creation but required for update/delete operations.

cognee/tests/test_usage_logger_e2e.py (1)

224-224: Consider reducing or documenting long sleep durations.

The 30-second asyncio.sleep calls (lines 224 and 236) make this test slow. If these are necessary for the cognify operation to complete, consider adding a brief comment explaining why, or exploring whether a shorter timeout with polling could achieve the same result.

cognee/tests/unit/infrastructure/databases/cache/test_redis_adapter_crud.py (1)

9-16: Add short docstrings to the in-memory Redis mock methods.
These helper methods are currently undocumented; a brief one-liner per method would satisfy the project’s docstring convention.

As per coding guidelines: "As a general rule, undocumented function definitions and class definitions in the project's Python code are assumed incomplete. Please consider suggesting a short summary of the code for any of these incomplete definitions as docstrings when reviewing."

cognee/infrastructure/databases/cache/fscache/FsCacheAdapter.py (1)

22-33: Add a short __init__ docstring.
It would help document the cache directory layout and diskcache initialization.

As per coding guidelines: "As a general rule, undocumented function definitions and class definitions in the project's Python code are assumed incomplete. Please consider suggesting a short summary of the code for any of these incomplete definitions as docstrings when reviewing."

@hajdul88 hajdul88 marked this pull request as draft February 3, 2026 16:11
@hajdul88 hajdul88 marked this pull request as ready for review February 3, 2026 17:41
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
cognee/infrastructure/databases/cache/fscache/FsCacheAdapter.py (1)

47-84: ⚠️ Potential issue | 🟠 Major

Add explicit ValidationError handling to create_qa_entry for correct error semantics.

The method wraps a Pydantic ValidationError as CacheConnectionError, misclassifying input validation failures as infrastructure errors. The sibling methods update_qa_entry and delete_feedback correctly map this to SessionQAEntryValidationError. Apply the same pattern here.

Proposed fix
         except Exception as e:
+        except ValidationError as e:
+            raise SessionQAEntryValidationError(
+                message=f"Session QA entry validation failed during create_qa_entry operation: {e!s}"
+            ) from e
+        except Exception as e:
             error_msg = f"Unexpected error while adding Q&A to diskcache: {str(e)}"
             logger.error(error_msg)
             raise CacheConnectionError(error_msg) from e

Also consider adding a docstring to create_qa_entry (see update_qa_entry at line 111 for the pattern).

cognee/infrastructure/databases/cache/redis/RedisAdapter.py (1)

119-156: ⚠️ Potential issue | 🟠 Major

Add explicit ValidationError handling in create_qa_entry to distinguish validation failures from connection errors.

The method constructs SessionQAEntry without explicitly catching ValidationError. Invalid data (e.g., feedback_score outside 1–5 range) gets caught by the generic exception handler and mislabeled as CacheConnectionError. Add a ValidationError catch block before the generic handler, matching the pattern in update_qa_entry.

Suggested fix
         except (redis.ConnectionError, redis.TimeoutError) as e:
             error_msg = f"Redis connection error while adding Q&A: {str(e)}"
             logger.error(error_msg)
             raise CacheConnectionError(error_msg) from e
+        except ValidationError as e:
+            raise SessionQAEntryValidationError(
+                message=f"Session QA entry validation failed during create_qa_entry operation: {e!s}"
+            ) from e
         except Exception as e:
             error_msg = f"Unexpected error while adding Q&A to Redis: {str(e)}"
             logger.error(error_msg)
             raise CacheConnectionError(error_msg) from e

@lxobr lxobr requested review from lxobr and removed request for lxobr February 6, 2026 14:49
Copy link
Collaborator

@lxobr lxobr left a comment

Choose a reason for hiding this comment

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

Nice work, looks good to me.

@hajdul88 hajdul88 merged commit f70ad68 into dev Feb 9, 2026
134 of 138 checks passed
@hajdul88 hajdul88 deleted the feature/cog-3879-enable-crud-in-session-and-implement-sessionmanager branch February 9, 2026 11:41
hajdul88 added a commit that referenced this pull request Feb 9, 2026
…ssionManager (part 2: Session Manager) (#2082)

<!-- .github/pull_request_template.md -->

Taks:
This PR adds CRUD operations and a centralized SessionManager to manage
session QAs. Each QA now has a stable ID and can store optional
feedback. The goal is to make session data easier to work with and
prepare the ground for future feedback-related features, without
changing existing behavior.

PR:
This PR is the second and final part of the session manager
implemenation. Due to the size of the PR the rest of the implementation
can be found in #2077

Acceptance Criteria
SessionManager provides full CRUD for session QAs.
Stored QAs include qa_id and feedback_text / feedback_score fields.
Create: New QAs are stored with a generated qa_id; existing “save after
search” behavior is unchanged.
Read: Session QAs can be fetched by user_id and session_id, with
optional last_n; responses include qa_id and feedback fields when
present.
Update: A QA can be updated by user_id, session_id, and qa_id without
losing any existing QA data.
Delete: A single QA or an entire session can be deleted; cache keys and
layout remain consistent.
Cache interfaces and adapters are extended only where necessary;
existing contracts are preserved or explicitly migrated.
Tests cover SessionManager CRUD and Adapter changes, and existing
session-related flows continue to pass.

## Type of Change
<!-- Please check the relevant option -->
- [ ] Bug fix (non-breaking change that fixes an issue)
- [x] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Code refactoring
- [ ] Performance improvement
- [ ] Other (please specify):

## Screenshots/Videos (if applicable)
<!-- Add screenshots or videos to help explain your changes -->

## Pre-submission Checklist
<!-- Please check all boxes that apply before submitting your PR -->
- [x] **I have tested my changes thoroughly before submitting this PR**
- [x] **This PR contains minimal changes necessary to address the
issue/feature**
- [x] My code follows the project's coding standards and style
guidelines
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] I have added necessary documentation (if applicable)
- [x] All new and existing tests pass
- [x] I have searched existing PRs to ensure this change hasn't been
submitted already
- [x] I have linked any relevant issues in the description
- [x] My commits have clear and descriptive messages

## DCO Affirmation
I affirm that all code in every commit of this pull request conforms to
the terms of the Topoteretes Developer Certificate of Origin.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Introduced SessionManager to manage user sessions with question-answer
entries and feedback tracking.
* Added operations to add, retrieve, update, and delete QA entries and
sessions with flexible caching support.
  * Enabled formatted session output for seamless prompt integration.

* **Tests**
* Added comprehensive integration tests with filesystem and Redis
caching backends.
* Added unit tests validating session operations and parameter
validation.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: lxobr <122801072+lxobr@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants