feat: migrate IM identity and snowflake primary keys

This commit is contained in:
richjohnrambo
2026-08-18 01:15:21 +08:00
parent db322d80dd
commit bf562c7d56
27 changed files with 1071 additions and 482 deletions
+32 -7
View File
@@ -7,6 +7,7 @@
-- 2. Tenant-scoped business tables live in each tenant database and do not include tenant_id.
-- 3. This file is for review and manual execution. Existing legacy columns/indexes should be checked before ALTER/DROP.
-- 4. Table definitions are aligned with server/db/mysql/adapter.go plus im_verification_codes used by chapter 1 verification APIs.
-- 5. Non-auto-increment BIGINT primary keys are generated by the server Snowflake generator.
SET NAMES utf8mb4;
@@ -54,12 +55,14 @@ CREATE TABLE IF NOT EXISTS hotgo.im_tenant_config (
-- ============================================================
CREATE TABLE IF NOT EXISTS tinode.im_user_security (
id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
auth_version INT NOT NULL DEFAULT 1,
password_updated_at DATETIME(3),
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (user_id)
PRIMARY KEY (id),
UNIQUE INDEX uk_im_user_security_user (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE IF NOT EXISTS tinode.im_verification_codes (
@@ -125,6 +128,7 @@ CREATE TABLE IF NOT EXISTS tinode.im_action_tokens (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE IF NOT EXISTS tinode.im_youth_mode_settings (
id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
purpose VARCHAR(64) NOT NULL,
password_hash VARBINARY(255) NOT NULL,
@@ -136,7 +140,8 @@ CREATE TABLE IF NOT EXISTS tinode.im_youth_mode_settings (
locked_until DATETIME(3),
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (user_id, purpose)
PRIMARY KEY (id),
UNIQUE INDEX uk_im_youth_mode_settings_user_purpose (user_id, purpose)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- ============================================================
@@ -234,6 +239,7 @@ CREATE TABLE IF NOT EXISTS tinode.im_friend_requests (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE IF NOT EXISTS tinode.im_friendships (
id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
peer_id BIGINT NOT NULL,
status VARCHAR(16) NOT NULL,
@@ -241,16 +247,19 @@ CREATE TABLE IF NOT EXISTS tinode.im_friendships (
topic CHAR(25) NOT NULL DEFAULT '',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (user_id, peer_id),
PRIMARY KEY (id),
UNIQUE INDEX uk_im_friendships_pair (user_id, peer_id),
INDEX idx_im_friendships_peer (peer_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE IF NOT EXISTS tinode.im_user_blocks (
id BIGINT NOT NULL,
blocker_id BIGINT NOT NULL,
blocked_id BIGINT NOT NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (blocker_id, blocked_id),
PRIMARY KEY (id),
UNIQUE INDEX uk_im_user_blocks_pair (blocker_id, blocked_id),
INDEX idx_im_user_blocks_blocked (blocked_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
@@ -553,6 +562,7 @@ CREATE TABLE IF NOT EXISTS tinode.im_mailbox_submissions (
-- ============================================================
CREATE TABLE IF NOT EXISTS tinode.im_user_profiles (
id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
avatar_file_id VARCHAR(64) NOT NULL DEFAULT '',
nickname VARCHAR(64) NOT NULL DEFAULT '',
@@ -560,14 +570,26 @@ CREATE TABLE IF NOT EXISTS tinode.im_user_profiles (
signature VARCHAR(256) NOT NULL DEFAULT '',
gender VARCHAR(16) NOT NULL DEFAULT '',
region VARCHAR(128) NOT NULL DEFAULT '',
email VARCHAR(128) NOT NULL DEFAULT '',
public_account VARCHAR(64) NOT NULL DEFAULT '',
version INT NOT NULL DEFAULT 1,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (user_id)
PRIMARY KEY (id),
UNIQUE INDEX uk_im_user_profiles_user (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- Existing database migration (the application performs the same migration
-- idempotently at startup):
-- 1. Add im_users.phone VARCHAR(32) NULL and a UNIQUE index.
-- 2. Add im_user_profiles.email VARCHAR(128) NOT NULL DEFAULT ''.
-- 3. Backfill phone/email from validated im_credentials first, then use
-- tel:/email: rows in im_usertags as a legacy fallback.
-- 4. Drop im_usertags and im_users.tags only after the backfill is verified.
-- im_topics.tags and im_topictags are topic discovery data and must be retained.
CREATE TABLE IF NOT EXISTS tinode.im_user_privacy_settings (
id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
add_me_methods JSON,
profile_visibility VARCHAR(32) NOT NULL DEFAULT 'friends',
@@ -576,7 +598,8 @@ CREATE TABLE IF NOT EXISTS tinode.im_user_privacy_settings (
version INT NOT NULL DEFAULT 1,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (user_id)
PRIMARY KEY (id),
UNIQUE INDEX uk_im_user_privacy_settings_user (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE IF NOT EXISTS tinode.im_app_releases (
@@ -599,6 +622,7 @@ CREATE TABLE IF NOT EXISTS tinode.im_app_releases (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE IF NOT EXISTS tinode.im_device_push_tokens (
id BIGINT NOT NULL,
device_id VARCHAR(128) NOT NULL,
user_id BIGINT NOT NULL,
provider VARCHAR(32) NOT NULL,
@@ -607,7 +631,8 @@ CREATE TABLE IF NOT EXISTS tinode.im_device_push_tokens (
platform VARCHAR(32) NOT NULL DEFAULT '',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (device_id),
PRIMARY KEY (id),
UNIQUE INDEX uk_im_device_push_tokens_device (device_id),
UNIQUE INDEX uk_im_device_push_tokens_provider_token (provider, token),
INDEX idx_im_device_push_tokens_user (user_id, updated_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;