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 8f23c05 commit 20ed5ae
Show file tree
Hide file tree
Showing 15 changed files with 402 additions and 90 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package kr.hakdang.cassdio.core.domain.cluster;

import com.datastax.oss.driver.api.core.CqlSession;
import kr.hakdang.cassdio.common.utils.IdGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import com.datastax.oss.driver.api.core.CqlSession;
import kr.hakdang.cassdio.core.domain.cluster.info.ClusterInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
Expand Down Expand Up @@ -39,6 +39,29 @@ public CqlSession get(String clusterId) {
return session;
}

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 @@ -2,7 +2,6 @@

import com.fasterxml.jackson.core.type.TypeReference;
import io.micrometer.common.util.StringUtils;
import kr.hakdang.cassdio.common.utils.IdGenerator;
import kr.hakdang.cassdio.common.utils.Jsons;
import kr.hakdang.cassdio.core.domain.cluster.ClusterException;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -11,7 +10,6 @@
import org.mapdb.Serializer;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import jakarta.validation.Valid;
import kr.hakdang.cassdio.common.CassdioConstants;
import kr.hakdang.cassdio.core.domain.cluster.ClusterConnector;
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 @@ -32,15 +32,14 @@
@RequestMapping("/api/cassandra/cluster")
public class ClusterApi {

private final ClusterConnector clusterConnector;
private final ClusterProvider clusterProvider;
private final CqlSessionFactory cqlSessionFactory;

public ClusterApi(
ClusterConnector clusterConnector,
ClusterProvider clusterProvider
ClusterProvider clusterProvider, CqlSessionFactory cqlSessionFactory
) {
this.clusterConnector = clusterConnector;
this.clusterProvider = clusterProvider;
this.cqlSessionFactory = cqlSessionFactory;
}

@GetMapping("")
Expand All @@ -61,16 +60,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 20ed5ae

Please sign in to comment.