6.9 KiB
SHiNE — структура БД (актуальная версия)
Перечень таблиц и назначение
solana_users Справочник пользователей: логин + ключ устройства + (опционально) Solana-ключ. Базовая таблица, используется как FK почти везде.
active_sessions Активные сессии авторизации/работы клиента: секреты, тайминги, WebPush-данные, IP и информация о клиенте.
users_params Хранилище актуальных параметров пользователя. Для каждой пары (login, param) хранится только самая новая версия по time_ms.
ip_geo_cache Кеш геолокации по IP для снижения нагрузки на внешние сервисы.
blockchain_state Агрегированное состояние блокчейна по blockchain_name: лимиты, текущий размер, последний глобальный блок и состояние линий 0..7.
blocks Журнал всех блоков и сообщений. Содержит историю событий: тексты, реакции, ответы, связи. PRIMARY KEY намеренно отсутствует.
connections_state ⭐ Актуальное состояние связей между пользователями (друг / контакт / подписка). Обновляется автоматически на основе событий из blocks.
message_stats ⭐ Агрегированные счётчики лайков и ответов на конкретные сообщения. Поддерживается триггерами из blocks.
Таблицы подробно
solana_users login — TEXT PK — уникальный логин пользователя client_key — TEXT NOT NULL — публичный ключ устройства (Base64(32) / HEX(64)) solana_key — TEXT NULL — публичный ключ Solana-аккаунта
active_sessions session_id — TEXT PK — идентификатор сессии login — TEXT NOT NULL, FK → solana_users(login) session_pwd — TEXT NOT NULL — секрет сессии storage_pwd — TEXT NOT NULL — секрет storage session_created_at_ms — INTEGER NOT NULL last_authirificated_at_ms — INTEGER NOT NULL push_endpoint — TEXT NULL push_p256dh_key — TEXT NULL push_auth_key — TEXT NULL client_ip — TEXT NULL client_info_from_client — TEXT NULL client_info_from_request — TEXT NULL user_language — TEXT NULL
users_params login — TEXT NOT NULL, FK → solana_users(login) param — TEXT NOT NULL time_ms — INTEGER NOT NULL value — TEXT NOT NULL client_key — TEXT NULL signature — TEXT NULL
Ограничение: UNIQUE(login, param)
Логика: обновление принимается только если excluded.time_ms > users_params.time_ms
ip_geo_cache ip — TEXT PK geo — TEXT NULL updated_at_ms — INTEGER NOT NULL
blockchain_state blockchain_name — TEXT PK login — TEXT NOT NULL, FK → solana_users(login) blockchain_key — TEXT NOT NULL size_limit — INTEGER NOT NULL file_size_bytes — INTEGER NOT NULL last_global_number — INTEGER NOT NULL (-1 = genesis) last_global_hash — TEXT NOT NULL updated_at_ms — INTEGER NOT NULL
Линии 0..7: для каждой линии: lineX_last_number lineX_last_hash
blocks login — TEXT NOT NULL bch_name — TEXT NOT NULL block_global_number — INTEGER NOT NULL block_global_pre_hash — TEXT NOT NULL block_line_index — INTEGER NOT NULL block_line_number — INTEGER NOT NULL block_line_pre_hash — TEXT NOT NULL msg_type — INTEGER NOT NULL msg_sub_type — INTEGER NOT NULL block_bytes — BLOB NULL
Ссылка на другой блок (nullable): to_login to_bch_name to_block_global_number to_block_hash
connections_state ⭐ Текущее агрегированное состояние связей.
login — TEXT NOT NULL rel_type — INTEGER NOT NULL 10 = FRIEND 20 = CONTACT 30 = FOLLOW to_login — TEXT NOT NULL to_bch_name — TEXT NOT NULL to_block_global_number — INTEGER NULL to_block_hash — TEXT NULL
Ограничение: UNIQUE(login, rel_type, to_login)
message_stats ⭐ Счётчики активности по целевому сообщению.
to_login — TEXT NOT NULL to_bch_name — TEXT NOT NULL to_block_global_number — INTEGER NOT NULL to_block_hash — TEXT NOT NULL likes_count — INTEGER NOT NULL DEFAULT 0 replies_count — INTEGER NOT NULL DEFAULT 0
UNIQUE: (to_login, to_bch_name, to_block_global_number, to_block_hash)
Триггеры БД (полная логика)
3.1 Связи пользователей trg_blocks_connection_state_ai AFTER INSERT ON blocks
Условие: msg_type = 3 (connection)
Добавление / обновление связи msg_sub_type IN (10,20,30) выполняется UPSERT в connections_state
Удаление связи msg_sub_type IN (11,21,31) удаляется соответствующая связь: 11 → 10 21 → 20 31 → 30
Итог: blocks — журнал событий connections_state — всегда актуальное состояние
3.2 Подсчёт лайков ⭐ trg_blocks_message_stats_like_ai AFTER INSERT ON blocks
Условие: msg_type = 2 (reaction) msg_sub_type = 1 (like)
Действие: определяется цель по to_bch_name, to_block_global_number, to_block_hash to_login вычисляется как substr(to_bch_name, 1, length(to_bch_name) - 3) выполняется UPSERT в message_stats likes_count += 1
3.3 Подсчёт ответов ⭐ trg_blocks_message_stats_reply_ai AFTER INSERT ON blocks
Условие: msg_type = 1 (text) msg_sub_type = 2 (reply)
Действие: цель определяется аналогично лайкам выполняется UPSERT в message_stats replies_count += 1
Индексы (смысл)
idx_solana_users_login — поиск пользователя idx_active_sessions_login — сессии пользователя idx_users_params_login — параметры пользователя idx_ip_geo_cache_updated_at — чистка кеша idx_blockchain_state_login — блокчейны пользователя idx_blockchain_state_updated_at — обслуживание idx_blocks_chain_global — чтение цепочки idx_blocks_to_target — реакции / ответы idx_message_stats_target — быстрый доступ к счётчикам
Итоговая модель мышления
blocks — неизменяемый журнал событий connections_state — проекция связей message_stats — проекция активности всё вычисляется детерминированно через триггеры