From b4363c6abc7b837223aec73cada95fd1de3684e1 Mon Sep 17 00:00:00 2001 From: gsd Date: Fri, 2 Feb 2024 23:03:06 +0300 Subject: [PATCH] external services --- .../java/app/controllers/StatsController.java | 11 ++- .../java/app/services/ExternalServices.java | 53 +++++++++++++++ src/main/java/app/services/db/DBService.java | 14 +++- .../handlers/ExternalServicesHandler.java | 67 +++++++++++++++++++ 4 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 src/main/java/app/services/ExternalServices.java create mode 100644 src/main/java/app/websocket/handlers/ExternalServicesHandler.java diff --git a/src/main/java/app/controllers/StatsController.java b/src/main/java/app/controllers/StatsController.java index e087e18..fb75b0c 100644 --- a/src/main/java/app/controllers/StatsController.java +++ b/src/main/java/app/controllers/StatsController.java @@ -3,6 +3,7 @@ package app.controllers; import app.annotations.interfaces.BurstUpdatePlayers; import app.annotations.interfaces.CollectStatistic; import app.entities.Stats; +import app.services.ExternalServices; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -17,10 +18,12 @@ import java.util.List; @RequestMapping("api/stats") public class StatsController { private Stats stats; + private ExternalServices externalServices; @Autowired - public StatsController(Stats stats){ + public StatsController(Stats stats, ExternalServices externalServices){ this.stats = stats; + this.externalServices = externalServices; } @GetMapping @@ -32,4 +35,10 @@ public class StatsController { } return new ResponseEntity<>(stats, HttpStatus.OK); } + + @GetMapping("/services") + @CollectStatistic + public ResponseEntity GetServices() { + return new ResponseEntity(externalServices.getServices(), HttpStatus.OK); + } } diff --git a/src/main/java/app/services/ExternalServices.java b/src/main/java/app/services/ExternalServices.java new file mode 100644 index 0000000..26757f9 --- /dev/null +++ b/src/main/java/app/services/ExternalServices.java @@ -0,0 +1,53 @@ +package app.services; + +import app.services.db.DBService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.Instant; +import java.util.HashMap; + +@Service +public class ExternalServices { + private HashMap services; + private DBService dbService; + private long last_db_update = 0L; + private final long refresh = 60L; + + @Autowired + ExternalServices(DBService dbService) { + this.dbService = dbService; + this.services = new HashMap<>(); + } + + public HashMap getServices() { + update(); + HashMap s = new HashMap<>(); + services.forEach((key, utime) -> { + if (Instant.now().getEpochSecond() - utime < refresh) s.put(key, true); + else s.put(key, false); + }); + return s; + } + + public void update() { + if (Instant.now().getEpochSecond() - last_db_update < refresh / 3) + return; + + try { + services.put("db_main", dbService.getMainServerTime()); + } catch (Exception e) { + services.put("db_main", 0L); + } + + try { + services.put("db_replica", dbService.getReplicaServerTime()); + } catch (Exception e) { + services.put("db_replica", 0L); + } + } + + public void update(String name) { + services.put(name, Instant.now().getEpochSecond()); + } +} diff --git a/src/main/java/app/services/db/DBService.java b/src/main/java/app/services/db/DBService.java index 2d12b68..8921327 100644 --- a/src/main/java/app/services/db/DBService.java +++ b/src/main/java/app/services/db/DBService.java @@ -22,10 +22,18 @@ public class DBService { } public Long getDBServerTime() { - Long rw_time = (Long) entityManager_rw.createNativeQuery("SELECT UNIX_TIMESTAMP()") + Long rw_time = getMainServerTime(); + Long ro_time = getReplicaServerTime(); + return rw_time; + } + + public Long getMainServerTime() { + return (Long) entityManager_rw.createNativeQuery("SELECT UNIX_TIMESTAMP()") .getSingleResult(); - Long ro_time = (Long) entityManager_ro.createNativeQuery("SELECT UNIX_TIMESTAMP()") + } + + public Long getReplicaServerTime() { + return (Long) entityManager_ro.createNativeQuery("SELECT UNIX_TIMESTAMP()") .getSingleResult(); - return rw_time; } } diff --git a/src/main/java/app/websocket/handlers/ExternalServicesHandler.java b/src/main/java/app/websocket/handlers/ExternalServicesHandler.java new file mode 100644 index 0000000..6be2069 --- /dev/null +++ b/src/main/java/app/websocket/handlers/ExternalServicesHandler.java @@ -0,0 +1,67 @@ +package app.websocket.handlers; + +import app.annotations.enums.AuthMethod; +import app.annotations.interfaces.CheckWebAccess; +import app.services.ExternalServices; +import app.websocket.BaseWebsocketHandler; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +import java.util.HashMap; + +@Component +public class ExternalServicesHandler extends TextWebSocketHandler implements BaseWebsocketHandler { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + private ObjectMapper objectMapper = new ObjectMapper(); + + private ExternalServices externalServices; + + @Autowired + ExternalServicesHandler(ExternalServices externalServices) { + this.externalServices = externalServices; + } + + @Override + public String getPath() { + return "services"; + } + + @Override + @CheckWebAccess(auth_method = AuthMethod.SECRET_KEY) + public void afterConnectionEstablished(WebSocketSession session) throws Exception { + logger.info("Session {} open", session.getId()); + super.afterConnectionEstablished(session); + if (session.isOpen()) { + logger.info("Session {} open", session.getId()); + } + } + + @Override + @CheckWebAccess(auth_method = AuthMethod.SECRET_KEY) + public void handleTextMessage(WebSocketSession session, TextMessage message) { + if (!session.isOpen()) return; + HashMap payload; + try { + payload = objectMapper.readValue(message.getPayload(), HashMap.class); + } catch (Exception e) { + logger.error("Cannot explode payload: {}", e.getMessage()); + return; + } + String service_name = (String) payload.get("name"); + externalServices.update(service_name); + } + + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { + logger.info("Session {} close", session.getId()); + super.afterConnectionClosed(session, status); + } +}