Skip to content

Add an ADR / design doc covering the load-bearing SPI decisions #31

Description

@dkayiwa

Problem

The querystore SPI has a set of conventions that consumers need to learn — patient-scoping contract, voided-row policy, trigger-method matching, lazy-init for provided-scope supertypes, etc. — but the conventions live as inline comments scattered across AbstractIndexingAdvice, AbstractRecordSerializer, QueryDocument, and the existing reference serializers (AllergyRecordSerializer, VisitRecordSerializer, EncounterRecordSerializer, etc.).

A new contributor wanting to add a resource type currently has to:

  1. Read the existing serializers to infer the metadata-shape convention (see Document the metadata-shape contract for ClinicalRecordSerializer / QueryDocument.putMetadata #27).
  2. Read AbstractIndexingAdvice source to understand the per-entity exception swallow (see Per-entity serialize() failures are swallowed at WARN with no metric — silent index drift #29) and trigger-name matching (see Validate AbstractIndexingAdvice TRIGGER_METHODS at bean init against the target service interface #17).
  3. Read omod/config.xml files in existing consumer modules to learn the advice registration pattern.
  4. Read the Spring moduleApplicationContext.xml files in existing consumer modules to learn the lazy-init=\"true\" pattern and why it's required.
  5. Reverse-engineer the patient-scoping contract from getPatientUuid() implementations.

For the billing module's slice we ended up writing a 24-decision ADR for the consumer (openmrs/openmrs-module-billing#176) covering the conventions we discovered. That document is consumer-specific but ~70% of its content is restating SPI-level conventions that would belong in a querystore-level document.

Suggested approach

A docs/adr/ directory in this repo with an initial ADR (or design doc) covering the SPI's load-bearing decisions. Candidates for inclusion:

The billing PR's ADR is a worked example of the format and depth that's useful. A querystore-level version would have prevented several Phase 1 review cycles in our slice and would unblock future contributors.

Failure mode prevented

Without this, every new consumer module rediscovers the conventions by reverse-engineering. The cost is paid in code review cycles, sometimes in production drift (a typo'd trigger method that ships green and surfaces weeks later, a missing lazy-init that breaks a downstream module's tests), and in fragmentation — each consumer ends up with a slightly different interpretation of the SPI's intent.

Related: #16, #17, #18, #27, #28, #29, #30.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions