Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
245ee8d
docs(etl): define immutable durable job replay
seonghobae Aug 6, 2026
9f86566
docs(etl): plan immutable durable job replay
seonghobae Aug 6, 2026
4b4d780
test(etl): require immutable replay lineage migration
seonghobae Aug 6, 2026
b059102
feat(etl): add immutable durable job replay lineage
seonghobae Aug 6, 2026
997dd19
feat(etl): classify immutable durable job replay failures
seonghobae Aug 6, 2026
9af7733
feat(etl): add immutable durable job replay result
seonghobae Aug 6, 2026
fb911df
fix(etl): preserve current replay job status on idempotent retry
seonghobae Aug 6, 2026
104dfa3
feat(etl): create immutable owner-scoped durable job replays
seonghobae Aug 6, 2026
0b60c12
feat(etl): expose immutable durable job replay resource
seonghobae Aug 6, 2026
e36759d
test(etl): cover immutable owner-scoped durable job replay
seonghobae Aug 6, 2026
37a06f5
test(etl): cover immutable durable job replay HTTP contract
seonghobae Aug 6, 2026
48c1bd1
test(etl): cover replay validation and transaction boundaries
seonghobae Aug 6, 2026
2b07e4b
test(etl): prove replay jobs enter ordinary worker lifecycle
seonghobae Aug 6, 2026
35d7734
docs(etl): add immutable durable job replay runbook
seonghobae Aug 6, 2026
f5ac3e3
docs(etl): record durable replay identity domain separation
seonghobae Aug 6, 2026
bf6b645
test(etl): cover replay payload admission limits
seonghobae Aug 6, 2026
821b7ae
test(etl): require immutable replay operations evidence
seonghobae Aug 6, 2026
82d283d
fix(etl): scope problem handling to replay endpoint
seonghobae Aug 6, 2026
a8dedeb
docs(etl): state replay connector safety limitation explicitly
seonghobae Aug 6, 2026
6221b84
docs(etl): align replay design with executable contracts
seonghobae Aug 6, 2026
51b0d13
test(docs): require durable replay changelog evidence
seonghobae Aug 6, 2026
c7900f7
docs(changelog): record durable job replay contract
seonghobae Aug 6, 2026
9a8a1fb
docs(etl): make replay verification plan executable
seonghobae Aug 6, 2026
b5d1928
test(etl): cover replay input decision boundaries
seonghobae Aug 6, 2026
13ba58c
test(etl): cover replay key and lineage integrity branches
seonghobae Aug 6, 2026
59313b7
test(etl): count only created pending replay rows
seonghobae Aug 6, 2026
85a269e
test(etl): cover empty replay batch validation path
seonghobae Aug 6, 2026
d287877
test(ci): require replay coverage diagnostics
seonghobae Aug 6, 2026
3acb00a
ci: diagnose durable replay coverage gaps
seonghobae Aug 6, 2026
954103b
test(etl): cover absent parsed replay root
seonghobae Aug 6, 2026
839fa54
merge: reconcile terminal replay with cancellation predecessor
seonghobae Aug 6, 2026
42da7df
test(etl): require owner-scoped replay lineage foreign keys
seonghobae Aug 6, 2026
c3a9627
fix(etl): enforce owner-scoped replay lineage in PostgreSQL
seonghobae Aug 6, 2026
c18ce76
test(etl): require documented owner-scoped replay lineage
seonghobae Aug 6, 2026
add14d7
docs(etl): document owner-scoped replay lineage constraints
seonghobae Aug 6, 2026
9dac989
docs(etl): specify database-enforced replay tenant lineage
seonghobae Aug 6, 2026
1f4d95d
docs(etl): add replay lineage tenant-integrity plan
seonghobae Aug 6, 2026
cb3340a
docs(changelog): record owner-scoped replay lineage integrity
seonghobae Aug 6, 2026
4f38819
test(etl): require PostgreSQL 18 replay migration rehearsal
seonghobae Aug 6, 2026
b0c719f
docs(etl): add replay standards evidence
seonghobae Aug 7, 2026
01d7b5e
test(etl): verify replay migrations on PostgreSQL
seonghobae Aug 7, 2026
8ad633a
ci(etl): run replay migrations on PostgreSQL 18
seonghobae Aug 7, 2026
aef9d29
test(etl): lock PostgreSQL replay migration workflow
seonghobae Aug 7, 2026
fdff889
docs(adr): record immutable replay lineage
seonghobae Aug 7, 2026
02bc464
test(etl): rehearse replay lineage on PostgreSQL
seonghobae Aug 7, 2026
6682c56
fix(etl): execute replay lineage rehearsal
seonghobae Aug 7, 2026
75cf08f
fix(ci): trigger replay lineage rehearsal changes
seonghobae Aug 7, 2026
7fd11da
fix(test): align replay migration contract
seonghobae Aug 7, 2026
798d46f
fix(test): satisfy terminal lifecycle constraints
seonghobae Aug 7, 2026
73d08ac
fix(test): normalize workflow line endings
seonghobae Aug 7, 2026
f45304d
test(etl): require database-owned replay lineage continuity
seonghobae Aug 7, 2026
15e6891
test(etl): reject replay rows that inherit a non-root root
seonghobae Aug 7, 2026
2057ae8
fix(etl): enforce immutable replay lineage continuity
seonghobae Aug 7, 2026
50bc90b
fix(etl): reject derived rows as replay roots
seonghobae Aug 7, 2026
92a8ad6
test(etl): rehearse replay lineage continuity in PostgreSQL
seonghobae Aug 7, 2026
896ba50
test(etl): align PostgreSQL rehearsal contract with lineage guard
seonghobae Aug 7, 2026
1a796ba
test(etl): require documented database lineage authority
seonghobae Aug 7, 2026
86e118b
docs(etl): plan database-owned replay lineage continuity
seonghobae Aug 7, 2026
d3c4685
docs(etl): define database-owned replay lineage continuity
seonghobae Aug 7, 2026
60d5d47
docs(etl): operate database-owned replay lineage continuity
seonghobae Aug 7, 2026
09a3fd4
docs(etl): trace replay lineage trigger to PostgreSQL standards
seonghobae Aug 7, 2026
038796e
docs(etl): record database-owned replay lineage decision
seonghobae Aug 7, 2026
5d96e5f
docs(etl): record database-owned replay lineage continuity
seonghobae Aug 7, 2026
af523a6
docs(etl): state exact replay-generation progression
seonghobae Aug 7, 2026
6c6137f
test(etl): require exact-head PostgreSQL migration checkout
seonghobae Aug 7, 2026
deac1ab
ci(etl): bind PostgreSQL migration gate to exact PR head
seonghobae Aug 7, 2026
d7d468d
test(etl): require referenced terminal evidence immutability
seonghobae Aug 7, 2026
cdf8c6b
test(etl): require PostgreSQL referenced-evidence immutability rehearsal
seonghobae Aug 7, 2026
1db7bb1
fix(etl): freeze referenced replay evidence
seonghobae Aug 7, 2026
3298634
test(etl): rehearse referenced replay evidence immutability
seonghobae Aug 7, 2026
7f3f16e
docs(etl): define referenced replay evidence immutability
seonghobae Aug 7, 2026
da03560
docs(etl): operate referenced replay evidence immutability
seonghobae Aug 7, 2026
ae74bbc
docs(changelog): record referenced replay evidence guard
seonghobae Aug 7, 2026
4a598aa
docs(adr): freeze referenced replay evidence
seonghobae Aug 7, 2026
45f67c3
test(etl): require deadlock-safe replay trigger lock order
seonghobae Aug 7, 2026
39e406d
test(etl): require concurrent replay lookup indexes
seonghobae Aug 7, 2026
dcfc48c
test(etl): isolate concurrent replay index migrations
seonghobae Aug 7, 2026
99d5cbc
test(etl): require replay digest continuity
seonghobae Aug 7, 2026
d0b2e35
fix(etl): serialize immutable replay evidence safely
seonghobae Aug 7, 2026
05179e7
perf(etl): index replay source lookups concurrently
seonghobae Aug 7, 2026
4035319
build(etl): run replay source index outside transaction
seonghobae Aug 7, 2026
75d6e6a
perf(etl): index replay root lookups concurrently
seonghobae Aug 7, 2026
2b0955d
build(etl): run replay root index outside transaction
seonghobae Aug 7, 2026
a9c3c76
test(etl): verify replay lookup indexes in PostgreSQL
seonghobae Aug 7, 2026
3a2fb6d
test(etl): require replay controller coverage
seonghobae Aug 7, 2026
9467406
fix(etl): enforce replay controller coverage
seonghobae Aug 7, 2026
1ead408
docs(etl): document replay index recovery
seonghobae Aug 7, 2026
228d08f
test(etl): rehearse exact replay digest and index integrity
seonghobae Aug 7, 2026
41a778c
test(ci): require replay coverage diagnostics
seonghobae Aug 7, 2026
33ba010
docs(etl): align replay design with database evidence
seonghobae Aug 7, 2026
bfd705e
fix(ci): diagnose replay controller coverage
seonghobae Aug 7, 2026
9b0a125
docs(adr): align replay authority and index rollout
seonghobae Aug 7, 2026
025798b
docs(doctoring): bind replay evidence and online indexes
seonghobae Aug 7, 2026
e249a8d
test(etl): require terminal-only replay descendant scans
seonghobae Aug 7, 2026
d41f704
fix(etl): bound replay descendant scans
seonghobae Aug 7, 2026
f33af02
test(etl): permit documented replay guard comments
seonghobae Aug 7, 2026
ba7fda8
test(etl): require exact replay index catalog verification
seonghobae Aug 7, 2026
fd7c61f
fix(etl): verify exact replay index definitions
seonghobae Aug 7, 2026
b408296
test(docs): require exact replay index verification evidence
seonghobae Aug 7, 2026
ba08f86
fix(etl): retain replay index verifier diagnostics contract
seonghobae Aug 7, 2026
48e9ed9
docs(etl): document exact replay index verification
seonghobae Aug 7, 2026
94ba007
docs(doctoring): record exact replay index evidence
seonghobae Aug 7, 2026
f5fd3ba
docs(changelog): record exact replay index verification
seonghobae Aug 7, 2026
7533959
fix(changelog): preserve idempotent retry wording
seonghobae Aug 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:

- name: Run tests (Windows)
if: runner.os == 'Windows'
run: .\\mvnw.cmd -B test
run: .\mvnw.cmd -B test

- name: Report uncovered JaCoCo branches
if: failure()
Expand All @@ -60,7 +60,9 @@ jobs:

coverage_targets = {
"com/xtrmetl/etl/job/EtlJobService": "EtlJobService.java",
"com/xtrmetl/etl/job/EtlJobReplayService": "EtlJobReplayService.java",
"com/xtrmetl/etl/controller/EtlJobController": "EtlJobController.java",
"com/xtrmetl/etl/controller/EtlJobReplayController": "EtlJobReplayController.java",
"com/xtrmetl/etl/service/Sha256Digest": "Sha256Digest.java",
}
reports = sorted(Path(".").glob("**/target/site/jacoco/jacoco.xml"))
Expand Down Expand Up @@ -135,4 +137,4 @@ jobs:

- name: Run tests (Windows)
if: runner.os == 'Windows'
run: .\\mvnw.cmd -B test
run: .\mvnw.cmd -B test
56 changes: 56 additions & 0 deletions .github/workflows/postgresql-migration-integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: PostgreSQL Migration Integration

on:
pull_request:
branches:
- develop
paths:
- "etl-service/src/main/resources/db/migration/**"
- "etl-service/src/test/postgresql/**"
- "scripts/verify-postgresql-migrations.sh"
- ".github/workflows/postgresql-migration-integration.yml"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: postgresql-migration-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
replay_lineage_migration:
name: replay-lineage-migration
if: github.event_name != 'workflow_dispatch' || github.ref_name == github.event.repository.default_branch
runs-on: ubuntu-latest
timeout-minutes: 15
services:
postgresql_database:
image: postgres:18-alpine
env:
POSTGRES_DB: mightyetl_replay_test
POSTGRES_USER: mightyetl_test
POSTGRES_PASSWORD: mightyetl_test_password
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready --username=mightyetl_test --dbname=mightyetl_replay_test"
--health-interval 5s
--health-timeout 5s
--health-retries 12
env:
PGHOST: 127.0.0.1
PGPORT: "5432"
PGDATABASE: mightyetl_replay_test
PGUSER: mightyetl_test
PGPASSWORD: mightyetl_test_password
steps:
- name: Check out exact pull-request head or protected default branch
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
with:
repository: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }}
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.event.repository.default_branch }}
persist-credentials: false
- name: Verify versioned migrations and immutable replay lineage
shell: bash
run: bash scripts/verify-postgresql-migrations.sh
13 changes: 10 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Authenticated operators can now create an ordinary pending durable job from an immutable failed or cancelled source only after resupplying a byte-identical bounded JSON payload; the terminal source remains unchanged and succeeded sources remain non-replayable.
- Replay lineage now remains database-authoritative across every writer: PostgreSQL validates the terminal immediate source, first root, exact source/root/generation continuity, generation-one identity, and one-step generation succession, while immutable lineage fields prevent post-insert reparenting.
- Once a terminal job is referenced as a replay source or root, PostgreSQL row-lock serialization now freezes its status, request evidence, attempt/failure state, cancellation evidence, and lifecycle timestamps so descendants cannot silently acquire different historical meaning.
- PostgreSQL migration verification now reconstructs and validates the exact replay-index column, predicate, and one-column nonunique shape in addition to readiness and validity, so a same-named but incorrectly defined index fails closed.
- Authenticated operators can now perform owner-scoped durable-job cancellation for `PENDING` and `RUNNING` work through an idempotent action that commits terminal `CANCELLED`, clears payload and lease state, stores only `cancellation_key_hash` plus a fixed code and timestamp, and returns stable RFC 9457 conflicts when success or failure already won.
- Cancellation-first races now make the former exact lease stale and roll back transactional target and response-ledger effects; success-first races remain `SUCCEEDED`, while same-key cancellation replays and different-key reuse fails closed.
- Owner-scoped durable-job status responses now emit deterministic weak SHA-256 `ETag` validators; ordinary and wildcard `If-None-Match` requests return an empty RFC 9110 `304 Not Modified` response only after authenticated owner-safe lookup, while `Cache-Control: no-store` remains unchanged.
Expand Down Expand Up @@ -37,9 +41,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Transactional migration `V7__add_etl_job_replay_lineage.sql`, owner-scoped replay admission, the named `etl_job_owner_identity_unique` support key, composite owner-scoped foreign keys for immediate-source and root lineage, `validate_etl_job_replay_lineage()` plus `etl_job_replay_lineage_guard_trigger`, and immutable `replay_source_job_record_id`, `replay_root_job_record_id`, and `replay_generation_count` evidence with concurrency, tenant-integrity, exact-continuity, worker-compatibility, rollout, incident, and rollback tests and documentation.
- PostgreSQL 18 rehearsal now executes valid first- and second-generation replay chains and rejects nonterminal sources, different generation-one roots, derived roots, skipped generations, cross-owner references, lineage mutation, referenced root/source evidence mutation, and protected source/root deletion before transactionally rehearsing trigger, function, constraint, and column rollback.
- Transactional migration `V6__add_etl_job_cancellation.sql`, owner-safe cancellation API and replay model, exact lease-invalidation and cancellation-versus-success integration tests, plus rollout, incident, connector-limitation, and rollback evidence in `docs/operations/durable-job-cancellation.md`.
- Deterministic ordinary, wildcard, changed-state, changed-failure-code, null-versus-empty, and unrelated-response conditional polling tests, complete controller Javadoc, privacy and rollback guidance, and APA 7th standards evidence in `docs/etl/durable-job-polling.md`.
- Controller-scoped polling advice, deterministic active/terminal lifecycle tests, disabled-worker fail-closed behavior, sub-second rounding coverage, rollback guidance, and APA 7th standards evidence in `docs/etl/durable-job-polling.md`.
- Controller-scoped polling advice, deterministic active/terminal lifecycle tests, disabled-worker fail-closed behavior, sub-second rounding coverage, rollback guidance, and APA 7th RFC 9110 evidence in `docs/etl/durable-job-polling.md`.
- Owner-scoped durable job list models and HTTP contract, strict cursor and page-limit validation, one-extra-row next-page detection, the descriptive `etl_job_owner_pagination_index`, deterministic tenant-isolation and equal-timestamp tests, migration rollback guidance, and APA 7th standards evidence in `docs/etl/durable-job-intake.md`.
- A production rollout and invalid-index recovery runbook for the nonblocking durable-job claim index: `docs/operations/durable-job-claim-index-rollout.md`.
- PostgreSQL `FOR UPDATE SKIP LOCKED` durable-job claiming, per-process and per-claim lease fencing, expiry reclaim, bounded attempts, exact-live-lease transitions, terminal payload clearing, stable failure codes, and finite-cardinality worker metrics.
Expand Down Expand Up @@ -77,6 +83,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Security

- Replay uses owner-scoped source selection, byte-exact digest verification, a versioned principal-scoped key domain, immutable relational lineage, composite owner-scoped foreign keys, and a database trigger that independently rejects cross-tenant references, nonterminal sources, false roots, generation discontinuities, lineage mutation, and mutation of referenced terminal evidence without retaining raw principals or replay keys; this evidence does not prove external connector safety, so connector-native idempotency, transaction participation, or compensation remains required.
- Cancellation stores only a principal-scoped SHA-256 replay identity and a fixed machine code, exposes no raw principal, key, hash, payload, lease, SQL, exception, or target detail, and requires an owner-matched conditional database update before reporting success.
- Conditional status validators are SHA-256 digests of only the complete owner-authorized operator-safe representation; payloads, raw principals, idempotency keys, internal hashes, leases, SQL, and exception text remain excluded, and wildcard evaluation occurs only after owner-safe lookup.
- Polling advice exposes only a bounded delay integer and is omitted when local execution is disabled or terminal; it never contains job, lease, principal, key, hash, payload, SQL, exception, target, or queue-depth data.
Expand Down Expand Up @@ -164,7 +171,7 @@ Through code analysis, identified the platform as:
- Microservices-based architecture using Spring Cloud
- Real-time Change Data Capture using Debezium
- Event streaming via Apache Kafka
- Service discovery with Netflix Eureka
- Service discovery and registration
- Distributed tracing with Zipkin

#### Key Components Documented
Expand Down Expand Up @@ -283,5 +290,5 @@ This changelog will be updated:
---

**Changelog Version**: 1.0
**Last Updated**: 2026-08-06
**Last Updated**: 2026-08-07
**Maintained By**: Development Team
Loading