Skip to content

Guidance (or support) for async invariants — uniqueness-style rules #39

Description

@btravers

Problem

Invariants are synchronous predicates over the declared fields. Rules like "slug not already taken" need I/O, and the package's no-I/O stance rightly keeps them out of invariants — but nothing says where they belong, so every adopter re-derives the answer. This is a recurring first-week question for exactly the DDD audience the library targets.

Proposal (docs first, API only if it earns it)

  1. Documentation: an explanation section (or how-to) stating the rule: an invariant is a closed-world fact about the entity's own data; open-world rules (uniqueness, referential existence, quota) are use-case preconditions, checked at the composition root where the repository lives — with a worked example (check-then-create, and what to do about the race: DB constraint + mapping the violation back to an InvalidEntity-shaped response).
  2. Optionally, a thin composition helper for that pattern at the use-case layer — e.g. an AsyncResult-returning precondition combinator that collects failures in the same issues shape, so the HTTP layer renders domain and use-case failures uniformly (Entity.renderIssue / Entity.keysOf already cover the rendering half).

Non-goal: factoryAsync-style async predicates inside the entity declaration — that would put I/O behind a pure-looking construction path and break the "a rejecting generator is a Defect" symmetry.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions