SHA256
поменял все названия таблиц и полей в таблицах на стиль только маленькие буквы и разделение через "_" . Все тесты проходят норм
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 — уникальный логин пользователя
|
|
device_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
|
|
device_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 — проекция активности
|
|
всё вычисляется детерминированно через триггеры |