Ctrl K
ComunidadGuías…

deploy/migrations/0126_star_gift_user_refs_and_profile_state.up.sql

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
-- Official clients may continue lifecycle actions from a freshly emitted
-- messageActionStarGiftUnique. Keep those user-local message ids as explicit
-- durable references to the same saved gift aggregate.
CREATE TABLE star_gift_user_message_refs (
    owner_user_id bigint NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    msg_id integer NOT NULL,
    saved_gift_id bigint NOT NULL REFERENCES peer_star_gifts(id) ON DELETE CASCADE,
    created_at timestamptz NOT NULL DEFAULT now(),
    PRIMARY KEY (owner_user_id, msg_id),
    CONSTRAINT star_gift_user_message_refs_msg_check CHECK (owner_user_id > 0 AND msg_id > 0)
);

CREATE INDEX star_gift_user_message_refs_saved_idx
    ON star_gift_user_message_refs(saved_gift_id, owner_user_id, msg_id);

INSERT INTO star_gift_user_message_refs(owner_user_id,msg_id,saved_gift_id)
SELECT box.owner_user_id, box.box_id, gift.id
FROM message_boxes box
JOIN unique_star_gifts unique_gift
  ON (box.media #>> '{service_action,star_gift_unique,gift,ID}') ~ '^[0-9]+$'
 AND unique_gift.id = (box.media #>> '{service_action,star_gift_unique,gift,ID}')::bigint
JOIN peer_star_gifts gift
  ON gift.id = unique_gift.source_saved_gift_id
 AND gift.owner_peer_type = 'user'
 AND gift.owner_peer_id = box.owner_user_id
WHERE NOT box.deleted
  AND box.media #>> '{service_action,kind}' = 'star_gift_unique'
  AND box.box_id <> gift.msg_id;

-- Hidden gifts cannot remain pinned. Compacting the whole owner vector here
-- also repairs historical gaps before the invariant is constrained.
ALTER TABLE peer_star_gifts
    ADD CONSTRAINT peer_star_gifts_hidden_unpinned_check
    CHECK (pinned_order<=6 AND (NOT unsaved OR pinned_order=0)) NOT VALID;

CREATE TEMP TABLE star_gift_pin_repairs ON COMMIT DROP AS
SELECT id,new_order
FROM (
    SELECT id,
           row_number() OVER (PARTITION BY owner_peer_type,owner_peer_id
                              ORDER BY pinned_order,id)::integer AS new_order
    FROM peer_star_gifts
    WHERE lifecycle_status='active' AND NOT unsaved AND pinned_order>0
) ranked
WHERE new_order<=6;

UPDATE peer_star_gifts SET pinned_order=0 WHERE pinned_order<>0;

UPDATE peer_star_gifts gift
SET pinned_order=repair.new_order
FROM star_gift_pin_repairs repair
WHERE gift.id=repair.id;

-- peer and saved_id share one TL flag and are channel-only. Earlier user gift
-- projections set peer=user (and sometimes a user box id in saved_id), which
-- made TDesktop select zero/stale ids instead of the emitted service message.
CREATE TEMP TABLE star_gift_user_unique_media_repairs (
    owner_user_id bigint NOT NULL,
    box_id integer NOT NULL,
    peer_type text NOT NULL,
    peer_id bigint NOT NULL,
    repaired_media jsonb NOT NULL,
    PRIMARY KEY(owner_user_id,box_id)
) ON COMMIT DROP;

INSERT INTO star_gift_user_unique_media_repairs(owner_user_id,box_id,peer_type,peer_id,repaired_media)
SELECT box.owner_user_id,
       box.box_id,
       box.peer_type,
       box.peer_id,
       jsonb_set(
           box.media #- '{service_action,star_gift_unique,saved_id}',
           '{service_action,star_gift_unique,peer}',
           '{"ID":0,"Type":""}'::jsonb,
           true
       )
FROM message_boxes box
WHERE NOT box.deleted
  AND box.media #>> '{service_action,kind}' = 'star_gift_unique'
  AND box.media #>> '{service_action,star_gift_unique,peer,Type}' = 'user';

DO $$
DECLARE
    repair record;
    next_pts integer;
    event_date integer := EXTRACT(EPOCH FROM clock_timestamp())::integer;
BEGIN
    FOR repair IN
        SELECT owner_user_id,box_id,peer_type,peer_id,repaired_media
        FROM star_gift_user_unique_media_repairs
        ORDER BY owner_user_id,box_id
    LOOP
        INSERT INTO user_update_watermarks(user_id,contiguous_pts)
        VALUES(repair.owner_user_id,0)
        ON CONFLICT(user_id) DO NOTHING;

        UPDATE user_update_watermarks
        SET contiguous_pts=contiguous_pts+1,updated_at=now()
        WHERE user_id=repair.owner_user_id
        RETURNING contiguous_pts INTO next_pts;

        UPDATE message_boxes
        SET media=repair.repaired_media,pts=next_pts
        WHERE owner_user_id=repair.owner_user_id AND box_id=repair.box_id AND NOT deleted;

        INSERT INTO user_update_events(
            user_id,pts,pts_count,date,event_type,message_box_id,peer_type,peer_id
        ) VALUES(
            repair.owner_user_id,next_pts,1,event_date,'edit_message',repair.box_id,repair.peer_type,repair.peer_id
        );

        INSERT INTO dispatch_outbox(
            target_user_id,pts,event_type,exclude_auth_key_id,exclude_session_id
        ) VALUES(repair.owner_user_id,next_pts,'edit_message',0,0);
    END LOOP;
END
$$;

UPDATE private_messages
SET media=jsonb_set(
    media #- '{service_action,star_gift_unique,saved_id}',
    '{service_action,star_gift_unique,peer}',
    '{"ID":0,"Type":""}'::jsonb,
    true
)
WHERE media #>> '{service_action,kind}' = 'star_gift_unique'
  AND media #>> '{service_action,star_gift_unique,peer,Type}' = 'user';