parent
5e962963a8
commit
011ab54fd6
@ -0,0 +1,68 @@
|
|||||||
|
<script setup>
|
||||||
|
import '@/assets/main.css'
|
||||||
|
import { useApiClient } from '@/main'
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
|
||||||
|
const apiClient = useApiClient()
|
||||||
|
|
||||||
|
async function getAgentMessageDtoList() {
|
||||||
|
const response = await apiClient.post('/app-api/agent/getAgentMessageDtoList')
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
let dfxAgentMessageDtoList = ref([])
|
||||||
|
|
||||||
|
function setDfaAgentInfoDto(dfxAgentMessageDto) {
|
||||||
|
alert(dfxAgentMessageDto)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
dfxAgentMessageDtoList.value = await getAgentMessageDtoList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<main class="dfx-main container w-100">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 pt-2 border-bottom">
|
||||||
|
<h3 class="h3">Dashboard</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<article class="col-12 pt-3">
|
||||||
|
<h5 class="h5">송수신 메시지 목록</h5>
|
||||||
|
<table class="table table-striped table-bordered align-middle">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col" class="text-center">Message UUID</th>
|
||||||
|
<th scope="col" class="text-center">Sender (Postman)</th>
|
||||||
|
<th scope="col" class="text-center">Recipient (Dropbox)</th>
|
||||||
|
<th scope="col" class="text-center">Send</th>
|
||||||
|
<th scope="col" class="text-center">Receive</th>
|
||||||
|
<th scope="col" class="text-center">Status</th>
|
||||||
|
<th scope="col" class="text-center">Data count</th>
|
||||||
|
<th scope="col" class="text-center">Data</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="table-group-divider">
|
||||||
|
<tr v-if="dfxAgentMessageDtoList.length > 0" v-for="dfxAgentMessageDto in dfxAgentMessageDtoList" :key="`${dfxAgentMessageDto.senderAgentId}-${dfxAgentMessageDto.messageUuid}`">
|
||||||
|
<td scope="row">{{ dfxAgentMessageDto.messageUuid }}</td>
|
||||||
|
<td class="text-center">{{ dfxAgentMessageDto.senderAgentId }}({{ dfxAgentMessageDto.senderPostmanId }})</td>
|
||||||
|
<td class="text-center">{{ dfxAgentMessageDto.recipientAgentId }}({{ dfxAgentMessageDto.receipientDropboxId }})</td>
|
||||||
|
<td class="text-center">{{ dfxAgentMessageDto.senderTimeString }}</td>
|
||||||
|
<td class="text-center">{{ dfxAgentMessageDto.recipientTimeString }}</td>
|
||||||
|
<td class="text-center">{{ dfxAgentMessageDto.processStatusCode }}</td>
|
||||||
|
<td class="text-right">{{ dfxAgentMessageDto.messageDateCount }}</td>
|
||||||
|
<td class="text-center"><button type="button" class="btn btn-primary btn-sm" @click.prevent="setDfaAgentInfoDto(dfxAgentInfoDto)">Data View</button></td>
|
||||||
|
</tr>
|
||||||
|
<tr v-else>
|
||||||
|
<td scope="row" class="text-center" colspan="8">no datas.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style></style>
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.bsmlab.dfx.dfxconsole.app.agent.service;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@ToString
|
||||||
|
public class DfxAgentMessageDto {
|
||||||
|
private String messageUuid;
|
||||||
|
private String senderAgentId;
|
||||||
|
private String senderHostName;
|
||||||
|
private String senderPostmanId;
|
||||||
|
private long senderTs;
|
||||||
|
private String senderTimeString;
|
||||||
|
private String recipientAgentId;
|
||||||
|
private String recipientHostName;
|
||||||
|
private String recipientDropboxId;
|
||||||
|
private long recipientTs;
|
||||||
|
private String recipientTimeString;
|
||||||
|
private String messageTypeCode;
|
||||||
|
private long consoleReceiveTs;
|
||||||
|
private String consoleReceiveTimeString;
|
||||||
|
private String processStatusCode;
|
||||||
|
private String messageData;
|
||||||
|
private int messageDataCount;
|
||||||
|
private long processAckTs;
|
||||||
|
private long processAckTimeString;
|
||||||
|
}
|
||||||
@ -0,0 +1,181 @@
|
|||||||
|
package com.bsmlab.dfx.dfxconsole.framework.support.mybatis;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.ibatis.session.SqlSessionFactory;
|
||||||
|
import org.mybatis.spring.SqlSessionFactoryBean;
|
||||||
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class RefreshableSqlSessionFactoryBean extends SqlSessionFactoryBean implements DisposableBean {
|
||||||
|
private SqlSessionFactory proxy;
|
||||||
|
private int interval = 500;
|
||||||
|
private Timer timer;
|
||||||
|
private TimerTask task;
|
||||||
|
private Resource[] mapperLocations;
|
||||||
|
private boolean running = false;
|
||||||
|
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
|
||||||
|
private final Lock r = rwl.readLock();
|
||||||
|
private final Lock w = rwl.writeLock();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMapperLocations(Resource[] mapperLocations) {
|
||||||
|
super.setMapperLocations(mapperLocations);
|
||||||
|
this.mapperLocations = mapperLocations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInterval(int interval) {
|
||||||
|
this.interval = interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh() throws Exception {
|
||||||
|
if(log.isInfoEnabled()) {
|
||||||
|
log.info("> Refreshing SQL Mapper Configuration...");
|
||||||
|
}
|
||||||
|
w.lock();
|
||||||
|
try {
|
||||||
|
super.afterPropertiesSet();
|
||||||
|
// refresh()가 호출될 때 기존 proxy를 재생성하여 기존 세션과 충돌을 방지한다.
|
||||||
|
proxy = (SqlSessionFactory) Proxy.newProxyInstance(
|
||||||
|
SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSessionFactory.class}
|
||||||
|
, (proxy, method, args) -> method.invoke(getParentObject(), args)
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
w.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
super.afterPropertiesSet();
|
||||||
|
setRefreshable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setRefreshable() {
|
||||||
|
proxy = (SqlSessionFactory) Proxy.newProxyInstance(
|
||||||
|
SqlSessionFactory.class.getClassLoader(),
|
||||||
|
new Class[]{SqlSessionFactory.class},
|
||||||
|
new InvocationHandler() {
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||||
|
return method.invoke(getParentObject(), args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
task = new TimerTask() {
|
||||||
|
private Map<Resource, Long> map = new HashMap<>();
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
if(isModified()) {
|
||||||
|
try {
|
||||||
|
refresh();
|
||||||
|
} catch(Exception e) {
|
||||||
|
log.error("caught exception", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isModified() {
|
||||||
|
boolean retVal = false;
|
||||||
|
if(mapperLocations != null) {
|
||||||
|
for(int i = 0; i < mapperLocations.length; i++) {
|
||||||
|
Resource mappingLocation = mapperLocations[i];
|
||||||
|
retVal |= findModifiedResource(mappingLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean findModifiedResource(Resource resource) {
|
||||||
|
boolean retVal = false;
|
||||||
|
List<String> modifiedResources = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
long modified = resource.lastModified();
|
||||||
|
|
||||||
|
if(map.containsKey(resource)) {
|
||||||
|
long lastModified = ((Long) map.get(resource)) .longValue();
|
||||||
|
|
||||||
|
if(lastModified != modified) {
|
||||||
|
map.put(resource, modified);
|
||||||
|
|
||||||
|
//modifiedResources.add(resource.getDescription()); // 전체경로
|
||||||
|
modifiedResources.add(resource.getFilename()); // 파일명
|
||||||
|
|
||||||
|
retVal = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
map.put(resource, modified);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("caught exception", e);
|
||||||
|
}
|
||||||
|
if(retVal) {
|
||||||
|
if(log.isInfoEnabled()) {
|
||||||
|
log.info("======================================================================================");
|
||||||
|
log.info("> Update File name : " + modifiedResources);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
timer = new Timer(true);
|
||||||
|
resetInterval();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getParentObject() throws Exception {
|
||||||
|
r.lock();
|
||||||
|
try {
|
||||||
|
return super.getObject();
|
||||||
|
} finally {
|
||||||
|
r.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqlSessionFactory getObject() {
|
||||||
|
return this.proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends SqlSessionFactory> getObjectType() {
|
||||||
|
return (this.proxy != null ? this.proxy.getClass() : SqlSessionFactory.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSingleton() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCheckInterval(int ms) {
|
||||||
|
interval = ms;
|
||||||
|
if(timer != null) {
|
||||||
|
resetInterval();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetInterval() {
|
||||||
|
if(running) {
|
||||||
|
timer.cancel();
|
||||||
|
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(interval > 0) {
|
||||||
|
timer.schedule(task, 0, interval); running = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() throws Exception {
|
||||||
|
timer.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in new issue