Files
gochat/channels/shangwutong/db/migrations/001_init.up.sql
T
2026-08-12 22:58:46 +08:00

208 lines
8.9 KiB
SQL

CREATE TABLE accounts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
gochat_account_id INTEGER NOT NULL,
gochat_inbox_id INTEGER NOT NULL UNIQUE,
gochat_inbox_identifier TEXT NOT NULL,
config_version INTEGER NOT NULL,
applied_config_version INTEGER NOT NULL DEFAULT 0,
config_sync_status TEXT NOT NULL DEFAULT 'pending',
session_id TEXT NOT NULL,
username TEXT NOT NULL,
password TEXT NOT NULL,
pending_password TEXT,
credential_state TEXT NOT NULL DEFAULT 'ready',
enabled INTEGER NOT NULL DEFAULT 1,
desired_presence TEXT NOT NULL DEFAULT 'online',
actual_presence TEXT NOT NULL DEFAULT 'offline',
connection_status TEXT NOT NULL DEFAULT 'offline',
base_url TEXT,
site_id TEXT,
login_name TEXT,
ma_token TEXT,
maxwordid INTEGER NOT NULL DEFAULT -1,
maxotick INTEGER NOT NULL DEFAULT -1,
maxtmpid INTEGER NOT NULL DEFAULT -1,
gochat_hmac_token TEXT NOT NULL,
gochat_webhook_secret TEXT NOT NULL,
failure_count INTEGER NOT NULL DEFAULT 0,
last_error_code TEXT,
last_error_message TEXT,
last_login_at DATETIME,
last_heartbeat_at DATETIME,
last_config_sync_at DATETIME,
deleted_at DATETIME,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CHECK(config_sync_status IN ('pending', 'applied', 'rejected', 'deleted')),
CHECK(desired_presence IN ('online', 'busy', 'away', 'offline')),
CHECK(actual_presence IN ('online', 'busy', 'away', 'offline')),
CHECK(enabled IN (0, 1))
);
CREATE UNIQUE INDEX idx_accounts_active_swt_identity
ON accounts(session_id, username)
WHERE deleted_at IS NULL;
CREATE INDEX idx_accounts_runnable
ON accounts(enabled, desired_presence, deleted_at);
CREATE TABLE conversation_maps (
account_id INTEGER NOT NULL REFERENCES accounts(id),
swt_sid TEXT NOT NULL,
gochat_contact_source_id TEXT NOT NULL,
gochat_contact_id INTEGER,
gochat_conversation_id INTEGER,
gochat_display_id INTEGER,
swt_assignee_name TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(account_id, swt_sid)
);
CREATE TABLE inbound_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
account_id INTEGER NOT NULL REFERENCES accounts(id),
swt_sid TEXT NOT NULL,
seq_id INTEGER NOT NULL,
kind INTEGER NOT NULL,
swt_event_key TEXT NOT NULL UNIQUE,
event_subtype TEXT,
op_name TEXT,
text TEXT,
swt_timestamp TEXT,
raw_line TEXT NOT NULL,
normalized_payload TEXT,
mapping_strategy TEXT,
delivery_status TEXT NOT NULL DEFAULT 'pending',
attempts INTEGER NOT NULL DEFAULT 0,
next_attempt_at DATETIME,
gochat_message_id INTEGER,
last_error TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(account_id, swt_sid, kind, seq_id),
CHECK(delivery_status IN ('pending', 'delivering', 'delivered', 'ignored', 'failed'))
);
CREATE INDEX idx_inbound_events_ready
ON inbound_events(delivery_status, next_attempt_at, account_id, id);
CREATE TABLE message_maps (
account_id INTEGER NOT NULL REFERENCES accounts(id),
swt_sid TEXT NOT NULL,
swt_message_id TEXT,
swt_seq_id INTEGER NOT NULL,
kind INTEGER NOT NULL,
child_index INTEGER NOT NULL DEFAULT 0,
direction TEXT NOT NULL,
gochat_message_id INTEGER NOT NULL,
gochat_source_id TEXT,
content_fingerprint TEXT,
retracted_at DATETIME,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(account_id, swt_sid, kind, swt_seq_id, child_index),
CHECK(direction IN ('incoming', 'outgoing'))
);
CREATE INDEX idx_message_maps_gochat_message_id
ON message_maps(gochat_message_id);
CREATE UNIQUE INDEX idx_message_maps_swt_message_id
ON message_maps(account_id, swt_sid, swt_message_id)
WHERE swt_message_id IS NOT NULL;
CREATE UNIQUE INDEX idx_message_maps_gochat_source_id
ON message_maps(gochat_source_id)
WHERE gochat_source_id IS NOT NULL;
CREATE TABLE outbound_messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
account_id INTEGER NOT NULL REFERENCES accounts(id),
swt_sid TEXT NOT NULL,
event_id TEXT NOT NULL UNIQUE,
occurred_at DATETIME NOT NULL,
gochat_message_id INTEGER NOT NULL UNIQUE,
retry_version INTEGER NOT NULL DEFAULT 0,
message_type TEXT NOT NULL,
content TEXT,
payload TEXT NOT NULL,
delivery_status TEXT NOT NULL DEFAULT 'pending',
result_version INTEGER NOT NULL DEFAULT 0,
external_id TEXT,
external_error_code TEXT,
claimed_at DATETIME,
attempts INTEGER NOT NULL DEFAULT 0,
next_attempt_at DATETIME,
status_sync_status TEXT NOT NULL DEFAULT 'not_required',
status_sync_attempts INTEGER NOT NULL DEFAULT 0,
status_sync_next_at DATETIME,
status_reported_at DATETIME,
last_error TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CHECK(delivery_status IN ('pending', 'delivering', 'delivered', 'uncertain', 'failed')),
CHECK(status_sync_status IN ('not_required', 'pending', 'syncing', 'synced'))
);
CREATE INDEX idx_outbound_messages_ready
ON outbound_messages(delivery_status, next_attempt_at, account_id, id);
CREATE UNIQUE INDEX idx_outbound_one_delivering_per_account
ON outbound_messages(account_id)
WHERE delivery_status = 'delivering';
CREATE INDEX idx_outbound_status_sync_ready
ON outbound_messages(status_sync_status, status_sync_next_at, account_id, id);
CREATE TABLE outbound_parts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
outbound_message_id INTEGER NOT NULL REFERENCES outbound_messages(id) ON DELETE CASCADE,
part_index INTEGER NOT NULL,
part_type TEXT NOT NULL,
attachment_id INTEGER,
content TEXT,
data_url TEXT,
file_name TEXT,
file_size INTEGER,
voice INTEGER NOT NULL DEFAULT 0,
delivery_status TEXT NOT NULL DEFAULT 'pending',
external_id TEXT,
last_error TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(outbound_message_id, part_index),
CHECK(part_type IN ('text', 'image', 'file', 'audio', 'video', 'unsupported')),
CHECK(delivery_status IN ('pending', 'delivered', 'uncertain', 'failed')),
CHECK(voice IN (0, 1))
);
CREATE INDEX idx_outbound_parts_message
ON outbound_parts(outbound_message_id, part_index);
CREATE TABLE outbound_operations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
account_id INTEGER NOT NULL REFERENCES accounts(id),
swt_sid TEXT NOT NULL,
event_id TEXT NOT NULL UNIQUE,
operation TEXT NOT NULL,
payload TEXT NOT NULL,
occurred_at DATETIME NOT NULL,
delivery_status TEXT NOT NULL DEFAULT 'pending',
claimed_at DATETIME,
attempts INTEGER NOT NULL DEFAULT 0,
next_attempt_at DATETIME,
last_error TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CHECK(operation IN ('end_conversation', 'change_contact_name')),
CHECK(delivery_status IN ('pending', 'delivering', 'delivered', 'uncertain', 'failed'))
);
CREATE INDEX idx_outbound_operations_ready
ON outbound_operations(delivery_status, next_attempt_at, account_id, id);
CREATE UNIQUE INDEX idx_outbound_one_delivering_operation_per_account
ON outbound_operations(account_id)
WHERE delivery_status = 'delivering';