Ctrl K
ComunidadGuías…

internal/store/postgres/channel_member_index_plan_integration_test.go

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

Archivo original ↗Preguntar a KiBot
package postgres

import (
	"context"
	"strings"
	"testing"

	"telesrv/internal/domain"
)

func TestChannelMemberIndexListPathPlansUseUserIndex(t *testing.T) {
	pool := testPool(t)
	ctx := context.Background()
	suffix := randomSuffix(t)
	users := NewUserStore(pool)
	owner := createTestUser(t, ctx, users, "+1887"+suffix+"61", "PlanIndexOwner", "")
	member := createTestUser(t, ctx, users, "+1887"+suffix+"62", "PlanIndexMember", "")
	var channelIDs []int64
	t.Cleanup(func() {
		if len(channelIDs) != 0 {
			_, _ = pool.Exec(ctx, "DELETE FROM channels WHERE id = ANY($1::bigint[])", channelIDs)
		}
		_, _ = pool.Exec(ctx, "DELETE FROM users WHERE id = ANY($1::bigint[])", []int64{owner.ID, member.ID})
	})

	channels := NewChannelStore(pool)
	publicAdmined, err := channels.CreateChannel(ctx, domain.CreateChannelRequest{
		CreatorUserID: owner.ID,
		Title:         "plan admined " + suffix,
		Megagroup:     true,
		Date:          1700000850,
	})
	if err != nil {
		t.Fatalf("create public admined: %v", err)
	}
	channelIDs = append(channelIDs, publicAdmined.Channel.ID)
	publicUsername := "planadmined" + suffix
	if _, err := channels.UpdateUsername(ctx, domain.UpdateChannelUsernameRequest{
		UserID:    owner.ID,
		ChannelID: publicAdmined.Channel.ID,
		Username:  publicUsername,
	}); err != nil {
		t.Fatalf("set public username: %v", err)
	}
	left, err := channels.CreateChannel(ctx, domain.CreateChannelRequest{
		CreatorUserID: owner.ID,
		Title:         "plan left " + suffix,
		Megagroup:     true,
		MemberUserIDs: []int64{member.ID},
		Date:          1700000851,
	})
	if err != nil {
		t.Fatalf("create left: %v", err)
	}
	channelIDs = append(channelIDs, left.Channel.ID)
	if _, err := channels.LeaveChannel(ctx, left.Channel.ID, member.ID, 1700000852); err != nil {
		t.Fatalf("leave channel: %v", err)
	}
	discussion, err := channels.CreateChannel(ctx, domain.CreateChannelRequest{
		CreatorUserID: owner.ID,
		Title:         "plan discussion " + suffix,
		Megagroup:     true,
		MemberUserIDs: []int64{member.ID},
		Date:          1700000853,
	})
	if err != nil {
		t.Fatalf("create discussion: %v", err)
	}
	channelIDs = append(channelIDs, discussion.Channel.ID)
	if _, err := channels.EditChannelAdmin(ctx, domain.EditChannelAdminRequest{
		UserID:    owner.ID,
		ChannelID: discussion.Channel.ID,
		MemberID:  member.ID,
		AdminRights: domain.ChannelAdminRights{
			PinMessages: true,
		},
		Date: 1700000854,
	}); err != nil {
		t.Fatalf("grant discussion admin: %v", err)
	}

	tx, err := pool.Begin(ctx)
	if err != nil {
		t.Fatalf("begin explain tx: %v", err)
	}
	defer func() { _ = tx.Rollback(ctx) }()
	if _, err := tx.Exec(ctx, "SET LOCAL enable_seqscan = off"); err != nil {
		t.Fatalf("disable seqscan: %v", err)
	}

	leftPlan := explainText(t, ctx, tx, `
SELECT channel_id
FROM user_channel_member_index
WHERE user_id = $1
  AND status = 'left'
  AND (broadcast OR megagroup)
  AND NOT deleted
ORDER BY left_at DESC, channel_id DESC
OFFSET $2
LIMIT $3
`, member.ID, 0, domain.MaxLeftChannelsLimit)
	requirePlanContains(t, leftPlan, "user_channel_member_index_left_idx")
	requirePlanNotContains(t, leftPlan, "channel_members_p")

	leftDetailPlan := explainText(t, ctx, tx, `
SELECT channel_id
FROM channel_members
WHERE user_id = $1
  AND channel_id = ANY($2::bigint[])
  AND status = 'left'
`, member.ID, []int64{left.Channel.ID})
	requireUniquePartitionCountAtMost(t, leftDetailPlan, `channel_members_p\d+`, 1)

	channelDetailPlan := explainText(t, ctx, tx, `
SELECT id
FROM channels
WHERE id = ANY($1::bigint[])
  AND NOT deleted
`, []int64{left.Channel.ID})
	requireUniquePartitionCountAtMost(t, channelDetailPlan, `channels_p\d+`, 1)

	usernameLookupPlan := explainText(t, ctx, tx, `
SELECT peer_id
FROM peer_usernames
WHERE username_lower = $1 AND peer_type = 'channel'
`, publicUsername)
	// 0150 adds peer_usernames_peer_order_idx, which covers this lookup as an
	// index-only scan; either index is an acceptable plan, a partition scan is not.
	if !strings.Contains(usernameLookupPlan, "peer_usernames_pkey") &&
		!strings.Contains(usernameLookupPlan, "peer_usernames_peer_order_idx") {
		t.Fatalf("username lookup plan = %s, want a peer_usernames index scan", usernameLookupPlan)
	}
	requirePlanNotMatches(t, usernameLookupPlan, `channels_p\d+`)

	usernameChannelDetailPlan := explainText(t, ctx, tx, `
SELECT id
FROM channels c
WHERE c.id = $1
  AND NOT c.deleted
`, publicAdmined.Channel.ID)
	requireUniquePartitionCountAtMost(t, usernameChannelDetailPlan, `channels_p\d+`, 1)
	requirePlanNotContains(t, usernameChannelDetailPlan, "Append")

	adminedPlan := explainText(t, ctx, tx, `
SELECT channel_id
FROM user_channel_member_index
WHERE user_id = $1
  AND status = 'active'
  AND role IN ('creator','admin')
  AND public_username
  AND NOT deleted
ORDER BY channel_id DESC
LIMIT $2
`, owner.ID, domain.MaxAdminedPublicChannels)
	requirePlanContains(t, adminedPlan, "user_channel_member_index_admined_public_idx")
	requirePlanNotContains(t, adminedPlan, "channel_members_p")

	discussionPlan := explainText(t, ctx, tx, `
SELECT channel_id
FROM user_channel_member_index
WHERE user_id = $1
  AND status = 'active'
  AND megagroup
  AND NOT broadcast
  AND NOT forum
  AND NOT deleted
  AND (role = 'creator' OR can_pin_messages)
ORDER BY channel_id DESC
LIMIT $2
`, member.ID, domain.MaxDiscussionGroupsLimit)
	requirePlanContains(t, discussionPlan, "user_channel_member_index_discussion_idx")
	requirePlanNotContains(t, discussionPlan, "channel_members_p")

	dialogCandidatePlan := explainText(t, ctx, tx, `
SELECT channel_id
FROM user_channel_member_index
WHERE user_id = $1
  AND status = 'active'
  AND NOT deleted
ORDER BY channel_id ASC
LIMIT $2
`, owner.ID, channelDialogCandidateLimit)
	requirePlanContains(t, dialogCandidatePlan, "user_channel_member_index")
	requirePlanNotContains(t, dialogCandidatePlan, "channel_members_p")

	dialogDetailPlan := explainText(t, ctx, tx, `
SELECT c.id,
       CASE WHEN c.top_message_id > m.available_min_id THEN c.top_message_id ELSE 0 END AS visible_top_id,
       CASE WHEN c.top_message_id > m.available_min_id THEN COALESCE(top_msg.message_date, d.top_message_date, c.date) ELSE 0 END AS visible_top_date
FROM channel_members m
JOIN channels c ON c.id = m.channel_id AND c.id = ANY($2::bigint[]) AND NOT c.deleted
LEFT JOIN channel_messages top_msg ON top_msg.channel_id = m.channel_id AND top_msg.channel_id = ANY($2::bigint[]) AND top_msg.id = c.top_message_id AND NOT top_msg.deleted
LEFT JOIN channel_dialogs d ON d.user_id = m.user_id AND d.channel_id = m.channel_id
WHERE m.user_id = $1
  AND m.channel_id = ANY($2::bigint[])
  AND m.status = 'active'
ORDER BY visible_top_date DESC,
         visible_top_id DESC,
         c.id DESC
LIMIT $3
`, owner.ID, []int64{publicAdmined.Channel.ID}, channelDialogQueryLimit)
	requireUniquePartitionCountAtMost(t, dialogDetailPlan, `channel_members_p\d+`, 1)
	requireUniquePartitionCountAtMost(t, dialogDetailPlan, `channels_p\d+`, 1)
	requireUniquePartitionCountAtMost(t, dialogDetailPlan, `channel_messages_p\d+`, 1)

	inactiveCandidatePlan := explainText(t, ctx, tx, `
SELECT channel_id
FROM user_channel_member_index
WHERE user_id = $1
  AND status = 'active'
  AND (broadcast OR megagroup)
  AND NOT deleted
ORDER BY channel_id ASC
LIMIT $2
`, owner.ID, channelDialogCandidateLimit)
	requirePlanContains(t, inactiveCandidatePlan, "user_channel_member_index")
	requirePlanNotContains(t, inactiveCandidatePlan, "channel_members_p")

	inactiveDetailPlan := explainText(t, ctx, tx, `
SELECT c.id,
       CASE WHEN c.top_message_id > m.available_min_id THEN c.top_message_id ELSE 0 END AS visible_top_id,
       CASE WHEN c.top_message_id > m.available_min_id THEN COALESCE(top_msg.message_date, d.top_message_date, c.date) ELSE GREATEST(c.date, m.joined_at) END AS visible_top_date
FROM channel_members m
JOIN channels c ON c.id = m.channel_id AND c.id = ANY($2::bigint[]) AND NOT c.deleted
LEFT JOIN channel_messages top_msg ON top_msg.channel_id = m.channel_id AND top_msg.channel_id = ANY($2::bigint[]) AND top_msg.id = c.top_message_id AND NOT top_msg.deleted
LEFT JOIN channel_dialogs d ON d.user_id = m.user_id AND d.channel_id = m.channel_id
WHERE m.user_id = $1
  AND m.channel_id = ANY($2::bigint[])
  AND m.status = 'active'
  AND (c.broadcast OR c.megagroup)
ORDER BY visible_top_date ASC,
         visible_top_id ASC,
         c.id ASC
LIMIT $3
`, owner.ID, []int64{publicAdmined.Channel.ID}, domain.MaxInactiveChannelsLimit)
	requireUniquePartitionCountAtMost(t, inactiveDetailPlan, `channel_members_p\d+`, 1)
	requireUniquePartitionCountAtMost(t, inactiveDetailPlan, `channels_p\d+`, 1)
	requireUniquePartitionCountAtMost(t, inactiveDetailPlan, `channel_messages_p\d+`, 1)

	mentionAffectedPlan := explainText(t, ctx, tx, `
SELECT DISTINCT user_id
FROM channel_unread_mention_index
WHERE channel_id = $1
  AND message_id = ANY($2::int[])
ORDER BY user_id ASC
`, publicAdmined.Channel.ID, []int32{1, 2})
	requirePlanContains(t, mentionAffectedPlan, "Index")
	requireUniquePartitionCountAtMost(t, mentionAffectedPlan, `channel_unread_mention_index_p\d+`, 1)
	requirePlanNotMatches(t, mentionAffectedPlan, `channel_unread_mentions_p\d+`)

	mentionDeleteBatchPlan := explainText(t, ctx, tx, `
WITH affected AS (
    SELECT DISTINCT unnest($3::bigint[]) AS user_id
),
deleted_mentions AS (
    DELETE FROM channel_unread_mentions um
    USING affected a
    WHERE um.user_id = ANY($3::bigint[])
      AND um.user_id = a.user_id
      AND um.channel_id = $1
      AND um.message_id = ANY($2::int[])
    RETURNING um.user_id, um.channel_id, um.message_id
),
deleted_index AS (
    DELETE FROM channel_unread_mention_index i
    USING affected a
    WHERE i.channel_id = $1
      AND i.user_id = a.user_id
      AND i.message_id = ANY($2::int[])
),
counts_before AS (
    SELECT user_id, COUNT(*)::int AS count
    FROM channel_unread_mentions
    WHERE channel_id = $1
      AND user_id = ANY($3::bigint[])
    GROUP BY user_id
),
deleted_counts AS (
    SELECT user_id, COUNT(*)::int AS count
    FROM deleted_mentions
    GROUP BY user_id
)
UPDATE channel_dialogs d
SET unread_mentions_count = GREATEST(COALESCE(c.count, 0) - COALESCE(dc.count, 0), 0),
    updated_at = now()
FROM affected a
LEFT JOIN counts_before c ON c.user_id = a.user_id
LEFT JOIN deleted_counts dc ON dc.user_id = a.user_id
WHERE d.user_id = ANY($3::bigint[])
  AND d.channel_id = $1
  AND d.user_id = a.user_id
`, publicAdmined.Channel.ID, []int32{1, 2}, []int64{member.ID})
	requireUniquePartitionCountAtMost(t, mentionDeleteBatchPlan, `channel_unread_mentions_p\d+`, 1)
	requireUniquePartitionCountAtMost(t, mentionDeleteBatchPlan, `channel_dialogs_p\d+`, 1)
	requireUniquePartitionCountAtMost(t, mentionDeleteBatchPlan, `channel_unread_mention_index_p\d+`, 1)
}