Міграція MySQL

MYSQL MIGRATION · DEV
ЗАГАЛЬНИЙ ПРОГРЕС МІГРАЦІЇ
0 / 41 кроків 0 / 5 фаз завершено
14
JSON файлів
1
Мігровано
3
Критичні
1
Середні
1
Прості
~2.2MB
Обсяг даних

check_circle Вже мігровано: Publisher

База даних
ua5web_publisher
Таблиці
publisher_folders, publisher_messages, publisher_migration_log
Міграції
4 міграції (001–004)
Шаблон
publisherStorageAdapter.js + publisherRepository.js
Підключення
mysql2/promise pool, connection.js
ENV перемикач
PUBLISHER_STORAGE_MODE=mysql

Фаза 1 — Nexus

Критична 0/9
Джерело
nexus-profiles.json (541 KB)
Таблиці
nexus_profiles, nexus_profile_static, nexus_profile_state, nexus_timeline_events
Записи
~20 профілів, ~500 подій таймлайну
Складність
Висока (вкладені обʼєкти, звʼязки 1:1 + 1:N)
  • Створити схему бази (4 таблиці з FK, індекси)SQL
  • Створити nexusRepository.js (маппери, CRUD, upsert)бекенд
  • Створити nexusStorageAdapter.js (перемикач JSON/MySQL)бекенд
  • Написати скрипт міграції: nexus-profiles.json → MySQLміграція
  • Оновити b5-nexus.js бекенд модульбекенд
  • Оновити anbu-bot/modules/5-nexus.jsбот
  • Оновити anbu-bot/modules/core/profile-manager.jsбот
  • Тест: читання/запис через адаптер, перевірка цілісностітест
  • Переключити NEXUS_STORAGE_MODE=mysql, деплойдеплой

Фаза 2 — Executor

Критична 0/8
Джерела
executor-history.json (95.9 KB), executor-stats.json (14.8 KB), executor-cards.json (12.6 KB), executor-sessions.json
Таблиці
executor_cards, executor_sessions, executor_session_participants, executor_points_adjustments, executor_user_stats
Записи
21 картка, 90+ сесій, 5 статистик
Складність
Середньо-висока (сесії з учасниками + коригування балів)
  • Створити схему бази (5 таблиць)SQL
  • Створити executorRepository.jsбекенд
  • Створити executorStorageAdapter.jsбекенд
  • Міграція: картки, історія, статистика, сесії → MySQLміграція
  • Оновити b3-executor.js бекенд модульбекенд
  • Оновити модулі executor в anbu-botбот
  • Тест: життєвий цикл сесій, бали, агрегація статистикитест
  • Переключити EXECUTOR_STORAGE_MODE=mysql, деплойдеплой

Фаза 3 — Challenger

Критична 0/8
Джерела
challenger-achievements.json (98.9 KB), challenger-activity.json (65 KB)
Таблиці
challenger_achievement_levels, _categories, _achievements, challenger_daily_activity, _streaks, _activity_history, _activity_metadata
Записи
47 досягнень, 5 активностей, щоденні скиди
Складність
Середня (щоденна активність + стріки + розблокування досягнень)
  • Створити схему бази (7 таблиць)SQL
  • Створити challengerRepository.jsбекенд
  • Створити challengerStorageAdapter.jsбекенд
  • Міграція: досягнення, активність, стріки → MySQLміграція
  • Оновити b6-challenger.js бекенд модульбекенд
  • Оновити модулі challenger в anbu-botбот
  • Тест: щоденний скид, підрахунок стріків, розблокування досягненьтест
  • Переключити CHALLENGER_STORAGE_MODE=mysql, деплойдеплой

Фаза 4 — Applicant + Observer

Середня 0/8
Джерела
applications.json (9.2 KB), members.json (1.1 KB)
Таблиці
applicant_applications, applicant_config, observer_members, observer_member_counter
Записи
7 заявок, 6 учасників
Складність
Проста (плоскі структури, мінімум даних)
  • Створити схему бази (4 таблиці)SQL
  • Створити applicantRepository.js + observerRepository.jsбекенд
  • Створити адаптери сховищабекенд
  • Міграція: заявки + учасники → MySQLміграція
  • Оновити b4-applicant.js + b1-observer.jsбекенд
  • Оновити модулі applicant + observer в anbu-botбот
  • Тест: потік заявок, лічильник учасниківтест
  • Переключити режими сховища, деплойдеплой

Фаза 5 — Paymaster + Очищення Publisher

Проста 0/8
Джерела
paymaster-drafts.json (1.2 KB), paymaster-history.json, paymaster-audit.json
Таблиці
paymaster_drafts, paymaster_history, paymaster_audit, paymaster_config
Записи
1 чернетка, порожня історія/аудит
Додатково
Видалити JSON fallback Publisher, прибрати застарілі файли
  • Створити схему бази (4 таблиці)SQL
  • Створити paymasterRepository.jsбекенд
  • Створити paymasterStorageAdapter.jsбекенд
  • Міграція: чернетки, історія, аудит → MySQLміграція
  • Оновити b7-paymaster.js + модулі ботабекенд
  • Видалити JSON fallback код Publisherочищення
  • Тест: потік paymaster, publisher без JSONтест
  • Переключити PAYMASTER_STORAGE_MODE=mysql, фінальний деплойдеплой

database Довідник схем

table_chartnexus_profilesочікує
КолонкаТипПримітки
idINT AUTO_INCREMENTPRIMARY KEY
user_idVARCHAR(20)UNIQUE NOT NULL
thread_idVARCHAR(20)
thread_urlVARCHAR(255)
created_atDATETIMECURRENT_TIMESTAMP
updated_atDATETIMEON UPDATE
table_chartnexus_profile_staticочікує
КолонкаТипПримітки
idINT AUTO_INCREMENTPRIMARY KEY
user_idVARCHAR(20)UNIQUE, FK → nexus_profiles
discord_usernameVARCHAR(100)
discord_global_nameVARCHAR(100)
first_joined_atDATETIME
account_created_atDATETIME
invite_codeVARCHAR(50)
invited_by_idVARCHAR(20)
member_numberINT
is_legacy_userBOOLEANDEFAULT FALSE
legacy_noteTEXT
table_chartnexus_profile_stateочікує
КолонкаТипПримітки
idINT AUTO_INCREMENTPRIMARY KEY
user_idVARCHAR(20)UNIQUE, FK → nexus_profiles
server_nicknameVARCHAR(255)
avatar_urlVARCHAR(512)
is_on_serverBOOLEANDEFAULT TRUE
is_bannedBOOLEANDEFAULT FALSE
current_tagVARCHAR(50)
current_rankVARCHAR(50)INDEX
reputationINTDEFAULT 0
pointsINTDEFAULT 0, INDEX
tasks_completedINTDEFAULT 0
tasks_failedINTDEFAULT 0
voice_time_minutesINTDEFAULT 0
messages_countINTDEFAULT 0
last_activeDATETIMEINDEX
warnings_totalINTDEFAULT 0
timeouts_totalINTDEFAULT 0
kicks_receivedINTDEFAULT 0
bans_receivedINTDEFAULT 0
achievementsJSONМасив ID
rolesJSONМасив ID
rank_historyJSONМасив обʼєктів
table_chartnexus_timeline_eventsочікує
КолонкаТипПримітки
idINT AUTO_INCREMENTPRIMARY KEY
event_idVARCHAR(50)UNIQUE
user_idVARCHAR(20)FK → nexus_profiles, INDEX
typeVARCHAR(50)INDEX
timestampDATETIMEINDEX
message_idVARCHAR(20)
dataJSONPayload події
table_chartexecutor_cardsочікує
КолонкаТипПримітки
idVARCHAR(20)PRIMARY KEY
nameVARCHAR(255)NOT NULL
descriptionTEXT
objectiveTEXT
typeVARCHAR(20)DEFAULT 'neutral'
categoryENUM('easy','medium','hard')INDEX
levelINTDEFAULT 1
pointsINTDEFAULT 0
reward_moneyINTDEFAULT 0
min_participantsINTDEFAULT 2
max_participantsINTDEFAULT 8
estimated_durationINTХвилини
is_activeBOOLEANDEFAULT TRUE, INDEX
table_chartexecutor_sessionsочікує
КолонкаТипПримітки
idINT AUTO_INCREMENTPRIMARY KEY
session_idVARCHAR(50)UNIQUE
card_idVARCHAR(20)FK → executor_cards
task_nameVARCHAR(255)
curator_idVARCHAR(20)INDEX
statusENUM('active','completed','cancelled')INDEX
total_pointsINTDEFAULT 0
completed_atDATETIMEINDEX
table_chartexecutor_session_participantsочікує
КолонкаТипПримітки
idINT AUTO_INCREMENTPRIMARY KEY
session_idVARCHAR(50)FK → executor_sessions
user_idVARCHAR(20)INDEX
is_curatorBOOLEANDEFAULT FALSE
confirmedBOOLEANDEFAULT FALSE
earned_pointsINTDEFAULT 0
final_pointsINTDEFAULT 0
table_chartexecutor_user_statsочікує
КолонкаТипПримітки
idINT AUTO_INCREMENTPRIMARY KEY
user_idVARCHAR(20)UNIQUE
total_pointsINTDEFAULT 0, INDEX
tasks_completedINTDEFAULT 0
mvp_countINTDEFAULT 0
penalties_receivedINTDEFAULT 0
bans_receivedINTDEFAULT 0
tasks_by_cardJSONСтатистика по картках
table_chartchallenger_achievementsочікує
КолонкаТипПримітки
idINTPRIMARY KEY
nameVARCHAR(255)NOT NULL
descriptionTEXT
iconVARCHAR(50)
levelINTFK → achievement_levels
categoryVARCHAR(50)FK → achievement_categories
pointsINTDEFAULT 0
conditionsJSONУмови розблокування
rewardJSONНеобовʼязкове
card_configJSONВізуальні налаштування
table_chartchallenger_daily_activityочікує
КолонкаТипПримітки
idINT AUTO_INCREMENTPRIMARY KEY
user_idVARCHAR(20)UNIQUE(user_id, date)
dateDATEINDEX
voice_minutesINTDEFAULT 0
messagesINTDEFAULT 0
reactions_givenINTDEFAULT 0
tasks_completedINTDEFAULT 0
total_pointsINTDEFAULT 0
is_activeBOOLEANDEFAULT FALSE
table_chartchallenger_streaksочікує
КолонкаТипПримітки
idINT AUTO_INCREMENTPRIMARY KEY
user_idVARCHAR(20)UNIQUE
current_streakINTDEFAULT 0, INDEX
longest_streakINTDEFAULT 0
last_active_dateDATE
streak_started_atDATE
table_chartapplicant_applicationsочікує
КолонкаТипПримітки
idVARCHAR(100)PRIMARY KEY
user_idVARCHAR(20)INDEX
usernameVARCHAR(100)
display_nameVARCHAR(200)
form_dataJSONNOT NULL
statusENUM('pending','accepted','rejected')INDEX
submitted_atDATETIMEINDEX
reviewed_atDATETIME
reviewed_byVARCHAR(20)
reject_reasonTEXT
table_chartobserver_membersочікує
КолонкаТипПримітки
idINT AUTO_INCREMENTPRIMARY KEY
numberINTNOT NULL
discord_idVARCHAR(20)UNIQUE
usernameVARCHAR(100)
joined_atDATETIMENOT NULL
sourceVARCHAR(50)DEFAULT 'real'
table_chartpaymaster_draftsочікує
КолонкаТипПримітки
idINT AUTO_INCREMENTPRIMARY KEY
week_idVARCHAR(20)UNIQUE
week_startDATETIME
week_endDATETIME
incomeJSON
deductionsJSON
distributableINTDEFAULT 0
directions_allocationJSON
publishedBOOLEANDEFAULT FALSE
created_atDATETIME
updated_atDATETIME
table_chartpaymaster_historyочікує
КолонкаТипПримітки
idINT AUTO_INCREMENTPRIMARY KEY
week_idVARCHAR(20)INDEX
dataJSONПовний знімок тижня
completed_atDATETIME
table_chartpaymaster_auditочікує
КолонкаТипПримітки
idINT AUTO_INCREMENTPRIMARY KEY
actionVARCHAR(100)NOT NULL
user_idVARCHAR(20)INDEX
detailsJSON
timestampDATETIMEINDEX

account_tree Архітектура міграції

swap_horizАдаптер сховища

Кожен модуль отримує адаптер, який зчитує *_STORAGE_MODE з ENV. Якщо json — читає/пише JSON файли. Якщо mysql — делегує в репозиторій.

Зразок: adapters/publisherStorageAdapter.js

storageРепозиторій

Чистий MySQL шар. Маппери fromDB() / toDB() конвертують camelCase ↔ snake_case. Використовує INSERT ... ON DUPLICATE KEY UPDATE для upsert.

Зразок: repositories/publisherRepository.js

hubПул підключень

Єдиний mysql2/promise пул в connection.js. Спільний для всіх репозиторіїв. Авто-міграція через ensureSchema() при старті.

Зразок: database/connection.js

move_downСкрипт міграції

Одноразовий скрипт для кожного модуля: читає JSON, трансформує дані, вставляє в MySQL. Логує в *_migration_log. Запускається вручну.

Зразок: database/migrations/migrate.js

tuneENV конфігурація

Кожен модуль керується незалежно:
PUBLISHER_STORAGE_MODE=mysql
NEXUS_STORAGE_MODE=json
EXECUTOR_STORAGE_MODE=json
CHALLENGER_STORAGE_MODE=json

Файл: .env

undoСтратегія відкату

JSON файли зберігаються як бекап. Переключити ENV назад на json і рестартнути — миттєвий відкат. Втрата даних неможлива під час переходу.

Міграція без простою