feat: catalog shared contracts (Tasks 1-4)
Task 1: Establish catalog identity and atomic file ownership - CatalogService, CatalogServiceInterface, ModelMetadata DTO - PdoCatalogRepository with atomic operations, savepoint support - FOR UPDATE file locks in ascending order, FOR NO KEY UPDATE for metadata - FK-compatible lock composition documented (spec §6) Task 2: M3 import & indexing engine delivery layer - ImportService, ImportWorker with durable collision handling - SpaceChecker, StreamingHasher, VerifiedCopier, StlValidator - FileEnumerator, LocalFilesystem, PathSafety - Console command wiring via ContainerWiringTest Task 3: Importer integration and repair - LegacyGuessedImportGroupingAdapter isolates first-directory guessing - ImportService uses adapter; ImportWorker uses CatalogServiceInterface - Null owners remain null; DomainException mapped to CATALOG_CONFLICT - SQL failure after registration/path update with caller sentinel rollback Task 4: PostgreSQL contention evidence and bounded acceptance - 6 new PostgresCatalogContractsTest cases with independent sessions - Generated schemas, 250ms lock timeouts, 5s statement timeouts - Ascending file locks, FOR SHARE contention, stale-owner rejection - Rollback/retry, nested transaction survival, root creation contention - Negative controls: replay FOR UPDATE removal (11 failures), metadata FOR UPDATE (4 FK KEY SHARE timeouts) - Fresh Docker PostgreSQL 17 / PHP 8.4.26: 473 tests, 2718 assertions, 10 skips, exit 0 All local: 474 tests, 2347 assertions, 54 skips, foundation/lint clean.
This commit is contained in:
1 parent
6b9fb54b4f
commit
a829d6e8c6
21 files changed
+1903
-61
No files matched your search
+30
-3
@@ -80,12 +80,39 @@ changes; issue states were rechecked through the live API afterward.
|
||||
| #25 | Queue/worker/locking exist; confirmed grouping and full replay/retry guarantees remain incomplete. |
|
||||
| #26 | Repository progress exists; caller-facing polling, full state distinctions and worker handling of empty jobs remain incomplete. |
|
||||
| #27 | Failures persist; supported retry with attempt history and persisted-message redaction remain incomplete. |
|
||||
| #28 | Bounded identity, explicit expected-owner reassignment and catalog-owned savepoint transactions are implemented with local/PG evidence above; whole-slice review approved, but broader metadata/lifecycle contracts remain open. Not complete. |
|
||||
| #28 | Identity/aggregate baseline plus shared importer, raw expected-metadata and status contracts are implemented in the uncommitted shared-contracts slice. Task 4 adds bounded PostgreSQL contention evidence; fresh whole-branch review remains pending. Explicit confirmed import grouping is not implemented. Not complete. |
|
||||
|
||||
## Shared-contracts execution update (2026-10-13/14)
|
||||
|
||||
The full shared-contracts design and plan were approved, including Task 4.
|
||||
Local PHP 8.3.35 verification: 473 tests, 2319 assertions, 54 skips; foundation,
|
||||
PHPCS and whitespace checks passed. Skipped PostgreSQL tests are not local lock
|
||||
evidence. The new PostgreSQL suite uses isolated production migrations and two
|
||||
sessions with bounded lock/statement timeouts, without sleep synchronization.
|
||||
Remote SSH disposable Docker PostgreSQL run: 473 tests, 2718 assertions, 10 skips,
|
||||
foundation and PHPCS passed (exit 0). Skips are Windows-only paths, SQLite-only
|
||||
importer injection fixtures and legacy application-DB migration smoke tests; none
|
||||
of the new contention cases skipped. Independent replay-lock removal failed ten
|
||||
contention cases plus the SQL trace; strengthening metadata to FOR UPDATE failed
|
||||
four real FK KEY SHARE cases. Restored source passed the full suite and lint.
|
||||
Exact source hashes/logs are recorded in the Task 4 execution report. Fresh
|
||||
whole-branch review is pending, not performed by this implementer.
|
||||
|
||||
Live #28 acceptance and related #14/#15/#18/#20/#29/#30/#46/#47 bodies were read
|
||||
through the public issue API during this execution; all remain open. #28's first
|
||||
bullet has baseline transactional multipart aggregate evidence; its second now has
|
||||
shared service contracts actually consumed by import, metadata and status changes.
|
||||
Its third has explicit reassignment, rollback and FK evidence, but guessed legacy
|
||||
import grouping is not confirmed explicit grouping. #14/#15/#18 dependencies are
|
||||
not waived. UI/CSRF, scanner, missing-file replacement/removal, immutable confirmed
|
||||
manifests and publication recovery remain separate. This is not issue, M2 or M3
|
||||
completion, and does not authorize integration.
|
||||
|
||||
## Important implementation findings
|
||||
|
||||
- `ImportService::group()` guesses associations from the first directory component.
|
||||
`ensureModel()` reuses folder/name identities. Neither is user confirmation.
|
||||
- `LegacyGuessedImportGroupingAdapter` now isolates the importer's first-directory
|
||||
association guessing. `ensureModel()` reuses folder/name identities. Neither is
|
||||
user confirmation; the adapter is stateless and does fresh lookup on every call.
|
||||
The M3 ledger's directory-grouping decision does not supersede live #20 criteria.
|
||||
- The scanner retains relative paths, but job creation discards them. The worker
|
||||
constructs destinations from a model folder and basename, flattening deeper paths.
|
||||
|
||||
Reference in new issue
Block a user