63 lines
2.0 KiB
Python
63 lines
2.0 KiB
Python
"""Qualify pgcrypto digest in the contact sync trigger.
|
|
|
|
Revision ID: 0002_pgcrypto_digest
|
|
Revises: 0001_initial
|
|
Create Date: 2026-07-16
|
|
"""
|
|
|
|
from collections.abc import Sequence
|
|
|
|
from alembic import op
|
|
|
|
revision: str = "0002_pgcrypto_digest"
|
|
down_revision: str | None = "0001_initial"
|
|
branch_labels: str | Sequence[str] | None = None
|
|
depends_on: str | Sequence[str] | None = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.execute(
|
|
"""
|
|
CREATE OR REPLACE FUNCTION han_app.enqueue_contact_sync()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
SECURITY INVOKER
|
|
SET search_path = han_app, pg_temp
|
|
AS $$
|
|
DECLARE
|
|
v_entity_id uuid;
|
|
v_task_type text;
|
|
v_dedup text;
|
|
BEGIN
|
|
IF current_setting('han.sync_suppress', true) = 'true' THEN
|
|
RETURN NEW;
|
|
END IF;
|
|
IF TG_TABLE_NAME = 'user_identities' THEN
|
|
v_entity_id := NEW.id;
|
|
v_task_type := CASE WHEN TG_OP = 'INSERT'
|
|
THEN 'contact.map_or_create' ELSE 'contact.update' END;
|
|
ELSE
|
|
v_entity_id := NEW.user_id;
|
|
v_task_type := CASE WHEN TG_OP = 'INSERT'
|
|
THEN 'contact.map_or_create' ELSE 'contact.update' END;
|
|
END IF;
|
|
v_dedup := v_task_type || ':' || v_entity_id::text || ':' ||
|
|
encode(public.digest(row_to_json(NEW)::text, 'sha256'), 'hex');
|
|
INSERT INTO han_app.sync_queue
|
|
(id, task_type, entity_type, entity_id, dedup_key, payload_json,
|
|
status, attempt_count, next_attempt_at, created_at, updated_at)
|
|
VALUES
|
|
(gen_random_uuid(), v_task_type, 'contact', v_entity_id, v_dedup,
|
|
jsonb_build_object('entity_id', v_entity_id), 'pending', 0,
|
|
now(), now(), now())
|
|
ON CONFLICT (dedup_key) DO NOTHING;
|
|
RETURN NEW;
|
|
END;
|
|
$$
|
|
"""
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
raise RuntimeError("Contact sync trigger migration is forward-only")
|