209 lines
6.9 KiB
Markdown
209 lines
6.9 KiB
Markdown
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 — проекция активности
|
||
всё вычисляется детерминированно через триггеры |