S19: consume versioned engineering resources and move landscape documentation
All checks were successful
Build, test and publish / verify (push) Successful in 8m54s
All checks were successful
Build, test and publish / verify (push) Successful in 8m54s
This commit is contained in:
182
docs/validation/S16-validation.md
Normal file
182
docs/validation/S16-validation.md
Normal file
@@ -0,0 +1,182 @@
|
||||
> Historical validation evidence from application commit `bd898e92d22f6c412e671908770f4d89c8ae12bc`. Commands retain their original paths; current tooling is documented in README.md.
|
||||
|
||||
# S16 implementation validation
|
||||
|
||||
## Delivered behavior
|
||||
|
||||
PostgreSQL owns normalized school, dancer, coach, group, membership, style, show,
|
||||
daypart, appearance and ordered-assignment tables, plus the latest scheduling run.
|
||||
Flyway V1 creates the schema, persistent identifier sequence, cross-school-safe
|
||||
foreign keys and row constraints. School keys, runtime identifiers, relationship
|
||||
identity, coach links, draft assignments and finalized state survive reload.
|
||||
|
||||
Application persistence uses JPA/Hibernate ORM with mapped entities in
|
||||
`repository.entity` and `EntityManager` repositories. Relationships, element
|
||||
collections, daypart order and orphan removal are managed by Hibernate; domain
|
||||
objects and API responses remain framework independent. The hand-written JDBC
|
||||
query/update layer and row readers have been removed.
|
||||
|
||||
The HTTP interceptor runs each school operation in a short repeatable-read JTA
|
||||
transaction under the existing domain monitor. Reads convert managed entities into
|
||||
detached domain snapshots. Hibernate's school `@Version` checks optimistic changes;
|
||||
a change stamp marks child-only edits so the school revision advances exactly once.
|
||||
Missing or stale caller revisions conflict before applying edits, and stale detached
|
||||
JPA entities also fail. Successful graph merges flush before commit, and status
|
||||
publication remains after durable commit. A single school-data endpoint gives the
|
||||
editor a consistent data/revision snapshot. Open editors retain their original
|
||||
revision across background refreshes; conflict responses preserve their input and
|
||||
require reload before retry. Replacement imports retain the target school ID and
|
||||
check the revision returned by preview. Existing JSON import/export semantics remain.
|
||||
|
||||
Domain-to-view projection now uses MapStruct 1.6.3 in the REST layer. The generated
|
||||
CDI `DomainViewMapper` covers schools, dancers, groups, coaches, dayparts and shows.
|
||||
A shared ID conversion projects relationships to ordered ID lists; validation results
|
||||
remain an explicit argument and preferred-daypart defaults delegate to the existing
|
||||
application rule. View record constructors retain their defensive copies. Entity to
|
||||
domain graph construction remains explicit in the persistence adapter.
|
||||
`unmappedTargetPolicy = ERROR` rejects missing target fields at compilation. A compiler
|
||||
probe with the actual mapper and an added unmapped SchoolView component confirms this
|
||||
failure, without modifying maintained sources. MapStruct's generated implementation
|
||||
is marked `lombok.Generated`, preserving the existing generated-code scope of coverage
|
||||
and architecture checks; handwritten mapper helpers remain covered and checked.
|
||||
|
||||
Flyway remains the schema authority; Hibernate validates rather than generates DDL.
|
||||
V1 is unchanged. V2 preserves existing rows, adds the aggregate change stamp and a
|
||||
JPA-managed identifier counter seeded above previously allocated IDs, and defers
|
||||
date/type uniqueness until commit so Hibernate can reorder retained dayparts safely.
|
||||
Identifier allocation takes a pessimistic lock on the counter row. Coach/dancer and
|
||||
group/coach associations use Hibernate composite join mappings to share the owning
|
||||
school key while letting Hibernate update the linked member column directly.
|
||||
|
||||
Run acceptance checks the school revision and persists the run before launch or
|
||||
acknowledgement. Acceptance itself does not change scheduling inputs. Background
|
||||
computation holds neither a database transaction nor the domain monitor. Progress
|
||||
commits before publication. Successful assignment replacement, school revision and
|
||||
terminal run status commit together; publication callbacks run only after commit.
|
||||
Deferred constraint failures roll back both assignments and status without
|
||||
publishing success. Database failure never falls back to acknowledged memory-only
|
||||
writes. Disconnected status subscribers cannot turn a committed result into a
|
||||
solver failure.
|
||||
|
||||
Startup recovery marks persisted Running runs Interrupted before serving status,
|
||||
retains their IDs, progress and previous saved assignments, and creates no old run
|
||||
guards. The frontend recognizes Interrupted and retains S12's reconnect/reload
|
||||
notification behavior. Timestamps use PostgreSQL microsecond precision consistently
|
||||
in live and recovered snapshots.
|
||||
|
||||
## Verification
|
||||
|
||||
- Maven clean verify: all 72 backend tests and 19 standards-checker regression tests
|
||||
pass. The JPA integration run also verified Flyway V1 and V2 and Hibernate schema
|
||||
validation against an empty database, as well as an upgrade of the populated V1
|
||||
test database.
|
||||
- Backend line coverage: 1763/1827 (96.50%), above the 80% gate.
|
||||
- Frontend: 32 unit tests, production build and ESLint pass (unchanged by the
|
||||
MapStruct-only backend change).
|
||||
- Generated-mapper CDI tests cover ordered relationship IDs, an unlinked coach,
|
||||
nested assignment order, defensive copies, explicit validation messages and the
|
||||
configured/default preferred-daypart rule. The compile-time unmapped-field probe
|
||||
passes with the expected compiler error.
|
||||
- Playwright: the three existing real REST/browser scenarios pass with PostgreSQL;
|
||||
a fourth scenario verifies two screens editing the same revision, conflict
|
||||
handling with retained form input, and successful reload/retry.
|
||||
- PostgreSQL tests cover simultaneous edits (one succeeds, one conflicts), missing
|
||||
revisions, relational graph recovery, IDs and ordered assignments, finalized
|
||||
state, deferred commit failure without success publication, failed replacement
|
||||
import rollback, stale scheduling inputs and interrupted-run recovery. JPA-specific
|
||||
tests verify stale detached entities, exactly one aggregate version increment for
|
||||
child-only edits, and reordered dayparts retaining their assignments.
|
||||
- `tooling/persistence/restart_test.py` runs the packaged production backend against
|
||||
an isolated persistent PostgreSQL container. It passes graceful restart and
|
||||
SIGKILL interruption checks, verifies a completed saved result after every
|
||||
restart, checks stable recovered IDs through HTTP and SSE, starts a new run after
|
||||
interruption, rejects mutations during a database outage, and verifies startup
|
||||
failure for an unreachable database and a deliberately failing Flyway migration.
|
||||
- CI helper tests: 17 pass. Release and actual deployment-shell behavior tests:
|
||||
32 pass. Shell syntax and Java/frontend formatting checks pass.
|
||||
|
||||
The packaged-process checks deliberately stop/restart only the named disposable
|
||||
test database. Production deployment was not performed. Database provisioning and
|
||||
transition instructions are in `docs/persistent-storage.md`; export every school
|
||||
before stopping the old in-memory release. Production Compose retains its database
|
||||
volume outside application replacement. CI supplies a separate disposable browser
|
||||
database and removes its anonymous volume during cleanup.
|
||||
|
||||
## Manual standards assessment
|
||||
|
||||
No waivers or weaker gates were added. Architecture tests pass. Persistence entities
|
||||
and their embeddable keys belong to the repository layer, while the scheduling
|
||||
records remain in `model.scheduling`. Mutable classes, no-argument construction,
|
||||
setters and replaceable collections are deliberate JPA lifecycle requirements;
|
||||
Hibernate installs managed collection wrappers and hydrates fields. Composite key
|
||||
values are assigned before persistence and are not mutated afterward. None of these
|
||||
entities or lazy collections escapes into the solver or the API. Existing immutable
|
||||
snapshot records still defensively copy mutable collections.
|
||||
|
||||
Retained review signals in changed code:
|
||||
|
||||
- Database fan-out 27 and transaction cyclomatic complexity 8: JPA/JTA lifecycle,
|
||||
rollback and heuristic failures, optimistic-conflict classification, and committed
|
||||
publication are handled in one transaction owner. Its two injected dependencies
|
||||
remain below the review signal.
|
||||
- SchoolWriter fan-out 17: one adapter builds and merges the school graph, removes
|
||||
deleted-show statuses, checks JPA revisions and flushes changes. PeopleMapping,
|
||||
GroupMapping and ShowMapping separate domain conversion from ORM lifecycle.
|
||||
- Entity fan-out reflects explicit relationship and collection annotations:
|
||||
DayPartEntity 22, GroupEntity 24, RunEntity 17, SchoolEntity 18 and ShowEntity 23.
|
||||
Each maps one existing table/aggregate boundary; splitting fields merely to lower
|
||||
annotation-driven fan-out would obscure the relational mappings. Entity collections
|
||||
are mutable only within the persistence adapter and Hibernate session.
|
||||
- SchoolTransactions fan-out 19 and request cyclomatic complexity 9: four collaborators
|
||||
cover the detached domain monitor, transaction owner, loader and writer. The branch
|
||||
structure distinguishes reads, run acceptance and domain mutations and maps storage
|
||||
failures separately from optimistic conflicts. SchoolChange's four components
|
||||
keep the revision and operation classification together.
|
||||
- SchedulingRuns fan-out 31: it coordinates immutable input/progress/run/result
|
||||
records, the solver port, durable lifecycle operations and subscriber callbacks;
|
||||
its three injected collaborators remain below the dependency review signal.
|
||||
- SchoolManagementService fan-out 38, 30 public methods, beginScheduling
|
||||
cyclomatic complexity 8 and the existing five-parameter updateShow are retained:
|
||||
aggregate use cases and validations remain together. Load installs detached state
|
||||
and resets transient input counters under the existing monitor.
|
||||
- REST resource fan-out is 18–28 (DanceSchoolResource 25): resources combine HTTP
|
||||
annotations, use cases, request/view contracts and the injected projection mapper.
|
||||
The consistent data endpoint assembles views inside the transaction. DomainViewMapper
|
||||
fan-out 25 represents six explicit source/target projections plus the MapStruct
|
||||
annotations and two small shared helpers. DomainViewMapperTest fan-out 22 exercises
|
||||
the generated CDI mapper's API edge cases. SchoolView's six components include the revision;
|
||||
SchoolDataView's five components represent one editor snapshot. ImportPreview's
|
||||
seventh component identifies the target revision for replacement.
|
||||
- PersistenceTest fan-out 47, seven injected fixtures, 335 code lines and methods of
|
||||
41/33/42 lines: these cross real ORM, graph and transaction boundaries, including
|
||||
detached-entity conflicts, commit-time failure, failed import, child versioning and
|
||||
reordered assignments. The fixtures remain below all blocking limits. Existing
|
||||
changed REST/SSE/background fixture metrics retain their S12/S7 rationale.
|
||||
|
||||
One active backend remains the supported deployment model. Global execution
|
||||
capacity, distributed workers, database backup/restore and recovery after database
|
||||
volume loss remain outside S16. S17 owns backup/restore.
|
||||
|
||||
## Review follow-up: database recovery during calculation
|
||||
|
||||
Terminal scheduling outcomes whose transaction fails remain pending in their worker.
|
||||
The worker retries storage once per second without holding the school monitor between
|
||||
attempts, retaining its run guard until the terminal status commits. Publication still
|
||||
happens only after commit. Shutdown interrupts the wait; startup recovery remains
|
||||
responsible for persisted Running statuses after a process restart. If the show was
|
||||
removed during the outage, the pending outcome is discarded rather than recreating
|
||||
its status. The finish method's cognitive complexity 12 and cyclomatic complexity 8 distinguish
|
||||
retryable storage failures, removed shows and shutdown; these lifecycle decisions
|
||||
stay in the run owner. SchedulingRuns fan-out is now 34 and its test fixture fan-out
|
||||
35: the added storage exception, interruption handling and outage fixture belong to
|
||||
this existing persistence lifecycle boundary.
|
||||
|
||||
The regression test simulates unavailable storage during result persistence, verifies
|
||||
that no terminal status is published prematurely and duplicate starts remain rejected,
|
||||
then restores storage without restarting the backend and checks the stable run ID,
|
||||
persisted failure status and released guard. Public transaction/callback documentation
|
||||
now specifies transaction ownership, callback timing and exception behavior.
|
||||
|
||||
Follow-up verification: clean Maven verify against PostgreSQL passes all 73 backend
|
||||
tests and 19 standards-checker tests. Standards and the coverage gate pass;
|
||||
backend line coverage is 1769/1841 (96.09%).
|
||||
Reference in New Issue
Block a user