Skip to content

Commit

Permalink
feat: new shutdown command + support from studio
Browse files Browse the repository at this point in the history
Fixed Issue #722
  • Loading branch information
lvca committed Jan 9, 2023
1 parent 0343689 commit 0faf000
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public HAMessageFactory(final ArcadeDBServer server) {
registerCommand(ReplicaReadyRequest.class);
registerCommand(UpdateClusterConfiguration.class);
registerCommand(ErrorResponse.class);
registerCommand(ServerShutdownRequest.class);
}

public void serializeCommand(final HACommand command, final Binary buffer, final long messageNumber) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright © 2021-present Arcade Data Ltd ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-FileCopyrightText: 2021-present Arcade Data Ltd ([email protected])
* SPDX-License-Identifier: Apache-2.0
*/
package com.arcadedb.server.ha.message;

import com.arcadedb.log.LogManager;
import com.arcadedb.server.ha.HAServer;

import java.util.logging.*;

public class ServerShutdownRequest extends HAAbstractCommand {
public ServerShutdownRequest() {
}

@Override
public HACommand execute(final HAServer server, final String remoteServerName, final long messageNumber) {
LogManager.instance().log(this, Level.SEVERE, "Server '%s' requested the shutdown of the server '%s'. Shutdown in progress...", null, remoteServerName,
server.getServerName());
server.getServer().stop();
return null;
}

@Override
public String toString() {
return "shutdown";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ else if (parts.length == 1)
.post("/user", new PostCreateUserHandler(this))//
.delete("/user/{userName}", new DeleteDropUserHandler(this))//
.get("/server", new GetServerHandler(this))//
.post("/server/{command}", new PostServerCommandHandler(this))//
.post("/server", new PostServerCommandHandler(this))//
.get("/ready", new GetReadyHandler(this))//
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ protected JSONObject createResult(final SecurityUser user, final Database databa
final JSONObject json = new JSONObject();
if (database != null)
json.setDateFormat(database.getSchema().getDateTimeFormat());
json.put("user", user.getName()).put("version", Constants.getVersion());
json.put("user", user.getName()).put("version", Constants.getVersion()).put("serverName", httpServer.getServer().getServerName());
return json;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@
*/
package com.arcadedb.server.http.handler;

import com.arcadedb.database.Binary;
import com.arcadedb.database.Database;
import com.arcadedb.serializer.json.JSONObject;
import com.arcadedb.server.ha.Leader2ReplicaNetworkExecutor;
import com.arcadedb.server.ha.message.ServerShutdownRequest;
import com.arcadedb.server.http.HttpServer;
import com.arcadedb.server.security.ServerSecurityUser;
import io.undertow.server.HttpServerExchange;

import java.util.*;
import java.io.*;

public class PostServerCommandHandler extends DatabaseAbstractHandler {
public PostServerCommandHandler(final HttpServer httpServer) {
Expand All @@ -36,12 +40,10 @@ protected boolean requiresDatabase() {
}

@Override
public void execute(final HttpServerExchange exchange, final ServerSecurityUser user, final Database database) {
final Deque<String> commandPar = exchange.getQueryParameters().get("command");
String command = commandPar.isEmpty() ? null : commandPar.getFirst().trim();
if (command.isEmpty())
command = null;
public void execute(final HttpServerExchange exchange, final ServerSecurityUser user, final Database database) throws IOException {
final JSONObject payload = new JSONObject(parseRequestPayload(exchange));

final String command = payload.has("command") ? payload.getString("command") : null;
if (command == null) {
exchange.setStatusCode(400);
exchange.getResponseSender().send("{ \"error\" : \"Server command is null\"}");
Expand All @@ -50,12 +52,40 @@ public void execute(final HttpServerExchange exchange, final ServerSecurityUser

httpServer.getServer().getServerMetrics().meter("http.server-command").mark();


if (command.startsWith("shutdown"))
shutdownServer(command);
else if (command.startsWith("disconnect "))
disconnectServer(command);
else {
exchange.setStatusCode(400);
exchange.getResponseSender().send("{ \"error\" : \"Server command not valid\"}");
return;
}

exchange.setStatusCode(200);
exchange.getResponseSender().send("{ \"result\" : \"ok\"}");
}

private void shutdownServer(final String command) throws IOException {
if (command.equals("shutdown")) {
// SHUTDOWN CURRENT SERVER
httpServer.getServer().stop();
} else if (command.startsWith("shutdown ")) {
final String serverName = command.substring("shutdown ".length());
final Leader2ReplicaNetworkExecutor replica = httpServer.getServer().getHA().getReplica(serverName);

final Binary buffer = new Binary();
httpServer.getServer().getHA().getMessageFactory().serializeCommand(new ServerShutdownRequest(), buffer, -1);
replica.sendMessage(buffer);
}
}

private void disconnectServer(final String command) {
final String serverName = command.substring("disconnect ".length());
final Leader2ReplicaNetworkExecutor replica = httpServer.getServer().getHA().getReplica(serverName);
replica.close();
}

@Override
protected boolean requiresTransaction() {
return false;
Expand Down
8 changes: 6 additions & 2 deletions server/src/main/resources/static/api.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
<div class="tab-pane fade" id="tab-api" role="tabpanel">
<div class="row">
<div class="col-12"><h4><i class="fa fa-plug"></i> HTTP API</h4></div>
</div>

<hr>

<div class="row">
<div class="col-12">
<h4><i class="fa fa-plug"></i> HTTP API</h4>
<br>
<div class="row">
<div class="col-1">
<b>Method</b>
Expand Down
6 changes: 5 additions & 1 deletion server/src/main/resources/static/cluster.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
<div class="tab-pane fade" id="tab-cluster" role="tabpanel">
<div class="row">
<div class="col-12"><h4><i class="fa fa-network-wired"></i> Cluster</h4></div>
</div>

<div class="row">
<div class="col-12">
<span id="serverInfo"></span>
</div>
</div>

<br>
<hr>

<div class="row">
<div class="col-2">
Expand Down
22 changes: 10 additions & 12 deletions server/src/main/resources/static/database.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
<div class="tab-pane fade" id="tab-database" role="tabpanel">

<div class="row">
<div class="col-2">
<label for="user">User</label>
</div>

<div class="col-10">
<span id="user"></span>
</div>
<div class="col-12"><h4><i class="fa fa-database"></i> Database</h4></div>
</div>

<div class="row">
<div class="col-2">
<label for="inputDatabase" class="form-label">Current database</label>
</div>
<div class="col-7">
<select id="inputDatabase" class="form-control"></select>
<div class="col-9">
<div class="form-inline">
<div class="form-group">
<label for="inputDatabase" id="user"></label>@
<select id="inputDatabase" class="form-control"></select>
</div>
</div>
</div>
<div class="col-3">
<button class="btn btn-pill" onclick="createDatabase()"><i class="fa fa-plus"></i> Create</button>
Expand All @@ -24,6 +20,8 @@
</div>
</div>

<hr>

<div class="row">
<div class="col-12">
<br><br>
Expand Down
34 changes: 32 additions & 2 deletions server/src/main/resources/static/js/studio-cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ function updateCluster( callback ){
record.push( escapeHtml( row.leftOn ) );
record.push( escapeHtml( row.throughput ) );
record.push( escapeHtml( row.latency ) );
record.push( "<button class='btn' onclick='shutdownServer(\""+ row.name + "\")'><i class='fas fa-power-off' style='color: red;'></i></button>" );

tableRecords.push( record );
}

Expand All @@ -42,7 +44,8 @@ function updateCluster( callback ){
{title: "Joined On"},
{title: "Left On"},
{title: "Throughput"},
{title: "Latency"}
{title: "Latency"},
{title: "Commands"},
],
data: tableRecords,
});
Expand Down Expand Up @@ -70,6 +73,33 @@ function renderDatabases(databases){
result += "<tr><td>"+db.name+"</td><td><button enabled='false'></td>";
}
result += '</table>';

return result;
}

function shutdownServer(serverName){
let command = serverName != null ? "shutdown " + serverName : "shutdown";
let message = serverName != null ? "Are you sure to shut down the server '"+serverName+"'?" : "Are you sure to shut down the current server?";
globalConfirm( "Shutdown Server", message, "warning", function(){ executeServerCommand(command, "Server shutdown request sent successfully");} );
}

function executeServerCommand(command, successMessage) {
if( command == null || command == "" )
return;

jQuery.ajax({
type: "POST",
url: "/api/v1/server",
data: JSON.stringify({
command: command,
}),
beforeSend: function (xhr){
xhr.setRequestHeader('Authorization', globalCredentials);
}
})
.done(function(data){
globalNotify( successMessage, data.result, "success");
})
.fail(function( jqXHR, textStatus, errorThrown ){
globalNotify( "Error", jqXHR.responseJSON.detail, "danger");
});
}
2 changes: 1 addition & 1 deletion server/src/main/resources/static/js/studio-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function updateServer( callback ){
if( pos > -1 ) {
version = version.substring( 0, pos ) + " <span style='font-size: 70%'>" + version.substring( pos ) + "</span>";
}
$("#serverVersion").html(version);
$("#serverConnection").html( data.user + "@" + data.serverName + " - v." + version);

if ( $.fn.dataTable.isDataTable( '#serverMetrics' ) )
try{ $('#serverMetrics').DataTable().destroy(); $('#serverMetrics').empty(); } catch(e){};
Expand Down
2 changes: 1 addition & 1 deletion server/src/main/resources/static/resources.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="tab-pane fade" id="tab-resources" role="tabpanel">
<h4><i class="fa fa-info-circle"></i>&nbsp;Useful Resources</h4>
<br>
<hr>
<div class="row">
<div class="col-6">
<ul>
Expand Down
16 changes: 7 additions & 9 deletions server/src/main/resources/static/server.html
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
<div class="tab-pane fade" id="tab-server" role="tabpanel">
<div class="row">
<div class="col-2">
<label for="serverVersion">Server Version</label>
</div>
<div class="col-10">
<span id="serverVersion"></span>
</div>
<div class="col-12"><h4><i class="fa fa-server"></i> Server</h4></div>
</div>

<div class="row">
<div class="col-2">
<label for="serverUser">User</label>
<label for="serverConnection">Connected to</label>
</div>
<div class="col-8">
<span id="serverConnection"></span>
</div>
<div class="col-10">
<span id="serverUser"></span>
<div class="col-2 text-right">
<button class="btn" onclick="shutdownServer()">Shutdown <i class="fas fa-power-off" style="color: red;"></i></button>
</div>
</div>

Expand Down

0 comments on commit 0faf000

Please sign in to comment.