Skip to content

Shared row-storage DDL is order-dependent; name the exact DROP CONSTRAINT in the refusal and the docs #1495

Open

Description

@KonstantinMirin

Problem

The Python and JavaScript row-storage migrations create the same tables, with one difference: the JavaScript adcp_reporting_row_sets declares obligation_id ... REFERENCES adcp_reporting_obligations(obligation_id), and the Python table does not, because Python obligations live in reporting_obligations. When both SDKs share one database (the supported reader topology, and what the interop test exercises), the order of the two migrations decides whether Python can write. If the JavaScript migration runs first, ready_row_storage refuses with STATE_UNAVAILABLE. The refusal names the constraint and says "or drop the constraint"; neither it nor the docs give the statement to run.

Evidence

All references are to main at 47084e83a; the JS SDK is adcp-client main at 7c7f730f4.

  • adcp-client src/lib/reporting/ledger/row-storage-migration.ts:109:

    obligation_id TEXT COLLATE "C" NOT NULL REFERENCES adcp_reporting_obligations(obligation_id),
  • src/adcp/reporting/ledger/reporting_row_storage.sql:127: obligation_id TEXT COLLATE "C" NOT NULL, (no foreign key).

  • src/adcp/reporting/ledger/row_storage.py:582-605, _refuse_foreign_core_keys, raises:

    "adcp_reporting_row_sets has a foreign key to another SDK's core table "
    f"({row[0]}); apply reporting_row_storage.sql before that SDK's migration, "
    "or drop the constraint",
  • docs/reporting-row-storage.md:60-63: "If the JavaScript migration created the table first, ready_row_storage refuses with the constraint name; apply this migration first, or drop that constraint."

  • docs/reporting-row-storage.md:349-350: "The row-storage migration applied by this SDK first, because the JavaScript adcp_reporting_row_sets has a foreign key to its own obligations table that Python obligations can never satisfy."

  • docs/reporting-row-storage.md:32-33: "A ledger database has exactly one writer SDK. Python and JavaScript can read each other's chunks (that is what the interop test proves)", so the two-migration database remains a supported layout.

Suggested fix

  • The refusal already has conname; append the statement: ALTER TABLE adcp_reporting_row_sets DROP CONSTRAINT "<conname>"; (quoted with quote_ident). Put the same statement, with the default constraint name PostgreSQL generates (adcp_reporting_row_sets_obligation_id_fkey), in both places in docs/reporting-row-storage.md.
  • Ask the JS SDK to drop the foreign key from row-storage-migration.ts, so the two DDLs are identical and the order stops mattering. That is a one-line change on their side and removes _refuse_foreign_core_keys here.

Introduced in #1464.

Activity

  1. added
    documentationImprovements or additions to documentation
    pythonPull requests that update python code
    on Oct 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationpythonPull requests that update python code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions