Skip to content

Add aexists_full to AtomicRedisModel for complex existence checks #224

Description

@yedidyakfir

Summary

Add an aexists_full class method to AtomicRedisModel that performs a comprehensive existence check across all Redis keys associated with a model instance — including the primary JSON key, special field keys (e.g., priority queues), and inner model keys — and returns a structured result describing what exists and what is missing.

Motivation

The current aexists method only checks whether the primary model key exists in Redis. For complex models with special fields (like RedisPriorityQueue) and inner/nested models, partial state is possible:

  • The main key might exist but a special field key could have expired (TTL mismatch)
  • A special field key might linger after the main key was deleted
  • Inner model data may be inconsistent with the parent

Having a detailed existence check enables better debugging, health monitoring, and data integrity validation.

Features / Details

  • New aexists_full(cls, key: str | Self) -> ExistsFullResult class method on AtomicRedisModel
  • Returns a result model (e.g., ExistsFullResult) with:
    • exists: bool — overall existence (True only if all expected keys exist)
    • model_key_exists: bool — whether the primary JSON key exists
    • special_fields: dict[str, bool] — per special field existence (e.g., {"tasks": True, "events": False})
    • inner_models: dict[str, bool] — per inner/nested model field existence (if applicable)
  • Should work with the pipeline context (_context_pipe) like aexists does
  • Should support both string keys and model instances as input

Use Cases

  • Data integrity checks: Verify a model and all its associated Redis keys are fully present
  • Debugging: Identify which part of a complex model is missing when something goes wrong
  • TTL drift detection: Catch cases where special field keys expire independently from the main model key
  • Cleanup operations: Know exactly what remains before attempting cleanup

Implementation Considerations

  • Follow the same pattern as aexists (classmethod, key resolution via _resolve_key)
  • Use _special_field_names to discover special fields and check their special_key
  • The result model (ExistsFullResult) should be added to rapyer/result.py alongside DeleteResult
  • Consider batching Redis EXISTS calls in a pipeline for performance
  • Inner model existence might require checking JSON path existence rather than separate keys

List tasks

  • Create ExistsFullResult model in rapyer/result.py
  • Implement aexists_full classmethod on AtomicRedisModel in rapyer/base.py
  • Check primary model key existence
  • Check all special field keys existence (iterate _special_field_names)
  • Check inner model field existence if applicable
  • Use pipeline for batching multiple EXISTS calls
  • Add unit tests for aexists_full with various model configurations
  • Add integration tests with real Redis for models with special fields
  • Test edge cases: partial existence, TTL expiry, missing special fields

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions