join colonies
Присоединяйтесь к колониям — техническая документация
🎯 Обзор
Функция «Присоединиться к колониям» позволяет объединить две пчелиные семьи путем перемещения ящиков из исходного улья в целевой, с опциями управления матками, автоматической фильтрацией типов ящиков и полным историческим отслеживанием. Трансляция событий в реальном времени обеспечивает согласованность пользовательского интерфейса во всех сеансах.
🏗️ Архитектура
Компоненты
- JoinColonyModal: компонент React (260 строк) с двухпанельным сравнением кустов.
- joinHives: мутация GraphQL с проверкой и атомарными операциями.
- event-stream-filter: трансляция событий в реальном времени для обновлений пользовательского интерфейса.
Услуги
- swarm-api: основная логика слияния, перемещение блоков, обновления статуса.
- web-app: пользовательский интерфейс frontend с интерактивным переключением типа слияния.
- Redis: pub/sub для трансляции событий в реальном времени.
- event-stream-filter: соединения WebSocket для обновлений в реальном времени.
Поток данных
graph LR
A[Web App] -->|joinHives mutation| B[GraphQL Router]
B --> C[swarm-api]
C -->|BEGIN TRANSACTION| D[MySQL]
C -->|Filter boxes| D
C -->|Move boxes to target| D
C -->|Update hive status| D
C -->|Record merge metadata| D
D -->|COMMIT| C
C --> E[Redis pub/sub]
E --> F[event-stream-filter]
F -->|WebSocket| G[Connected Clients]
C --> B
B --> A
📋 Технические характеристики
Схема базы данных
ALTER TABLE hives
ADD COLUMN merged_into_hive_id INT UNSIGNED NULL,
ADD COLUMN merge_date DATETIME NULL,
ADD COLUMN merge_type ENUM('both_queens', 'source_queen_kept', 'target_queen_kept') NULL,
ADD INDEX idx_merged_into_hive_id (merged_into_hive_id);
GraphQL API
Мутация
mutation JoinHives($sourceHiveId: ID!, $targetHiveId: ID!, $mergeType: MergeType!) {
joinHives(
sourceHiveId: $sourceHiveId
targetHiveId: $targetHiveId
mergeType: $mergeType
) {
id
name
status
mergedIntoHiveId
mergeDate
mergeType
mergedFromHives {
id
name
mergeDate
mergeType
}
}
}
enum MergeType {
both_queens
source_queen_kept
target_queen_kept
}
Запрос
query GetHive($hiveId: ID!) {
hive(id: $hiveId) {
id
name
status
mergedIntoHive {
id
name
}
mergedFromHives {
id
name
mergeDate
mergeType
}
}
}
События Redis
hive:join:{targetHiveId}
hive:merged:{sourceHiveId}
🔧 Детали реализации
Фронтенд
- Framework: Реагируйте с помощью TypeScript.
- Управление состоянием: useState для модального состояния, выбора цели, типа слияния.
- Компоненты пользовательского интерфейса:
- Двухпанельный макет (источник слева, цель справа)
- Кнопка переключения типа слияния (циклически переключается между 3 вариантами)
- Проверка в реальном времени и обработка ошибок
- Обработка событий: подписка на WebSocket для получения обновлений в реальном времени.
Бэкэнд (Go)
Логика фильтрации блоков
func filterMovableBoxes(boxes []Box) []Box {
var movableBoxes []Box
for _, box := range boxes {
if box.Type != "BOTTOM" && box.Type != "GATE" {
movableBoxes = append(movableBoxes, box)
}
}
return movableBoxes
}
Процесс объединения
- Проверка существования исходного и целевого ульев.
- Подтвердить ту же пасеку
- Проверьте исходный код, который еще не объединен.
- Получите все коробки из исходного улья.
- Фильтры (исключая ДНО и ВОРОТА)
- Получите максимальную позицию в целевом улье.
- Начать транзакцию
- Переместите коробки:
UPDATE boxes SET hive_id = ?, position = ? WHERE id IN (?). - Обновить исходный куст:
UPDATE hives SET status = 'merged', merged_into_hive_id = ?, merge_date = NOW(), merge_type = ? WHERE id = ?. - Зафиксировать транзакцию
- Публикация событий Redis
- Верните обновленный целевой улей.
Производительность
- Транзакция базы данных обеспечивает атомарность (все или ничего)
- Фильтрация ящиков выполняется в памяти (быстрая работа)
- Перерасчет позиции в одном ОБНОВЛЕНИИ
- Redis pub/sub неблокирует ответ на мутацию.
- События WebSocket доставляются асинхронно.
⚙️ Конфигурация
Никакой специальной настройки не требуется. Использует существующие:
- пул соединений MySQL
- Соединение Redis для публикации/подписки
- Сервер WebSocket в фильтре потока событий.