hyperswitch icon indicating copy to clipboard operation
hyperswitch copied to clipboard

feat(users): store and retrieve lineage_context from DB instead of Redis

Open tsdk02 opened this issue 7 months ago • 1 comments

Type of Change

  • [ ] Bugfix
  • [x] New feature
  • [x] Enhancement
  • [x] Refactoring
  • [ ] Dependency updates
  • [ ] Documentation
  • [ ] CI/CD

Description

Previously, the user's lineage_context (userid, org_id, merchant_id, profile_id, role_id, tenant_id) was cached in Redis. This PR moves the storage and retrieval of lineage_context to the PostgreSQL users table instead of Redis.

This ensures permanent persistence of lineage_context in DB, as opposed to the 7 days TTL when stored in Redis.

Key Changes

  • Schema Change:

    • Added lineage_context as a JSONB column in the users table.
  • During Login:

    • Attempt to fetch lineage_context from DB (users.lineage_context).
    • If present:
      • Validate the context by checking if a matching user role exists (checks both v1 and v2 user roles).
      • If valid → use it for JWT generation.
      • If not → fallback to default DB-based role resolution.
    • If not present → fallback directly to default role resolution.
    • DB update for the new lineage context is now done via tokio::spawn to avoid blocking response.
  • During Org/Merchant/Profile Switch:

    • After switching, the new lineage_context is serialized and persisted in the users table.
    • This enables restoring the last used context during the next login.
    • The update is done in the background using tokio::spawn with success and failure logs.
  • Error Handling:

    • All DB failures or deserialization errors are logged.
    • Failures do not interrupt the login/switch flow — safe fallback ensures continuity.

Additional Changes

  • [ ] This PR modifies the API contract
  • [x] This PR modifies the database schema
  • [ ] This PR modifies application configuration/environment variables

Motivation and Context

By moving the lineage_context to the users table in DB:

  • We ensure the context is consistently available regardless of deployment environment.
  • The last used account context becomes part of the user's persistent record.
  • It simplifies logic and avoids prefix mismatches across tenants.

How did you test it?

Screenshot 2025-04-29 at 11 45 43 PM

image

Test Case 1: Lineage Context Caching on Login

  1. Log in as a user with an assigned role.
  2. Check that lineage_context is stored in the users table (PostgreSQL).
  3. Log out and log back in → verify that the JWT reflects the same org/merchant/profile context without role fallback.

Test Case 2: Lineage Context Update on Org/Profile Switch

  1. Log in as a user and switch to another org/merchant/profile.
  2. Confirm that the updated context is persisted in the lineage_context field in the DB.
  3. Log out and log in again → JWT should reflect the newly switched context.

Test Case 3: Fallback to Role Resolution upon clearing lineage_context in db (Tested on local)

  1. Manually removed lineage_context from the DB for a user.
  2. Logged in again → verified that the system correctly falls back to the default role resolution logic.
  3. Confirm that the context is repopulated in the DB after login.

Test Case 4: Fallback to Role Resolution upon deleting user_role (Tested on local)

  1. Manually deleted user_role from the DB for a user (user_role corresponds to user invited to another account)
  2. Tried to log in again → verified that the system correctly falls back to the default role resolution logic.
  3. Confirm that the context is repopulated in the DB after login.

Checklist

  • [x] I formatted the code cargo +nightly fmt --all
  • [x] I addressed lints thrown by cargo clippy
  • [x] I reviewed the submitted code
  • [ ] I added unit tests for my changes where possible

tsdk02 avatar Apr 29 '25 19:04 tsdk02