From 86c4cb9295e442380733ccdfee41f46ef6af7aca Mon Sep 17 00:00:00 2001 From: Salman Manoe Date: Fri, 14 Jan 2022 08:18:41 +0700 Subject: [PATCH] Add PgStatActivityService Pembuatan service monitoring proses aktivitas database, service cancel backend, dan service terminate backend --- .../medifirst2000/dao/PgStatActivityDao.java | 32 ++++++++ .../service/PgStatActivityService.java | 19 +++++ .../impl/PgStatActivityServiceImpl.java | 43 +++++++++++ .../entities/PgStatActivity.java | 46 +++++++++++ .../controller/IntegrationController.java | 76 +++++++++++++++++++ 5 files changed, 216 insertions(+) create mode 100644 jasamedika-business/src/main/java/com/jasamedika/medifirst2000/dao/PgStatActivityDao.java create mode 100644 jasamedika-business/src/main/java/com/jasamedika/medifirst2000/service/PgStatActivityService.java create mode 100644 jasamedika-business/src/main/java/com/jasamedika/medifirst2000/service/impl/PgStatActivityServiceImpl.java create mode 100644 jasamedika-domain/src/main/java/com/jasamedika/medifirst2000/entities/PgStatActivity.java diff --git a/jasamedika-business/src/main/java/com/jasamedika/medifirst2000/dao/PgStatActivityDao.java b/jasamedika-business/src/main/java/com/jasamedika/medifirst2000/dao/PgStatActivityDao.java new file mode 100644 index 00000000..ded28210 --- /dev/null +++ b/jasamedika-business/src/main/java/com/jasamedika/medifirst2000/dao/PgStatActivityDao.java @@ -0,0 +1,32 @@ +package com.jasamedika.medifirst2000.dao; + +import java.util.List; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.jasamedika.medifirst2000.entities.PgStatActivity; + +/** + * @author salmanoe + * @since Jan 12, 2022 + */ +@Repository("pgStatActivityDao") +public interface PgStatActivityDao extends PagingAndSortingRepository { + + @Query(value = "select pid, " + + "to_char(now() - pg_stat_activity.query_start, 'yyyy-MM-dd HH24:MI:SS.MS') as duration, " + "query, " + + "state " + "from pg_stat_activity " + "where state != 'idle' " + + "and (now() - pg_stat_activity.query_start) > interval '1 minutes' " + + "order by pg_stat_activity.query_start", nativeQuery = true) + List findByStateAndInterval(); + + @Query(value = "select pg_cancel_backend(:pid)", nativeQuery = true) + void callPgCancelBackend(@Param("pid") Integer pid); + + @Query(value = "select pg_terminate_backend(:pid)", nativeQuery = true) + void callPgTerminateBackend(@Param("pid") Integer pid); + +} diff --git a/jasamedika-business/src/main/java/com/jasamedika/medifirst2000/service/PgStatActivityService.java b/jasamedika-business/src/main/java/com/jasamedika/medifirst2000/service/PgStatActivityService.java new file mode 100644 index 00000000..231e4849 --- /dev/null +++ b/jasamedika-business/src/main/java/com/jasamedika/medifirst2000/service/PgStatActivityService.java @@ -0,0 +1,19 @@ +package com.jasamedika.medifirst2000.service; + +import java.util.List; + +import com.jasamedika.medifirst2000.entities.PgStatActivity; + +/** + * @author salmanoe + * @since Jan 12, 2022 + */ +public interface PgStatActivityService { + + public List findByStateAndInterval(); + + public Boolean callCancelBackend(Integer pid); + + public Boolean callTerminateBackend(Integer pid); + +} diff --git a/jasamedika-business/src/main/java/com/jasamedika/medifirst2000/service/impl/PgStatActivityServiceImpl.java b/jasamedika-business/src/main/java/com/jasamedika/medifirst2000/service/impl/PgStatActivityServiceImpl.java new file mode 100644 index 00000000..b5d7f353 --- /dev/null +++ b/jasamedika-business/src/main/java/com/jasamedika/medifirst2000/service/impl/PgStatActivityServiceImpl.java @@ -0,0 +1,43 @@ +package com.jasamedika.medifirst2000.service.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.jasamedika.medifirst2000.dao.PgStatActivityDao; +import com.jasamedika.medifirst2000.entities.PgStatActivity; +import com.jasamedika.medifirst2000.service.PgStatActivityService; + +/** + * @author salmanoe + * @since Jan 12, 2022 + */ +@Service("pgStatActivityService") +public class PgStatActivityServiceImpl implements PgStatActivityService { + + @Autowired + private PgStatActivityDao pgStatActivityDao; + + @Override + public List findByStateAndInterval() { + List result = pgStatActivityDao.findByStateAndInterval(); + + return result; + } + + @Override + public Boolean callCancelBackend(Integer pid) { + pgStatActivityDao.callPgCancelBackend(pid); + + return true; + } + + @Override + public Boolean callTerminateBackend(Integer pid) { + pgStatActivityDao.callPgTerminateBackend(pid); + + return true; + } + +} diff --git a/jasamedika-domain/src/main/java/com/jasamedika/medifirst2000/entities/PgStatActivity.java b/jasamedika-domain/src/main/java/com/jasamedika/medifirst2000/entities/PgStatActivity.java new file mode 100644 index 00000000..4f326bce --- /dev/null +++ b/jasamedika-domain/src/main/java/com/jasamedika/medifirst2000/entities/PgStatActivity.java @@ -0,0 +1,46 @@ +package com.jasamedika.medifirst2000.entities; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.annotations.Immutable; + +/** + * @author salmanoe + * @since Jan 12, 2022 + */ +@Entity +@Immutable +public class PgStatActivity { + + @Id + @Column(name = "pid", insertable = false, updatable = false) + private Integer pid; + + @Column(name = "duration", insertable = false, updatable = false) + private String duration; + + @Column(name = "query", insertable = false, updatable = false) + private String query; + + @Column(name = "state", insertable = false, updatable = false) + private String state; + + public Integer getPid() { + return pid; + } + + public String getDuration() { + return duration; + } + + public String getQuery() { + return query; + } + + public String getState() { + return state; + } + +} diff --git a/jasamedika-sdm/src/main/java/com/jasamedika/medifirst2000/controller/IntegrationController.java b/jasamedika-sdm/src/main/java/com/jasamedika/medifirst2000/controller/IntegrationController.java index 63caadb6..79f18830 100644 --- a/jasamedika-sdm/src/main/java/com/jasamedika/medifirst2000/controller/IntegrationController.java +++ b/jasamedika-sdm/src/main/java/com/jasamedika/medifirst2000/controller/IntegrationController.java @@ -1,11 +1,28 @@ package com.jasamedika.medifirst2000.controller; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.orm.jpa.JpaSystemException; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import com.jasamedika.medifirst2000.constants.MessageResource; import com.jasamedika.medifirst2000.controller.base.LocaleController; +import com.jasamedika.medifirst2000.core.web.WebConstants; +import com.jasamedika.medifirst2000.entities.PgStatActivity; +import com.jasamedika.medifirst2000.exception.ServiceVOException; +import com.jasamedika.medifirst2000.service.PgStatActivityService; +import com.jasamedika.medifirst2000.util.rest.RestUtil; import com.jasamedika.medifirst2000.vo.LoginUserVO; @RestController @@ -14,4 +31,63 @@ public class IntegrationController extends LocaleController { private static final Logger LOGGER = LoggerFactory.getLogger(IntegrationController.class); + @Autowired + private PgStatActivityService pgStatActivityService; + + @RequestMapping(value = "/pg-stat-activity/in-state-for-minutes", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getPgStatActivityInStateForMinutes(HttpServletRequest request) { + try { + List result = pgStatActivityService.findByStateAndInterval(); + mapHeaderMessage.put(WebConstants.HttpHeaderInfo.LABEL_SUCCESS, + getMessage(MessageResource.LABEL_SUCCESS, request)); + return RestUtil.getJsonResponse(result, HttpStatus.OK, mapHeaderMessage); + } catch (ServiceVOException e) { + LOGGER.error("Got exception {} when get pg_stat_activity in state for minutes", e.getMessage()); + mapHeaderMessage.put(WebConstants.HttpHeaderInfo.LABEL_SUCCESS, e.getMessage()); + return RestUtil.getJsonResponse(HttpStatus.INTERNAL_SERVER_ERROR, mapHeaderMessage); + } catch (JpaSystemException jse) { + LOGGER.error("Got exception {} when get pg_stat_activity in state for minutes", jse.getMessage()); + mapHeaderMessage.put(WebConstants.HttpHeaderInfo.LABEL_SUCCESS, jse.getMessage()); + return RestUtil.getJsonResponse(HttpStatus.CONFLICT, mapHeaderMessage); + } + } + + @RequestMapping(value = "/pg-stat-activity/cancel-backend", method = RequestMethod.POST) + public ResponseEntity callPgCancelBackend(HttpServletRequest request, + @RequestParam(value = "pid", required = true) Integer pid) { + try { + Boolean result = pgStatActivityService.callCancelBackend(pid); + mapHeaderMessage.put(WebConstants.HttpHeaderInfo.LABEL_SUCCESS, + getMessage(MessageResource.LABEL_SUCCESS, request)); + return RestUtil.getJsonResponse(result, HttpStatus.OK, mapHeaderMessage); + } catch (ServiceVOException sve) { + LOGGER.error("Got exception {} when call pg_cancel_backend pid : {}", sve.getMessage(), pid); + mapHeaderMessage.put(WebConstants.HttpHeaderInfo.LABEL_SUCCESS, sve.getMessage()); + return RestUtil.getJsonResponse(HttpStatus.INTERNAL_SERVER_ERROR, mapHeaderMessage); + } catch (JpaSystemException jse) { + LOGGER.error("Got exception {} when call pg_cancel_backend pid : {}", jse.getMessage(), pid); + mapHeaderMessage.put(WebConstants.HttpHeaderInfo.LABEL_SUCCESS, jse.getMessage()); + return RestUtil.getJsonResponse(HttpStatus.CONFLICT, mapHeaderMessage); + } + } + + @RequestMapping(value = "/pg-stat-activity/terminate-backend", method = RequestMethod.POST) + public ResponseEntity callPgTerminateBackend(HttpServletRequest request, + @RequestParam(value = "pid", required = true) Integer pid) { + try { + Boolean result = pgStatActivityService.callTerminateBackend(pid); + mapHeaderMessage.put(WebConstants.HttpHeaderInfo.LABEL_SUCCESS, + getMessage(MessageResource.LABEL_SUCCESS, request)); + return RestUtil.getJsonResponse(result, HttpStatus.OK, mapHeaderMessage); + } catch (ServiceVOException sve) { + LOGGER.error("Got exception {} when call pg_terminate_backend pid : {}", sve.getMessage(), pid); + mapHeaderMessage.put(WebConstants.HttpHeaderInfo.LABEL_SUCCESS, sve.getMessage()); + return RestUtil.getJsonResponse(HttpStatus.INTERNAL_SERVER_ERROR, mapHeaderMessage); + } catch (JpaSystemException jse) { + LOGGER.error("Got exception {} when call pg_terminate_backend pid : {}", jse.getMessage(), pid); + mapHeaderMessage.put(WebConstants.HttpHeaderInfo.LABEL_SUCCESS, jse.getMessage()); + return RestUtil.getJsonResponse(HttpStatus.CONFLICT, mapHeaderMessage); + } + } + }