Skip to content

Commit

Permalink
Apply Cluster Session Clear
Browse files Browse the repository at this point in the history
  • Loading branch information
akageun committed Aug 3, 2024
1 parent f51ff2b commit 08e3ed0
Show file tree
Hide file tree
Showing 13 changed files with 403 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

Expand Down Expand Up @@ -33,6 +34,29 @@ public CqlSession get(String clusterId) {
return SESSION.computeIfAbsent(key, this::makeSession);
}

public void clearAll() {
for (Map.Entry<String, CqlSession> entry : SESSION.entrySet()) {
try {
SESSION.remove(entry.getKey()).close();
} catch (Exception e) {
log.error("closed Fail : {}", entry.getKey());
}
}
}

public void clear(String clusterId) {
try {
CqlSession session = SESSION.remove(clusterId);
if (session == null) {
return;
}

session.close();
} catch (Exception e) {
log.error("closed Fail : {}", clusterId);
}
}

public CqlSession makeSession(String clusterId) {
ClusterInfo info = clusterProvider.findById(clusterId);
if (info == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import kr.hakdang.cassdio.common.CassdioConstants;
import kr.hakdang.cassdio.core.domain.cluster.CassdioVersionChecker;
import kr.hakdang.cassdio.core.domain.cluster.ClusterProvider;
import kr.hakdang.cassdio.core.domain.cluster.CqlSessionFactory;
import kr.hakdang.cassdio.core.domain.cluster.info.ClusterInfo;
import kr.hakdang.cassdio.web.common.dto.response.ApiResponse;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -34,13 +35,16 @@ public class ClusterApi {

private final CassdioVersionChecker cassdioVersionChecker;
private final ClusterProvider clusterProvider;
private final CqlSessionFactory cqlSessionFactory;

public ClusterApi(
CassdioVersionChecker cassdioVersionChecker,
ClusterProvider clusterProvider
ClusterProvider clusterProvider,
CqlSessionFactory cqlSessionFactory
) {
this.cassdioVersionChecker = cassdioVersionChecker;
this.clusterProvider = clusterProvider;
this.cqlSessionFactory = cqlSessionFactory;
}

@GetMapping("")
Expand All @@ -61,16 +65,44 @@ public ApiResponse<Map<String, Object>> clusterList(
return ApiResponse.ok(responseMap);
}

@PostMapping("/session/clear")
public ApiResponse<Map<String, Object>> clusterSessionAllClear(
) {
Map<String, Object> responseMap = new HashMap<>();

cqlSessionFactory.clearAll();

return ApiResponse.ok(responseMap);
}

@GetMapping("/{clusterId}")
public ApiResponse<Map<String, Object>> clusterDetail(
@PathVariable(name = CassdioConstants.CLUSTER_ID_PATH) String clusterId,
@RequestParam(required = false, defaultValue = "false") boolean withPassword
) {
Map<String, Object> responseMap = new HashMap<>();
ClusterInfo info = clusterProvider.findByIdWithoutCache(clusterId);
if (!withPassword) {
info = info.toBuilder().password(null).build();
}

responseMap.put("cluster", info);

return ApiResponse.ok(responseMap);
}

@PostMapping("/{clusterId}/session/clear")
public ApiResponse<Map<String, Object>> clusterSessionOneClear(
@PathVariable(name = CassdioConstants.CLUSTER_ID_PATH) String clusterId
) {
Map<String, Object> responseMap = new HashMap<>();
responseMap.put("cluster", clusterProvider.findByIdWithoutCache(clusterId));

cqlSessionFactory.clear(clusterId);

return ApiResponse.ok(responseMap);
}


@PostMapping("")
public ApiResponse<Void> clusterRegister(
@Valid @RequestBody ClusterRegisterRequest request
Expand Down
34 changes: 32 additions & 2 deletions cassdio-web/src/main/webapp/src/components/admin/admin-layout.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,37 @@
import {Link, Outlet} from "react-router-dom";
import React from "react";

import CassdioSidebar from "../layout/cassdio-sidebar";

const AdminLayout = () => {
return (
<>
</>
<div className="container-fluid h-100">
<div className="row">

<CassdioSidebar>
<ul className="nav flex-column">
<li className="nav-item">
<Link
className={`nav-link d-flex align-items-center gap-2 link-body-emphasis text-decoration-none`}
to={`/admin`}>
<i className="bi bi-house"></i> Home
</Link>
</li>
<li className="nav-item">
<Link
className={`nav-link d-flex align-items-center gap-2 link-body-emphasis text-decoration-none`}
to={`/admin/cluster`}>
<i className="bi bi-database-fill"></i> Cluster
</Link>
</li>
</ul>
</CassdioSidebar>

<main className="col-md-9 ms-sm-auto col-lg-10 px-md-4 mb-5">
<Outlet/>
</main>
</div>
</div>
)
}

Expand Down
111 changes: 40 additions & 71 deletions cassdio-web/src/main/webapp/src/components/cluster/cluster-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import React, {useEffect, useState} from "react";
import {Link} from "react-router-dom";

import Spinner from "components/common/spinner";

import ClusterManageModal from "./modal/cluster-manage-modal";
import useCluster from "hooks/useCluster";

const ClusterList = () => {
Expand Down Expand Up @@ -35,82 +33,53 @@ const ClusterList = () => {
<h2 className="h2">Clusters</h2>
<div className="btn-toolbar mb-2 mb-md-0">
<div className="btn-group me-2">
<button type="button" className="btn btn-sm btn-outline-secondary"
onClick={e => setShowClusterModal(true)}>
<i className="bi bi-database-fill"></i> New Cluster
</button>
<Link to={`/admin/cluster`} className="btn btn-sm btn-outline-secondary">
New
</Link>
</div>
</div>
</div>

<Spinner loading={clustersLoading}>
<div className="table-responsive small">
<table className="table table-sm table-hover">
<thead>
<tr className={"table-dark"}>
<th className={"text-center"} scope="col">#</th>
<th className={"text-center"} scope="col">Cluster Id</th>
<th className={"text-center"} scope="col">Cluster Name</th>
<th className={"text-center"} scope="col">ContactPoints</th>
<th className={"text-center"} scope="col">Port</th>
<th className={"text-center"} scope="col">Local Datacenter</th>
</tr>
</thead>
<tbody className="table-group-divider">
{
(clusters && clusters.length > 0) ? clusters.map((info, infoIndex) => {
<div className="row g-4">
<Spinner loading={clustersLoading}>
{
(clusters && clusters.length > 0) ? clusters.map((info, infoIndex) => {
return (
<tr key={infoIndex}>
<td className={"text-center"}>
<a className={"btn btn-sm btn-outline-warning"}
onClick={e => {
setDetailClusterId(info.clusterId);
setShowClusterModal(true);
}}>
<i className="bi bi-pencil-fill"></i>
</a>
<a className={"btn btn-sm btn-outline-danger"}
onClick={e => {
removeClusterId(info.clusterId);
}}>
<i className="bi bi-trash"></i>
</a>
</td>
<td className={"text-center"}>
<Link
className={"text-decoration-none"}
to={`/cluster/${info.clusterId}`}>
{info.clusterId}
</Link>
</td>
<td className={"text-center"}>
<Link
className={"text-decoration-none"}
to={`/cluster/${info.clusterId}`}>
{info.clusterName}
</Link>
</td>
<td className={"text-center text-truncate"}>{info.contactPoints}</td>
<td className={"text-center"}>{info.port}</td>
<td className={"text-center"}>{info.localDatacenter}</td>
</tr>
)
}) : <tr>
<td className={"text-center"} colSpan={6}>No Data</td>
</tr>
}
</tbody>
</table>
</div>
</Spinner>
<div className={"col-md-4 col-sm-12"} key={`clusters${infoIndex}`}>
<div className="card">
<div className="card-body">
<h4 className="card-title">
<Link
className={"text-decoration-none link-body-emphasis"}
to={`/cluster/${info.clusterId}`}>
{info.clusterName}
</Link>
</h4>
<h6 className="card-subtitle mb-2 text-body-secondary">Cluster Id
: {info.clusterId}</h6>
<p className="card-text text-truncate">{info.memo}</p>

{
showClusterModal && <ClusterManageModal
show={showClusterModal}
clusterId={detailClusterId}
handleClose={() => closeClusterModal()}/>
}
<Link to={`/cluster/${info.clusterId}`}
className="btn btn-primary btn-sm">
Go To
</Link>
</div>
</div>
</div>
)
}) :
<div className={"col"}>
<p>
No Data

<Link to={`/admin/cluster`} className={`ms-2 btn btn-sm btn-outline-primary`}>
Go to registration
</Link>
</p>
</div>
}
</Spinner>
</div>
</>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import {useEffect} from "react";

import {Modal} from "react-bootstrap";
import Spinner from "components/common/spinner";
import useCluster from "../../../hooks/useCluster";
import useCluster from "hooks/useCluster";

const ClusterManageModal = ({show, handleClose, clusterId}) => {
const ClusterManageModal = ({show, handleClose, clusterId, readonly = false}) => {
const {
doGetClusterList,
removeClusterId,
Expand Down Expand Up @@ -53,7 +53,8 @@ const ClusterManageModal = ({show, handleClose, clusterId}) => {
<div className="col-6 mb-2">
<label htmlFor="clusterPort" className="form-label">Cluster Port</label>
<div className="input-group">
<input type="number" className="form-control form-control-sm" id="clusterPort" placeholder=""
<input type="number" className="form-control form-control-sm" id="clusterPort"
placeholder=""
value={clusterInfo.port || 0}
onChange={evt => setClusterInfo(t => {
return {...t, port: evt.target.value}
Expand Down Expand Up @@ -110,7 +111,8 @@ const ClusterManageModal = ({show, handleClose, clusterId}) => {
Password
</label>
<div className="input-group">
<input type="password" className="form-control form-control-sm" id="clusterPassword"
<input type="password" className="form-control form-control-sm"
id="clusterPassword"
placeholder="Cluster Password"
value={clusterInfo.password || ''}
onChange={evt => setClusterInfo(t => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import {useEffect} from "react";
import {Modal, OverlayTrigger, Tooltip} from "react-bootstrap";
import {toast} from "react-toastify";

const TableRowDetailModal = ({show, handleClose, rowDetailView, convertedRowHeader}) => {

const handleCopyClipBoard = async (data) => {
try {
await navigator.clipboard.writeText(data);
await toast.info("Copied")
} catch (e) {
toast.error('Fail Copy');
}
};

useEffect(() => {
//show component

Expand Down Expand Up @@ -49,7 +59,7 @@ const TableRowDetailModal = ({show, handleClose, rowDetailView, convertedRowHead
{rowDetailView[info.column_name]}
</td>
<td>
<a className={"btn btn-sm btn-outline-secondary"}>COPY</a>
<a className={"btn btn-sm btn-outline-secondary"} onClick={e => handleCopyClipBoard(rowDetailView[info.column_name])}>COPY</a>
</td>
</tr>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ const CassdioHeader = () => {
Cassdio
</Link>

<ul className="navbar-nav flex-row d-md-none">
<li className="nav-item text-nowrap">
<ul className="navbar-nav flex-row ">
<li className="nav-item text-nowrap d-md-none">
<button className="nav-link px-3 text-white" type="button" data-bs-toggle="offcanvas"
data-bs-target={`#${cassdioHelper.CASSDIO_SIDEBAR_ID}`}
aria-controls={`${cassdioHelper.CASSDIO_SIDEBAR_ID}`}
Expand Down
Loading

0 comments on commit 08e3ed0

Please sign in to comment.