chore: refresh gramsrv public release
This commit is contained in:
parent
75cebe8dbf
commit
70b6820474
1274 changed files with 378751 additions and 59919 deletions
|
|
@ -2,6 +2,7 @@ package postgres
|
|||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
|
@ -37,16 +38,21 @@ func TestMessagePartitionSeekPlansUseIndexes(t *testing.T) {
|
|||
})
|
||||
|
||||
messages := NewMessageStore(pool)
|
||||
var first domain.SendPrivateTextResult
|
||||
for i := 0; i < 3; i++ {
|
||||
if _, err := messages.SendPrivateText(ctx, domain.SendPrivateTextRequest{
|
||||
sent, err := messages.SendPrivateText(ctx, domain.SendPrivateTextRequest{
|
||||
SenderUserID: sender.ID,
|
||||
RecipientUserID: recipient.ID,
|
||||
RandomID: int64(9000 + i),
|
||||
Message: "plan check",
|
||||
Date: 1700000300 + i,
|
||||
}); err != nil {
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("seed message %d: %v", i, err)
|
||||
}
|
||||
if i == 0 {
|
||||
first = sent
|
||||
}
|
||||
}
|
||||
if _, err := pool.Exec(ctx, `
|
||||
UPDATE dispatch_outbox
|
||||
|
|
@ -77,7 +83,7 @@ WHERE owner_user_id = $1
|
|||
ORDER BY box_id DESC
|
||||
LIMIT 20
|
||||
`, recipient.ID, sender.ID, 100000)
|
||||
requirePlanUsesPartitionIndex(t, historyPlan, "message_boxes")
|
||||
requirePlanUsesIndex(t, historyPlan, "message_boxes")
|
||||
requirePlanNotContains(t, historyPlan, "Append")
|
||||
|
||||
updatesPlan := explainText(t, ctx, tx, `
|
||||
|
|
@ -88,12 +94,108 @@ WHERE user_id = $1
|
|||
ORDER BY pts ASC
|
||||
LIMIT 100
|
||||
`, recipient.ID, 0)
|
||||
requirePlanUsesPartitionIndex(t, updatesPlan, "user_update_events")
|
||||
requirePlanUsesIndex(t, updatesPlan, "user_update_events")
|
||||
requirePlanNotContains(t, updatesPlan, "Append")
|
||||
|
||||
updateDetailPlan := explainText(t, ctx, tx, `
|
||||
SELECT
|
||||
e.pts,
|
||||
COALESCE(m.box_id, 0)::int AS message_id,
|
||||
COALESCE(m.fwd_from_peer_type, '')::text AS fwd_from_peer_type,
|
||||
COALESCE(m.fwd_from_peer_id, 0)::bigint AS fwd_from_peer_id,
|
||||
COALESCE(m.reply_to_peer_type, '')::text AS reply_to_peer_type,
|
||||
COALESCE(m.reply_to_peer_id, 0)::bigint AS reply_to_peer_id,
|
||||
COALESCE(peer_u.id, 0)::bigint AS peer_user_id,
|
||||
COALESCE(from_u.id, 0)::bigint AS from_user_id,
|
||||
COALESCE(fwd_u.id, 0)::bigint AS fwd_user_id,
|
||||
COALESCE(reply_u.id, 0)::bigint AS reply_user_id
|
||||
FROM user_update_events e
|
||||
LEFT JOIN message_boxes m ON m.owner_user_id = e.user_id AND m.box_id = e.message_box_id
|
||||
LEFT JOIN users peer_u ON m.peer_type = 'user' AND peer_u.id = m.peer_id
|
||||
LEFT JOIN users from_u ON from_u.id = m.from_user_id
|
||||
LEFT JOIN users fwd_u ON m.fwd_from_peer_type = 'user' AND fwd_u.id = m.fwd_from_peer_id
|
||||
LEFT JOIN users reply_u ON m.reply_to_peer_type = 'user' AND reply_u.id = m.reply_to_peer_id
|
||||
WHERE e.user_id = $1
|
||||
AND e.pts > $2
|
||||
ORDER BY e.pts ASC
|
||||
LIMIT 100
|
||||
`, recipient.ID, 0)
|
||||
requirePlanUsesIndex(t, updateDetailPlan, "user_update_events")
|
||||
requireUniquePartitionCountAtMost(t, updateDetailPlan, `message_boxes_p\d+`, 1)
|
||||
requirePlanNotContains(t, updateDetailPlan, "channels_p")
|
||||
|
||||
batchDispatchDetailPlan := explainText(t, ctx, tx, `
|
||||
SELECT
|
||||
e.pts,
|
||||
COALESCE(m.box_id, 0)::int AS message_id,
|
||||
COALESCE(m.fwd_from_peer_type, '')::text AS fwd_from_peer_type,
|
||||
COALESCE(m.fwd_from_peer_id, 0)::bigint AS fwd_from_peer_id,
|
||||
COALESCE(m.reply_to_peer_type, '')::text AS reply_to_peer_type,
|
||||
COALESCE(m.reply_to_peer_id, 0)::bigint AS reply_to_peer_id,
|
||||
COALESCE(peer_u.id, 0)::bigint AS peer_user_id,
|
||||
COALESCE(from_u.id, 0)::bigint AS from_user_id,
|
||||
COALESCE(fwd_u.id, 0)::bigint AS fwd_user_id,
|
||||
COALESCE(reply_u.id, 0)::bigint AS reply_user_id
|
||||
FROM unnest($1::bigint[]) WITH ORDINALITY AS u(user_id, ord)
|
||||
JOIN unnest($2::int[]) WITH ORDINALITY AS p(pts, ord) USING (ord)
|
||||
JOIN user_update_events e ON e.user_id = u.user_id AND e.pts = p.pts
|
||||
LEFT JOIN message_boxes m ON m.owner_user_id = e.user_id AND m.box_id = e.message_box_id
|
||||
LEFT JOIN users peer_u ON m.peer_type = 'user' AND peer_u.id = m.peer_id
|
||||
LEFT JOIN users from_u ON from_u.id = m.from_user_id
|
||||
LEFT JOIN users fwd_u ON m.fwd_from_peer_type = 'user' AND fwd_u.id = m.fwd_from_peer_id
|
||||
LEFT JOIN users reply_u ON m.reply_to_peer_type = 'user' AND reply_u.id = m.reply_to_peer_id
|
||||
`, []int64{recipient.ID}, []int32{int32(first.RecipientMessage.Pts)})
|
||||
requirePlanNotContains(t, batchDispatchDetailPlan, "channels_p")
|
||||
|
||||
visibleByPrivatePlan := explainText(t, ctx, tx, `
|
||||
SELECT box_id
|
||||
FROM message_boxes
|
||||
WHERE owner_user_id = ANY($1::bigint[])
|
||||
AND message_sender_id = $2::bigint
|
||||
AND private_message_id = $3::bigint
|
||||
AND NOT deleted
|
||||
ORDER BY owner_user_id ASC, box_id ASC
|
||||
FOR UPDATE
|
||||
`, []int64{sender.ID, recipient.ID}, sender.ID, first.SenderMessage.UID)
|
||||
requirePlanUsesIndex(t, visibleByPrivatePlan, "message_boxes")
|
||||
requireUniquePartitionCountAtMost(t, visibleByPrivatePlan, `message_boxes_p\d+`, 2)
|
||||
|
||||
deleteByPrivatePlan := explainText(t, ctx, tx, `
|
||||
WITH requested AS (
|
||||
SELECT
|
||||
($1::bigint[])[i] AS message_sender_id,
|
||||
($2::bigint[])[i] AS private_message_id,
|
||||
($3::bigint[])[i] AS owner_user_id
|
||||
FROM generate_subscripts($2::bigint[], 1) AS g(i)
|
||||
WHERE i <= cardinality($1::bigint[])
|
||||
AND i <= cardinality($3::bigint[])
|
||||
),
|
||||
deduped AS (
|
||||
SELECT DISTINCT message_sender_id, private_message_id, owner_user_id
|
||||
FROM requested
|
||||
WHERE owner_user_id <> 0
|
||||
),
|
||||
updated AS (
|
||||
UPDATE message_boxes m
|
||||
SET deleted = true
|
||||
FROM deduped d
|
||||
WHERE m.owner_user_id = ANY($3::bigint[])
|
||||
AND m.owner_user_id = d.owner_user_id
|
||||
AND m.message_sender_id = d.message_sender_id
|
||||
AND m.private_message_id = d.private_message_id
|
||||
AND NOT m.deleted
|
||||
RETURNING m.owner_user_id, m.box_id
|
||||
)
|
||||
SELECT owner_user_id, box_id
|
||||
FROM updated
|
||||
ORDER BY owner_user_id ASC, box_id ASC
|
||||
`, []int64{sender.ID, sender.ID}, []int64{first.SenderMessage.UID, first.SenderMessage.UID}, []int64{sender.ID, recipient.ID})
|
||||
requirePlanUsesIndex(t, deleteByPrivatePlan, "message_boxes")
|
||||
requireUniquePartitionCountAtMost(t, deleteByPrivatePlan, `message_boxes_p\d+`, 2)
|
||||
|
||||
dispatchPlan := explainText(t, ctx, tx, `
|
||||
WITH picked AS (
|
||||
SELECT target_user_id, id
|
||||
SELECT target_user_id, pts, id
|
||||
FROM dispatch_outbox
|
||||
WHERE (
|
||||
status = 'pending'
|
||||
|
|
@ -107,12 +209,30 @@ WITH picked AS (
|
|||
LIMIT 100
|
||||
FOR UPDATE SKIP LOCKED
|
||||
)
|
||||
SELECT target_user_id, id
|
||||
SELECT target_user_id, pts, id
|
||||
FROM picked
|
||||
`)
|
||||
requirePlanContains(t, dispatchPlan, "dispatch_outbox_p")
|
||||
requirePlanContains(t, dispatchPlan, "dispatch_outbox")
|
||||
requirePlanContains(t, dispatchPlan, "Index")
|
||||
requirePlanNotMatches(t, dispatchPlan, `dispatch_outbox_p\d+`)
|
||||
requirePlanNotContains(t, dispatchPlan, "Seq Scan")
|
||||
|
||||
failedCleanupPlan := explainText(t, ctx, tx, `
|
||||
WITH doomed AS (
|
||||
SELECT target_user_id, id
|
||||
FROM dispatch_outbox
|
||||
WHERE status = 'failed'
|
||||
AND updated_at < now() - interval '1 day'
|
||||
ORDER BY updated_at ASC, target_user_id ASC, id ASC
|
||||
LIMIT 100
|
||||
)
|
||||
SELECT target_user_id, id
|
||||
FROM doomed
|
||||
`)
|
||||
requirePlanContains(t, failedCleanupPlan, "dispatch_outbox")
|
||||
requirePlanContains(t, failedCleanupPlan, "Index")
|
||||
requirePlanNotMatches(t, failedCleanupPlan, `dispatch_outbox_p\d+`)
|
||||
requirePlanNotContains(t, failedCleanupPlan, "Seq Scan")
|
||||
}
|
||||
|
||||
func explainText(t *testing.T, ctx context.Context, tx pgx.Tx, query string, args ...any) string {
|
||||
|
|
@ -138,9 +258,11 @@ func explainText(t *testing.T, ctx context.Context, tx pgx.Tx, query string, arg
|
|||
return b.String()
|
||||
}
|
||||
|
||||
func requirePlanUsesPartitionIndex(t *testing.T, plan, table string) {
|
||||
// requirePlanUsesIndex 断言计划在指定表上走索引扫描、未退化为 Seq Scan。
|
||||
// 去分区后这些表都是普通表(不再有 *_pNN 子分区),故只校验「命中目标表 + 用了索引 + 无 Seq Scan」。
|
||||
func requirePlanUsesIndex(t *testing.T, plan, table string) {
|
||||
t.Helper()
|
||||
requirePlanContains(t, plan, table+"_p")
|
||||
requirePlanContains(t, plan, table)
|
||||
requirePlanContains(t, plan, "Index")
|
||||
requirePlanNotContains(t, plan, "Seq Scan")
|
||||
}
|
||||
|
|
@ -158,3 +280,26 @@ func requirePlanNotContains(t *testing.T, plan string, needle string) {
|
|||
t.Fatalf("plan contains %q:\n%s", needle, plan)
|
||||
}
|
||||
}
|
||||
|
||||
func requirePlanNotMatches(t *testing.T, plan string, pattern string) {
|
||||
t.Helper()
|
||||
re := regexp.MustCompile(pattern)
|
||||
if re.MatchString(plan) {
|
||||
t.Fatalf("plan matches %q:\n%s", pattern, plan)
|
||||
}
|
||||
}
|
||||
|
||||
func requireUniquePartitionCountAtMost(t *testing.T, plan, pattern string, max int) {
|
||||
t.Helper()
|
||||
re := regexp.MustCompile(pattern)
|
||||
matches := re.FindAllString(plan, -1)
|
||||
seen := make(map[string]struct{}, len(matches))
|
||||
for _, match := range matches {
|
||||
seen[match] = struct{}{}
|
||||
}
|
||||
// 去分区后这些表已是普通表:0 处 *_pNN 命中是预期(合格)。保留本断言作为回归护栏——
|
||||
// 若某天意外重新引入分区且单查询触及 >max 个分区,这里会炸出来。
|
||||
if len(seen) > max {
|
||||
t.Fatalf("plan touches %d unique partitions, want <= %d:\n%s", len(seen), max, plan)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue