fix: sync system identity upsert idempotency
Sync telesrv c7c5a3d (fix(auth): make system identity upsert idempotent). Skipped telesrv docs changes per public sync rules.
This commit is contained in:
parent
004365ed48
commit
a6fe2574fe
2 changed files with 60 additions and 22 deletions
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -208,7 +209,7 @@ func TestLoginCodeDeliveryPostgresCommitAckLossRecoversFromReceipt(t *testing.T)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoginCodeDeliveryPostgresDifferentUsersDoNotRewriteOfficialUser(t *testing.T) {
|
func TestLoginCodeDeliveryPostgresDifferentUsersDoNotRewriteOfficialIdentity(t *testing.T) {
|
||||||
pool := testPool(t)
|
pool := testPool(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
firstUser := createLoginCodeDeliveryTestUser(t, ctx, pool, "official-row-first")
|
firstUser := createLoginCodeDeliveryTestUser(t, ctx, pool, "official-row-first")
|
||||||
|
|
@ -222,6 +223,16 @@ func TestLoginCodeDeliveryPostgresDifferentUsersDoNotRewriteOfficialUser(t *test
|
||||||
if err := pool.QueryRow(ctx, `SELECT xmin::text FROM users WHERE id = $1`, domain.OfficialSystemUserID).Scan(&xminBefore); err != nil {
|
if err := pool.QueryRow(ctx, `SELECT xmin::text FROM users WHERE id = $1`, domain.OfficialSystemUserID).Scan(&xminBefore); err != nil {
|
||||||
t.Fatalf("load official user xmin: %v", err)
|
t.Fatalf("load official user xmin: %v", err)
|
||||||
}
|
}
|
||||||
|
var usernameBefore, usernameXminBefore string
|
||||||
|
if err := pool.QueryRow(ctx, `
|
||||||
|
SELECT username_lower, xmin::text
|
||||||
|
FROM peer_usernames
|
||||||
|
WHERE peer_type = 'user' AND peer_id = $1`, domain.OfficialSystemUserID).Scan(&usernameBefore, &usernameXminBefore); err != nil {
|
||||||
|
t.Fatalf("load official username identity: %v", err)
|
||||||
|
}
|
||||||
|
if want := strings.ToLower(domain.OfficialSystemUser().Username); usernameBefore != want {
|
||||||
|
t.Fatalf("official username = %q, want %q", usernameBefore, want)
|
||||||
|
}
|
||||||
|
|
||||||
const workers = 12
|
const workers = 12
|
||||||
users := make([]domain.User, workers)
|
users := make([]domain.User, workers)
|
||||||
|
|
@ -256,6 +267,16 @@ func TestLoginCodeDeliveryPostgresDifferentUsersDoNotRewriteOfficialUser(t *test
|
||||||
if xminAfter != xminBefore {
|
if xminAfter != xminBefore {
|
||||||
t.Fatalf("official system user row was rewritten: xmin %s -> %s", xminBefore, xminAfter)
|
t.Fatalf("official system user row was rewritten: xmin %s -> %s", xminBefore, xminAfter)
|
||||||
}
|
}
|
||||||
|
var usernameAfter, usernameXminAfter string
|
||||||
|
if err := pool.QueryRow(ctx, `
|
||||||
|
SELECT username_lower, xmin::text
|
||||||
|
FROM peer_usernames
|
||||||
|
WHERE peer_type = 'user' AND peer_id = $1`, domain.OfficialSystemUserID).Scan(&usernameAfter, &usernameXminAfter); err != nil {
|
||||||
|
t.Fatalf("reload official username identity: %v", err)
|
||||||
|
}
|
||||||
|
if usernameAfter != usernameBefore || usernameXminAfter != usernameXminBefore {
|
||||||
|
t.Fatalf("official username identity was rewritten: %q/%s -> %q/%s", usernameBefore, usernameXminBefore, usernameAfter, usernameXminAfter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoginCodeDeliveryPostgresReceiptRetentionIsBoundedAndSeekOrdered(t *testing.T) {
|
func TestLoginCodeDeliveryPostgresReceiptRetentionIsBoundedAndSeekOrdered(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -66,29 +66,46 @@ func ensureOfficialSystemUserWithDB(ctx context.Context, db sqlcgen.DBTX, msg do
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if _, err := db.Exec(ctx, `
|
if _, err := db.Exec(ctx, `
|
||||||
WITH upserted AS (
|
WITH desired (
|
||||||
INSERT INTO users (id, access_hash, phone, first_name, last_name, username, country_code, verified, support, about, is_bot, bot_info_version)
|
id, access_hash, phone, first_name, last_name, username,
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
country_code, verified, support, about, is_bot, bot_info_version
|
||||||
ON CONFLICT (id) DO UPDATE SET
|
) AS (
|
||||||
access_hash = EXCLUDED.access_hash,
|
VALUES ($1::bigint, $2::bigint, $3::text, $4::text, $5::text, $6::text,
|
||||||
phone = EXCLUDED.phone,
|
$7::text, $8::boolean, $9::boolean, $10::text, $11::boolean, $12::integer)
|
||||||
first_name = EXCLUDED.first_name,
|
), upserted AS (
|
||||||
last_name = EXCLUDED.last_name,
|
INSERT INTO users (id, access_hash, phone, first_name, last_name, username, country_code, verified, support, about, is_bot, bot_info_version)
|
||||||
username = EXCLUDED.username,
|
SELECT id, access_hash, phone, first_name, last_name, username, country_code, verified, support, about, is_bot, bot_info_version
|
||||||
country_code = EXCLUDED.country_code,
|
FROM desired
|
||||||
verified = EXCLUDED.verified,
|
ON CONFLICT (id) DO UPDATE SET
|
||||||
support = EXCLUDED.support,
|
access_hash = EXCLUDED.access_hash,
|
||||||
about = EXCLUDED.about,
|
phone = EXCLUDED.phone,
|
||||||
is_bot = EXCLUDED.is_bot,
|
first_name = EXCLUDED.first_name,
|
||||||
bot_info_version = EXCLUDED.bot_info_version,
|
last_name = EXCLUDED.last_name,
|
||||||
updated_at = now()
|
username = EXCLUDED.username,
|
||||||
RETURNING id, lower(username) AS username_lower
|
country_code = EXCLUDED.country_code,
|
||||||
), deleted_old_username AS (
|
verified = EXCLUDED.verified,
|
||||||
DELETE FROM peer_usernames
|
support = EXCLUDED.support,
|
||||||
WHERE peer_type = 'user' AND peer_id = (SELECT id FROM upserted)
|
about = EXCLUDED.about,
|
||||||
|
is_bot = EXCLUDED.is_bot,
|
||||||
|
bot_info_version = EXCLUDED.bot_info_version,
|
||||||
|
updated_at = now()
|
||||||
|
WHERE (
|
||||||
|
users.access_hash, users.phone, users.first_name, users.last_name,
|
||||||
|
users.username, users.country_code, users.verified, users.support,
|
||||||
|
users.about, users.is_bot, users.bot_info_version
|
||||||
|
) IS DISTINCT FROM (
|
||||||
|
EXCLUDED.access_hash, EXCLUDED.phone, EXCLUDED.first_name, EXCLUDED.last_name,
|
||||||
|
EXCLUDED.username, EXCLUDED.country_code, EXCLUDED.verified, EXCLUDED.support,
|
||||||
|
EXCLUDED.about, EXCLUDED.is_bot, EXCLUDED.bot_info_version
|
||||||
|
)
|
||||||
)
|
)
|
||||||
INSERT INTO peer_usernames (username_lower, peer_type, peer_id)
|
INSERT INTO peer_usernames (username_lower, peer_type, peer_id)
|
||||||
SELECT username_lower, 'user', id FROM upserted
|
SELECT lower(username), 'user', id
|
||||||
|
FROM desired
|
||||||
|
ON CONFLICT (peer_type, peer_id) DO UPDATE SET
|
||||||
|
username_lower = EXCLUDED.username_lower,
|
||||||
|
updated_at = now()
|
||||||
|
WHERE peer_usernames.username_lower IS DISTINCT FROM EXCLUDED.username_lower
|
||||||
`, u.ID, u.AccessHash, u.Phone, u.FirstName, u.LastName, u.Username, u.CountryCode, u.Verified, u.Support, u.About, u.Bot, u.BotInfoVersion); err != nil {
|
`, u.ID, u.AccessHash, u.Phone, u.FirstName, u.LastName, u.Username, u.CountryCode, u.Verified, u.Support, u.About, u.Bot, u.BotInfoVersion); err != nil {
|
||||||
return fmt.Errorf("ensure official system user: %w", err)
|
return fmt.Errorf("ensure official system user: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue