Phase 6: replace app template with the vet sample domain + jobs slice, pipelines and worker

- templates/app now carries the vet server (parents/pets/treatments/vets/appointments)
- added domain/jobs slice with /jobs OpenAPI paths and Job schema (x- extensions)
- added pipelines/shared scaffold (loader, ports, registry) and the
  appointment_reminder family; worker.py dispatches jobs by kind
- wired init.py, config.py worker knobs, .env.example, docker-compose worker
- unit tests for jobs routes, the pipeline family and worker dispatch (12 passing)
This commit is contained in:
2026-10-20 14:49:10 +05:30
parent 6f6f0d6e6d
commit 56aa1322fb
83 changed files with 2946 additions and 610 deletions

View File

@@ -0,0 +1,3 @@
"""# Summary
Pets domain slice."""

View File

@@ -0,0 +1,37 @@
"""# Summary
Pets domain — animals owned by parents and treated in appointments.
"""
from typing import Literal
from pydantic import BaseModel
from domain.parents.models import Metadata
class Pet(BaseModel):
"""A pet patient.
Attributes:
id (int | None): Server-assigned identifier. Defaults to None.
name (str): Name of the pet.
species (str): Type of animal (dog, cat, bird).
age (int | None): Age in years. Defaults to None.
weight (float | None): Weight in kilograms. Defaults to None.
birthDate (str | None): ISO date of birth. Defaults to None.
photo (str | None): Stored photo path after upload. Defaults to None.
parents (list[dict]): Embedded parent objects (or bare ids on input).
metadata (Metadata | None): Presentation metadata. Defaults to None.
"""
id: int | None = None
name: str
species: Literal["dog", "cat", "bird"]
age: int | None = None
weight: float | None = None
birthDate: str | None = None
photo: str | None = None
parents: list[dict] = []
metadata: Metadata | None = None
model_config = {"extra": "ignore"}

View File

@@ -0,0 +1,3 @@
"""# Summary
Pets domain ports."""

View File

@@ -0,0 +1,25 @@
"""# Summary
Pets persistence ports — integer-id document and repository factory.
"""
from mongo_ops import BaseDocument
from pydantic import Field
from domain.pets.models import Pet
from infra.db.repos import create_repo
class PetDocument(Pet, BaseDocument):
"""Persisted pet document. The integer ``id`` shadows the ObjectId."""
id: int | None = Field(default=None, validation_alias="_id")
def create_pet_repo():
"""Create the pet repository selected by ``settings.repo_backend``.
Returns:
IntIdMemoryRepository | IntIdMongoRepository: Repository wired to the
``pets`` collection/store.
"""
return create_repo("pets", PetDocument)

View File

@@ -0,0 +1,33 @@
"""# Summary
CRUD service wiring for the pet aggregate via the hexa container.
"""
from hexa import build
from domain.pets.models import Pet
from domain.pets.ports.db import PetDocument
from infra.adapters.service import CrudsServiceAdaptor
class PetCrudsService(CrudsServiceAdaptor[Pet, PetDocument]):
"""Pet CRUD service resolving :class:`PetDocument` from a repo.
Notes:
Instances are created by :func:`get_pet_service`. The ``model`` and
``schema`` class attributes bind the domain model and its document type.
"""
model = Pet
schema = PetDocument
def get_pet_service(repo) -> PetCrudsService:
"""Build a pet CRUD service wired to ``repo``.
Args:
repo (Any): Integer-id pet repository from :func:`create_pet_repo`.
Returns:
PetCrudsService: Ready-to-use pet CRUD service.
"""
return build(PetCrudsService, instances={"repo": repo})