From 49d5756ceb077d3f207c62c36e9279c2a45a1797 Mon Sep 17 00:00:00 2001 From: sirius0xdev Date: Tue, 7 Jul 2026 18:29:50 -0400 Subject: [PATCH] Make events PK composite (id, ingested_at) for TimescaleDB hypertable partitioning requirement --- alembic/versions/001_initial.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/alembic/versions/001_initial.py b/alembic/versions/001_initial.py index d6bdbcf..fc97118 100644 --- a/alembic/versions/001_initial.py +++ b/alembic/versions/001_initial.py @@ -38,9 +38,11 @@ def upgrade() -> None: ) # events (will become hypertable) + # NOTE: TimescaleDB requires the partitioning column (ingested_at) to be + # part of the primary key / any unique index, so the PK is composite. op.create_table( 'events', - sa.Column('id', UUID(as_uuid=True), primary_key=True), + sa.Column('id', UUID(as_uuid=True), nullable=False), sa.Column('source_type', sa.Enum('rss', 'gdel-t2', 'social', 'earthquake', 'disaster', 'weather', 'fire', 'satellite', name='event_source_type'), nullable=False, index=True), sa.Column('source_id', UUID(as_uuid=True)), sa.Column('title', sa.Text()), @@ -57,6 +59,7 @@ def upgrade() -> None: sa.Column('ingested_at', sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False), sa.Column('source_timestamp', sa.DateTime(timezone=True), nullable=False), sa.Column('search_vector', TSVECTOR), + sa.PrimaryKeyConstraint('id', 'ingested_at'), ) # Convert events to TimescaleDB hypertable