Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/session clear #106

Merged
merged 1 commit into from
Aug 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading