rl-docs-hub

Home · Apps · rl-main-infra · todo_api · todo_mobile


Architecture

High-Level Design

todo_api is a monolithic NestJS GraphQL service with modular boundaries for auth, list/item domain logic, and synchronization support.

Runtime Components

Module Topology

graph TD
  A[AppModule] --> B[AuthModule]
  A --> C[SyncModule]
  A --> D[ListsModule]
  A --> E[ItemsModule]

  D --> C
  E --> C
  E --> D

  B --> F[JwtStrategy + Passport JWT]
  C --> G[SyncService]
  D --> H[ListsResolver + ListsService]
  E --> I[ItemsResolver + ItemsService]

Request Lifecycle

flowchart LR
  Client -->|Bearer JWT| GraphQLResolver
  GraphQLResolver --> Guard[GqlAuthGuard]
  Guard --> Strategy[JwtStrategy.validate]
  Strategy -->|user.sub| ResolverMethod
  ResolverMethod --> DomainService
  DomainService --> Mongo[(MongoDB)]
  DomainService --> SyncService
  SyncService --> Mongo
  ResolverMethod --> Response

Auth Model

Domain Behavior

Lists

Items

Sync & Conflict Strategy

Pull side

Push side

Conflict mechanics

Idempotency Strategy

pushChanges optionally accepts idempotencyKey:

  1. Lookup by (ownerId, key)
  2. If found, return previously stored response immediately
  3. If absent, process operations and persist response using upsert ($setOnInsert)

This guarantees replay safety for mobile retries/timeouts without duplicate effects.

Sync Push Execution (Mermaid)

sequenceDiagram
  autonumber
  participant C as Client
  participant R as SyncResolver
  participant S as SyncService
  participant L as ListsService
  participant I as ItemsService

  C->>R: pushChanges(operations, idempotencyKey)
  R->>S: resolveIdempotent(ownerId, key)
  alt key exists
    S-->>R: previous response
    R-->>C: return cached response
  else no record
    loop each operation
      R->>R: parse payload JSON
      alt LIST:UPSERT
        R->>L: create/update (with expectedVersion)
      else ITEM:UPSERT
        R->>I: create/update (with expectedVersion)
      else ITEM:MOVE
        R->>I: move (with expectedVersion)
      else unsupported
        R->>R: append conflict
      end
    end
    R->>S: saveIdempotent(ownerId, key, response)
    R-->>C: SyncPushResult
  end