Обработка остановки сервера, фикс EventManager
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package com.rosetta.im;
|
package com.rosetta.im;
|
||||||
|
|
||||||
import com.rosetta.im.event.EventManager;
|
import com.rosetta.im.event.EventManager;
|
||||||
|
import com.rosetta.im.listeners.ServerStopListener;
|
||||||
|
|
||||||
public class ContextBuilder {
|
public class ContextBuilder {
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ public class ContextBuilder {
|
|||||||
* Создание глобальных объектов приложения
|
* Создание глобальных объектов приложения
|
||||||
*/
|
*/
|
||||||
EventManager eventManager = new EventManager();
|
EventManager eventManager = new EventManager();
|
||||||
|
eventManager.registerListener(new ServerStopListener());
|
||||||
|
|
||||||
this.appContext = new AppContext(eventManager);
|
this.appContext = new AppContext(eventManager);
|
||||||
return this.appContext;
|
return this.appContext;
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public class EventManager {
|
|||||||
* @throws EventException Ошибка при обработке события
|
* @throws EventException Ошибка при обработке события
|
||||||
* @throws Exception Общая ошибка при вызове метода
|
* @throws Exception Общая ошибка при вызове метода
|
||||||
*/
|
*/
|
||||||
private boolean fireEvent(Event event) throws EventException, Exception {
|
private boolean fireEvent(Event event) throws EventException {
|
||||||
for(Listener listener : this.listeners) {
|
for(Listener listener : this.listeners) {
|
||||||
/**
|
/**
|
||||||
* Получаем все методы в Listener с аннотацией @EventHandler
|
* Получаем все методы в Listener с аннотацией @EventHandler
|
||||||
@@ -81,8 +81,12 @@ public class EventManager {
|
|||||||
/**
|
/**
|
||||||
* Если параметры совпадают и они одного типа - вызываем событие
|
* Если параметры совпадают и они одного типа - вызываем событие
|
||||||
*/
|
*/
|
||||||
|
try{
|
||||||
method.setAccessible(true);
|
method.setAccessible(true);
|
||||||
method.invoke(listener, event);
|
method.invoke(listener, event);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new EventException("Error while invoking event handler method: " + method.getName(), e);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Если событие отменяемое - проверяем его статус
|
* Если событие отменяемое - проверяем его статус
|
||||||
*/
|
*/
|
||||||
@@ -94,11 +98,6 @@ public class EventManager {
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Если метод обрабатывающий событие
|
|
||||||
* реализован неправильно - выбрасываем исключение
|
|
||||||
*/
|
|
||||||
throw new EventException("Invalid event params");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.rosetta.im.listeners;
|
||||||
|
|
||||||
|
import com.rosetta.im.client.tags.ECIAuthentificate;
|
||||||
|
import com.rosetta.im.client.tags.ECIDevice;
|
||||||
|
import com.rosetta.im.database.repository.DeviceRepository;
|
||||||
|
import com.rosetta.im.event.EventHandler;
|
||||||
|
import com.rosetta.im.event.Listener;
|
||||||
|
import com.rosetta.im.event.events.ServerStopEvent;
|
||||||
|
import com.rosetta.im.service.services.DeviceService;
|
||||||
|
|
||||||
|
import io.orprotocol.Server;
|
||||||
|
import io.orprotocol.client.Client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* При остановке сервера нам нужно обновить всем клиентам время последней активности устройства
|
||||||
|
* чтобы корректно потом отработать загрузку сообщений для пользователя
|
||||||
|
*/
|
||||||
|
public class ServerStopListener implements Listener {
|
||||||
|
|
||||||
|
private static final DeviceRepository deviceRepository = new DeviceRepository();
|
||||||
|
private static final DeviceService deviceService = new DeviceService(deviceRepository);
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onServerStop(ServerStopEvent event) {
|
||||||
|
Server server = event.getServer();
|
||||||
|
System.out.println("Server is stopping. Please wait...");
|
||||||
|
for(Client client : server.getClients()){
|
||||||
|
ECIAuthentificate eciAuth = client.getTag(ECIAuthentificate.class);
|
||||||
|
if(eciAuth == null || !eciAuth.hasAuthorized()){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ECIDevice eciDevice = client.getTag(ECIDevice.class);
|
||||||
|
if(eciDevice == null){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
deviceService.updateDeviceLeaveTime(eciDevice.getDeviceId());
|
||||||
|
}
|
||||||
|
System.out.println("Server stopped successfully.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -45,4 +45,17 @@ public class DeviceService extends Service<DeviceRepository> {
|
|||||||
return this.getRepository().countByField("publicKey", user.getPublicKey());
|
return this.getRepository().countByField("publicKey", user.getPublicKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Обновляет время последней активности устройства
|
||||||
|
* @param deviceId ID устройства
|
||||||
|
*/
|
||||||
|
public void updateDeviceLeaveTime(String deviceId) {
|
||||||
|
Device device = this.getRepository().findByField("deviceId", deviceId);
|
||||||
|
if(device == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
device.setLeaveTime(System.currentTimeMillis());
|
||||||
|
this.getRepository().update(device);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package io.orprotocol;
|
|||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -194,6 +196,7 @@ public class Server extends WebSocketServer {
|
|||||||
* Настраиваем планировщик для проверки активности клиентов.
|
* Настраиваем планировщик для проверки активности клиентов.
|
||||||
*/
|
*/
|
||||||
this.inactivityShedulerTweaker();
|
this.inactivityShedulerTweaker();
|
||||||
|
this.wakeupShutdownHook();
|
||||||
|
|
||||||
int port = this.getPort();
|
int port = this.getPort();
|
||||||
System.out.println("\u001B[32mServer started at x.x.x.x:" + port + "\u001B[0m");
|
System.out.println("\u001B[32mServer started at x.x.x.x:" + port + "\u001B[0m");
|
||||||
@@ -203,6 +206,18 @@ public class Server extends WebSocketServer {
|
|||||||
this.listener.onServerStart(this);
|
this.listener.onServerStart(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить список подключенных клиентов
|
||||||
|
* @return множество клиентов
|
||||||
|
*/
|
||||||
|
public Set<Client> getClients() {
|
||||||
|
Set<Client> clients = new HashSet<>();
|
||||||
|
for(WebSocket socket : this.getConnections()) {
|
||||||
|
clients.add(socket.getAttachment());
|
||||||
|
}
|
||||||
|
return clients;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Планировщик для проверки активности клиентов.
|
* Планировщик для проверки активности клиентов.
|
||||||
* Если планировщик обнаруживает неактивного клиента, он отключает его с соответствующим кодом ошибки.
|
* Если планировщик обнаруживает неактивного клиента, он отключает его с соответствующим кодом ошибки.
|
||||||
@@ -218,4 +233,19 @@ public class Server extends WebSocketServer {
|
|||||||
}, this.settings.heartbeatInterval, this.settings.heartbeatInterval, TimeUnit.MILLISECONDS);
|
}, this.settings.heartbeatInterval, this.settings.heartbeatInterval, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Пробуждает хук завершения для корректной остановки сервера.
|
||||||
|
*/
|
||||||
|
private void wakeupShutdownHook() {
|
||||||
|
if(this.listener == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||||
|
/**
|
||||||
|
* Останавливаем сервер при завершении работы и вызываем слушатели остановки сервера.
|
||||||
|
*/
|
||||||
|
System.out.println("JVM Shutdown detected, stopping server...");
|
||||||
|
this.listener.onServerStop(this);
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user