Skip to content

#475 Support linking a child partitioning to multiple parents - #496

Draft
lsulak wants to merge 22 commits into
masterfrom
feature/475-multiple-child-parent-linkage-possible
Draft

lsulak wants to merge 22 commits into
masterfrom
feature/475-multiple-child-parent-linkage-possible

Conversation

@lsulak

@lsulak lsulak commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator

Overview

Lets a child Atum partitioning be linked to multiple parents in one operation (instead of calling getOrCreateAtumSubContext N times).

  • DB: new append-only migrations V0.10.0.1 (private copy helper) and V0.10.0.2 (runs.create_partitioning_with_parents): validates all parents up front, links all in one transaction, re-links existing children, unions/de-duplicates measures and additional data. Shipped migrations untouched.
  • Model: PartitioningSubmitDTO / PartitioningSubmitV2DTO carry a list of parents; compat apply keeps old callers compiling; decoders still accept old JSON. Encoders now always emit the list field.
  • Server v2: POST /partitionings accepts 2+ parent ids (de-duplicated, capped at 100; 41→404, cycle→409). 0–1 parents use the existing DB function. v1 unchanged.
  • Lineage: tests added; get_partitioning_ancestors already handles multiple parents.
  • Agent: AtumAgent.getOrCreateAtumSubContext(subPartitions, parents: Seq[AtumContext]) and AtumContext.subContext(subPartitions, parents); one HTTP POST carrying all parent ids.

Compatibility note: a new agent sending to an old server loses extra parents (old servers ignore the new field) — upgrade the server first (documented in agent/server READMEs).

Validation: model, reader, agent (3 axes), server unit tests, testDB, and testCompatibility against a live server all passed locally.

Release Notes

  • Support linking a child partitioning to multiple parents in one call (getOrCreateAtumSubContext(subPartitions, parents), AtumContext.subContext)
  • New DB function runs.create_partitioning_with_parents and multi-parent support in server v2 create endpoint
  • Server must be upgraded before agents to use multi-parent linking

Related

Closes #475

lsulak and others added 21 commits October 19, 2026 22:51
- union + dedup copy of measure definitions across copy-from parents (D-03)
- child-then-skip additional data merge with skipped_ad_keys reporting (D-04, D-04a)
- owned by atum_owner, EXECUTE revoked from PUBLIC (T-01-01)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- 9 tests: measure union + dedup, child-then-skip additional data, NULL value
  semantics, conflict-scope vs copy-from, empty set, array hygiene
- two-column filters use SQL conditions to avoid balta 0.1.0 param-order bug

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…, TEXT, BIGINT[])

- validates all parents up front (status 41, nothing written)
- creates or reuses the child (no status 31), links every parent idempotently
- copies parents' data via runs._copy_parents_data_to_partitioning (RD-2 ancestry-based copy-from set)
- EXECUTE revoked from PUBLIC, granted to atum_user only

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…g overload

- 15 tests: two-parent link, atomic status 41, NULL/empty/single-element arrays,
  re-link (13 not 31), idempotent resubmit (14), POLICY-01 end-to-end,
  reversed-id topology (RD-2), shipped overload resolution

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…s, copied_rows, tie-break and privilege tests (WR-04, WR-07, WR-08, IN-03, IN-05, IN-06)

- pin search_path (pg_catalog, public, pg_temp) on the SECURITY DEFINER helper; public is needed
  because column defaults call public.global_id()
- return status 41 for a NULL/non-existent child instead of silently doing nothing or failing on FKs
- add OUT copied_rows (rows actually inserted) so callers can tell a no-op from a write
- document why copied measure definitions keep the parent's created_by/created_at while
  copied additional data is stamped with i_by_user (matches shipped create_partitioning)
- tests: earliest-parent tie-break with explicit created_at, 41 for missing/NULL child,
  has_function_privilege (owner only), pinned search_path; hasNext asserts, drop redundant assert

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e, conflict, concurrency and linking semantics (CR-01, CR-02, WR-01, WR-02, WR-03, WR-04, WR-05, WR-06, WR-08, IN-02, IN-04, IN-05)

Amends the unreleased V0.10.0.2 migration in place (renamed to V0.10.0.2__create_partitioning_with_parents.sql).

- WR-02: new function name runs.create_partitioning_with_parents(JSONB, TEXT, BIGINT[]); the shipped
  runs.create_partitioning is the only function of its name again, so untyped positional NULL resolves
- CR-02: reject a parent that is the partitioning itself or its descendant with status 43, before any
  write (write-side guard only; serialized by an advisory xact lock)
- CR-01: additional data conflict scope is every ancestor of the partitioning after linking, so a key
  skipped for a conflict is not filled in later by another parent
- WR-01: data of every supplied parent is always copied (idempotent), so {p1,p2} and {p1} then {p1,p2} converge
- WR-03: INSERT ... ON CONFLICT DO NOTHING + re-select, a concurrent create no longer raises partitioning_unq
- WR-04: SET search_path = pg_catalog, public, pg_temp (public is needed for public.global_id())
- WR-05: descendants of an existing partitioning are added to the flows of the newly linked parents
- WR-06: status 13 whenever links or data were written, 14 only for a pure no-op
- IN-02: skipped keys returned in OUT skipped_ad_keys, status_text only carries their count
- IN-04: existing partitioning with NULL/empty parents returns 14, pinned by a test
- tests: renamed suite, 24 tests incl. CR-01/CR-02/WR-01/WR-02/WR-05/WR-06 scenarios, privileges,
  pinned search_path, AD created_by stamping

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… custom codec

- store parentPartitionings: Seq[PartitioningDTO]; Option compat apply
- encoder always emits parentPartitionings; decoder accepts legacy parentPartitioning
- extend serialization tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- use parentPartitionings.headOption to keep single-parent behaviour

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- store parentPartitioningIds: Seq[Long]; decode old/new JSON, encode new key only
- CreatePartitioning passes parentPartitioningIds.headOption

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- new CreatePartitioningWithParents wrapper (typed BIGINT[] arg, 43 -> conflict)
- repository de-duplicates parent ids and routes 0-1 vs 2+ parents
- wire layer in Main; unit and DB integration tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…4 variant

- Controller de-duplicates parent ids, rejects >100 with 400 before service call
- POST /partitionings endpoint exposes 404 variant
- Controller and service tests for cap, dedupe, 404/409 propagation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- 201 for multi-parent, legacy single-parent JSON and no-parent bodies
- 404/409/400 mapping at HTTP level

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Resolve every parent id; 2+ parents always POST once (no child GET, no PATCH)
- 0-1 parent flow unchanged
- Tests decode POST body and assert parentPartitioningIds order

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- single createPartitioning dispatch with deduped parents, child identity = subPartitions
- empty parents throw IllegalArgumentException

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- delegates to AtumAgent multi-parent overload
- document in agent README

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ond, pagination, unq_flows)

- No duplicates possible (unq_flows + PK); V0.10.0.3 migration not needed

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- child created once via getOrCreateAtumSubContext(sub, Seq(p1,p2))
- asserts ancestors == {A,B} via server v2 endpoint and flow links without duplicates

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ion values

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 12:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

JaCoCo Coverage Report

Metric (instruction) Coverage Threshold Status
Overall 66.32% 64.0% ✅
Changed Files 93.97% 80.0% ✅
Group Coverage (O/Ch) Threshold (O/Ch) Status (O/Ch)
atum-agent 83.33% / 87.94% 78.0% / 80.0% ✅/✅
atum-model 34.66% / 49.09% 34.0% / 80.0% ✅/❌
atum-server 77.79% / 96.72% 78.0% / 80.0% ❌/✅
Report Coverage (O/Ch) Threshold (O/Ch) Status (O/Ch)
Report: agent_spark3 - scala:2.13.18 83.33% / 87.94% 78.0% / 80.0% ✅/✅
Report: model - scala:2.13.18 34.66% / 49.09% 34.0% / 80.0% ✅/❌
Report: server - scala:2.13.18 77.79% / 96.72% 78.0% / 80.0% ❌/✅
File Path Coverage Threshold Status
AtumAgent.scala 83.25% 60.0% ✅
AtumContext.scala 96.84% 60.0% ✅
CreatePartitioning.scala 93.75% 60.0% ✅
CreatePartitioningIfNotExists.scala 94.92% 60.0% ✅
CreatePartitioningWithParents.scala 44.51% 60.0% ❌
Endpoints.scala 98.8% 60.0% ✅
HttpDispatcher.scala 86.85% 60.0% ✅
PartitioningControllerImpl.scala 91.81% 60.0% ✅
PartitioningRepositoryImpl.scala 98.91% 60.0% ✅
PartitioningSubmitDTO.scala 49.09% 60.0% ❌
PartitioningSubmitV2DTO.scala 49.09% 60.0% ❌

Run 40548410307 · Event: pull_request

@lsulak
lsulak marked this pull request as draft October 21, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Atum Agent: Support linking Atum Partitioning of a child with multiple parents

2 participants