|
|
|
|
@@ -0,0 +1,110 @@
|
|
|
|
|
"""v0.1.8 notifications baseline
|
|
|
|
|
|
|
|
|
|
Revision ID: 5e6f7a8b9c0d
|
|
|
|
|
Revises: None
|
|
|
|
|
Create Date: 2026-07-13 00:00:00.000000
|
|
|
|
|
"""
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from alembic import op
|
|
|
|
|
import sqlalchemy as sa
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
revision = "5e6f7a8b9c0d"
|
|
|
|
|
down_revision = None
|
|
|
|
|
branch_labels = None
|
|
|
|
|
depends_on = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def upgrade() -> None:
|
|
|
|
|
op.create_table(
|
|
|
|
|
"notification_messages",
|
|
|
|
|
sa.Column("id", sa.String(length=36), nullable=False),
|
|
|
|
|
sa.Column("tenant_id", sa.String(length=36), nullable=False),
|
|
|
|
|
sa.Column("source_module", sa.String(length=100), nullable=False),
|
|
|
|
|
sa.Column("source_resource_type", sa.String(length=100), nullable=False),
|
|
|
|
|
sa.Column("source_resource_id", sa.String(length=255), nullable=True),
|
|
|
|
|
sa.Column("event_kind", sa.String(length=100), nullable=False),
|
|
|
|
|
sa.Column("channel", sa.String(length=40), nullable=False),
|
|
|
|
|
sa.Column("recipient", sa.String(length=500), nullable=True),
|
|
|
|
|
sa.Column("recipient_type", sa.String(length=40), nullable=True),
|
|
|
|
|
sa.Column("recipient_id", sa.String(length=255), nullable=True),
|
|
|
|
|
sa.Column("recipient_label", sa.String(length=500), nullable=True),
|
|
|
|
|
sa.Column("subject", sa.String(length=500), nullable=True),
|
|
|
|
|
sa.Column("body_text", sa.Text(), nullable=True),
|
|
|
|
|
sa.Column("body_html", sa.Text(), nullable=True),
|
|
|
|
|
sa.Column("action_url", sa.String(length=1000), nullable=True),
|
|
|
|
|
sa.Column("priority", sa.Integer(), nullable=False),
|
|
|
|
|
sa.Column("status", sa.String(length=40), nullable=False),
|
|
|
|
|
sa.Column("not_before_at", sa.DateTime(timezone=True), nullable=True),
|
|
|
|
|
sa.Column("queued_at", sa.DateTime(timezone=True), nullable=True),
|
|
|
|
|
sa.Column("sent_at", sa.DateTime(timezone=True), nullable=True),
|
|
|
|
|
sa.Column("failed_at", sa.DateTime(timezone=True), nullable=True),
|
|
|
|
|
sa.Column("read_at", sa.DateTime(timezone=True), nullable=True),
|
|
|
|
|
sa.Column("acknowledged_at", sa.DateTime(timezone=True), nullable=True),
|
|
|
|
|
sa.Column("cancelled_at", sa.DateTime(timezone=True), nullable=True),
|
|
|
|
|
sa.Column("attempt_count", sa.Integer(), nullable=False),
|
|
|
|
|
sa.Column("last_error", sa.Text(), nullable=True),
|
|
|
|
|
sa.Column("external_message_id", sa.String(length=255), nullable=True),
|
|
|
|
|
sa.Column("payload", sa.JSON(), nullable=False),
|
|
|
|
|
sa.Column("metadata", sa.JSON(), nullable=False),
|
|
|
|
|
sa.Column("deleted_at", sa.DateTime(timezone=True), nullable=True),
|
|
|
|
|
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
|
|
|
|
|
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
|
|
|
|
|
sa.PrimaryKeyConstraint("id", name=op.f("pk_notification_messages")),
|
|
|
|
|
)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_channel"), "notification_messages", ["channel"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_deleted_at"), "notification_messages", ["deleted_at"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_event_kind"), "notification_messages", ["event_kind"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_external_message_id"), "notification_messages", ["external_message_id"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_not_before_at"), "notification_messages", ["not_before_at"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_priority"), "notification_messages", ["priority"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_recipient"), "notification_messages", ["recipient"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_recipient_id"), "notification_messages", ["recipient_id"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_recipient_type"), "notification_messages", ["recipient_type"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_source_module"), "notification_messages", ["source_module"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_source_resource_id"), "notification_messages", ["source_resource_id"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_source_resource_type"), "notification_messages", ["source_resource_type"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_status"), "notification_messages", ["status"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_messages_tenant_id"), "notification_messages", ["tenant_id"], unique=False)
|
|
|
|
|
op.create_index("ix_notification_messages_due", "notification_messages", ["tenant_id", "status", "not_before_at"], unique=False)
|
|
|
|
|
op.create_index("ix_notification_messages_source", "notification_messages", ["tenant_id", "source_module", "source_resource_type", "source_resource_id"], unique=False)
|
|
|
|
|
op.create_index("ix_notification_messages_tenant_recipient", "notification_messages", ["tenant_id", "recipient_type", "recipient_id"], unique=False)
|
|
|
|
|
op.create_index("ix_notification_messages_tenant_status", "notification_messages", ["tenant_id", "status"], unique=False)
|
|
|
|
|
|
|
|
|
|
op.create_table(
|
|
|
|
|
"notification_delivery_attempts",
|
|
|
|
|
sa.Column("id", sa.String(length=36), nullable=False),
|
|
|
|
|
sa.Column("tenant_id", sa.String(length=36), nullable=False),
|
|
|
|
|
sa.Column("notification_id", sa.String(length=36), nullable=False),
|
|
|
|
|
sa.Column("attempt_no", sa.Integer(), nullable=False),
|
|
|
|
|
sa.Column("channel", sa.String(length=40), nullable=False),
|
|
|
|
|
sa.Column("provider", sa.String(length=100), nullable=True),
|
|
|
|
|
sa.Column("status", sa.String(length=40), nullable=False),
|
|
|
|
|
sa.Column("started_at", sa.DateTime(timezone=True), nullable=True),
|
|
|
|
|
sa.Column("finished_at", sa.DateTime(timezone=True), nullable=True),
|
|
|
|
|
sa.Column("external_message_id", sa.String(length=255), nullable=True),
|
|
|
|
|
sa.Column("error", sa.Text(), nullable=True),
|
|
|
|
|
sa.Column("details", sa.JSON(), nullable=False),
|
|
|
|
|
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
|
|
|
|
|
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
|
|
|
|
|
sa.ForeignKeyConstraint(
|
|
|
|
|
["notification_id"],
|
|
|
|
|
["notification_messages.id"],
|
|
|
|
|
name=op.f("fk_notification_delivery_attempts_notification_id_notification_messages"),
|
|
|
|
|
ondelete="CASCADE",
|
|
|
|
|
),
|
|
|
|
|
sa.PrimaryKeyConstraint("id", name=op.f("pk_notification_delivery_attempts")),
|
|
|
|
|
)
|
|
|
|
|
op.create_index(op.f("ix_notification_delivery_attempts_channel"), "notification_delivery_attempts", ["channel"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_delivery_attempts_notification_id"), "notification_delivery_attempts", ["notification_id"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_delivery_attempts_provider"), "notification_delivery_attempts", ["provider"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_delivery_attempts_status"), "notification_delivery_attempts", ["status"], unique=False)
|
|
|
|
|
op.create_index(op.f("ix_notification_delivery_attempts_tenant_id"), "notification_delivery_attempts", ["tenant_id"], unique=False)
|
|
|
|
|
op.create_index("ix_notification_attempts_notification", "notification_delivery_attempts", ["notification_id", "attempt_no"], unique=False)
|
|
|
|
|
op.create_index("ix_notification_attempts_tenant_status", "notification_delivery_attempts", ["tenant_id", "status"], unique=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def downgrade() -> None:
|
|
|
|
|
op.drop_table("notification_delivery_attempts")
|
|
|
|
|
op.drop_table("notification_messages")
|