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