Skip to content

Commit

Permalink
Create Server shutdown RPC service:
Browse files Browse the repository at this point in the history
- Add ServerControl related RPC to proto.
- Wire in ServerControl to scala server code.
- Wire ServerControl into typescript client code with stopServerGraceful and stopServerImmediate.

Closes #553
  • Loading branch information
shanedell committed Mar 8, 2023
1 parent 58bc60a commit 3d96a86
Show file tree
Hide file tree
Showing 15 changed files with 411 additions and 284 deletions.
78 changes: 77 additions & 1 deletion src/rpc/client/ts/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { getLogger } from './logger'
import { getClient } from './client'
import { Empty } from 'google-protobuf/google/protobuf/empty_pb'
import * as fs from 'fs'
import { ServerControlKind, ServerControlRequest } from './omega_edit_pb'

/**
* Artifact class
Expand Down Expand Up @@ -128,14 +129,85 @@ export async function startServer(
})
}

/**
* Stops the server gracefully
* @returns true if the server was stopped
*/
export function stopServerGraceful(): Promise<number> {
return new Promise<number>(async () => {
return stopServer(ServerControlKind.SERVER_CONTROL_GRACEFUL_SHUTDOWN)
})
}

/**
* Stops the server immediatly
* @returns true if the server was stopped
*/
export function stopServerImmediate(): Promise<number> {
return new Promise<number>(async () => {
return stopServer(ServerControlKind.SERVER_CONTROL_IMMEDIATE_SHUTDOWN)
})
}

/**
* Stop the server
* @param kind defines how the server should shutdown
* @returns true if the server was stopped
*/
function stopServer(kind: ServerControlKind): Promise<number> {
getLogger().debug({
fn: 'stopServer',
kind: kind.toString(),
})

return new Promise<number>((resolve, reject) => {
getClient().serverControl(
new ServerControlRequest().setKind(kind),
(err, resp) => {
if (err) {
getLogger().error({
fn: 'stopServer',
err: {
msg: err.message,
details: err.details,
code: err.code,
stack: err.stack,
},
})

return reject('stopServer error: ' + err.message)
}

if (resp.getResponseCode() != 0) {
getLogger().error({
fn: 'stopServer',
err: { msg: 'stopServer exit status: ' + resp.getResponseCode() },
})

return reject('stopServer error')
}

getLogger().debug({
fn: 'stopServer',
kind: kind.toString(),
stopped: true,
})

return resolve(resp.getResponseCode())
}
)
})
}

/**
* Stop the server
* @param pid pid of the server process
* @returns true if the server was stopped
*/
export function stopServer(pid: number | undefined): boolean {
export function stopServerUsingPID(pid: number | undefined): boolean {
if (pid) {
getLogger().debug({ fn: 'stopServer', pid: pid })

try {
const result = process.kill(pid, 'SIGTERM')
getLogger().debug({ fn: 'stopServer', pid: pid, stopped: result })
Expand All @@ -148,12 +220,15 @@ export function stopServer(pid: number | undefined): boolean {
msg: 'Server already stopped',
pid: pid,
})

return true
}

getLogger().error({
fn: 'stopServer',
err: { msg: 'Error stopping server', pid: pid, err: err },
})

return false
}
}
Expand All @@ -162,6 +237,7 @@ export function stopServer(pid: number | undefined): boolean {
fn: 'stopServer',
err: { msg: 'Error stopping server, no PID' },
})

return false
}

Expand Down
39 changes: 23 additions & 16 deletions src/rpc/client/ts/src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,22 +314,29 @@ export function unsubscribeSession(session_id: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
const request = new ObjectId().setId(session_id)
getLogger().debug({ fn: 'unsubscribeSession', rqst: request.toObject() })
getClient().unsubscribeToSessionEvents(request, (err, r) => {
if (err) {
getLogger().error({
fn: 'unsubscribeSession',
err: {
msg: err.message,
details: err.details,
code: err.code,
stack: err.stack,
},
})
return reject('unsubscribeSession error: ' + err.message)
}
getLogger().debug({ fn: 'unsubscribeSession', resp: r.toObject() })
return resolve(r.getId())
})
getClient()
.unsubscribeToSessionEvents(request, (err, r) => {
if (err) {
getLogger().error({
fn: 'unsubscribeSession',
err: {
msg: err.message,
details: err.details,
code: err.code,
stack: err.stack,
},
})
return reject('unsubscribeSession error: ' + err.message)
}
getLogger().debug({ fn: 'unsubscribeSession', resp: r.toObject() })
return resolve(r.getId())
})
.on('error', (err) => {
// Call cancelled thrown when server is shutdown
if (!err.message.includes('Call cancelled')) {
throw err
}
})
})
}

Expand Down
39 changes: 23 additions & 16 deletions src/rpc/client/ts/src/viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,21 +333,28 @@ export function unsubscribeViewport(viewport_id: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
const request = new ObjectId().setId(viewport_id)
getLogger().debug({ fn: 'unsubscribeViewport', rqst: request.toObject() })
getClient().unsubscribeToViewportEvents(request, (err, r) => {
if (err) {
getLogger().error({
fn: 'unsubscribeViewport',
err: {
msg: err.message,
details: err.details,
code: err.code,
stack: err.stack,
},
})
return reject(`unsubscribeViewport error: ${err.message}`)
}
getLogger().debug({ fn: 'unsubscribeViewport', resp: r.toObject() })
return resolve(r.getId())
})
getClient()
.unsubscribeToViewportEvents(request, (err, r) => {
if (err) {
getLogger().error({
fn: 'unsubscribeViewport',
err: {
msg: err.message,
details: err.details,
code: err.code,
stack: err.stack,
},
})
return reject(`unsubscribeViewport error: ${err.message}`)
}
getLogger().debug({ fn: 'unsubscribeViewport', resp: r.toObject() })
return resolve(r.getId())
})
.on('error', (err) => {
// Call cancelled thrown when server is shutdown
if (!err.message.includes('Call cancelled')) {
throw err
}
})
})
}
65 changes: 60 additions & 5 deletions src/rpc/client/ts/tests/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
*/

import { createSimpleFileLogger, getLogger, setLogger } from '../src/logger'
import { startServer, stopServer } from '../src/server'
import {
startServer,
stopServerImmediate,
stopServerUsingPID,
} from '../src/server'
import { getClientVersion } from '../src/version'
import { setAutoFixViewportDataLength } from '../src/viewport'
import * as fs from 'fs'
Expand All @@ -41,6 +45,7 @@ function getPidFile(port: number): string {

/**
* Mocha test fixture to setup the logger and start the server
* Mocha test fixture to setup to start the server
* @remarks used by mocha
*/
export async function mochaGlobalSetup(): Promise<number | undefined> {
Expand All @@ -60,14 +65,12 @@ export async function mochaGlobalSetup(): Promise<number | undefined> {
fn: 'mochaGlobalSetup',
msg: 'starting server',
port: testPort,
pidfile: getPidFile(testPort),
})

// don't fix viewport data length in tests
setAutoFixViewportDataLength(false)

const pid = await startServer(rootPath, getClientVersion(), testPort)
mochaGlobalTeardown()
if (pid) {
fs.writeFileSync(pidFile, pid.toString(), 'utf8')
}
Expand All @@ -78,24 +81,42 @@ export async function mochaGlobalSetup(): Promise<number | undefined> {
pid: pid,
pidfile: getPidFile(testPort),
})

return pid
}

/**
* Mocha test fixture to stop the server
* @remarks used by mocha
*/
export function mochaGlobalTeardown(): boolean {
export async function mochaGlobalTeardown(): Promise<boolean> {
const pidFile = getPidFile(testPort)
getLogger().debug({
fn: 'mochaGlobalTeardown',
msg: 'stopping server',
port: testPort,
pidfile: pidFile,
})

if ((await stopServerImmediate()) != 0) {
if (fs.existsSync(pidFile)) {
fs.unlinkSync(pidFile)
}

getLogger().debug({
fn: 'mochaGlobalTeardown',
msg: 'server stopped',
port: testPort,
stopped: true,
})

return true
}

if (fs.existsSync(pidFile)) {
const pid = parseInt(fs.readFileSync(pidFile, 'utf8').toString())
if (stopServer(pid)) {

if (stopServerUsingPID(pid)) {
fs.unlinkSync(pidFile)
getLogger().debug({
fn: 'mochaGlobalTeardown',
Expand All @@ -106,11 +127,45 @@ export function mochaGlobalTeardown(): boolean {
return true
}
}

getLogger().debug({
fn: 'mochaGlobalTeardown',
msg: 'failed to stop server',
port: testPort,
pidfile: pidFile,
})

return false
}

// export async function mochaGlobalTeardown(): Promise<number> {
// let stopped = await stopServerImmediate()
// .catch((err) => {
// getLogger().error({
// fn: 'stopServer',
// err: {
// msg: err.message,
// details: err.details,
// code: err.code,
// stack: err.stack,
// },
// })

// // Call cancelled thrown when server is shutdown
// if (!err.message.includes('Call cancelled')) {
// throw err
// }

// return 0
// })

// if (stopped != 0) {
// getLogger().debug({
// fn: 'mochaGlobalTeardown',
// msg: 'failed to stop server',
// port: testPort,
// })
// }

// return stopped
// }
Loading

0 comments on commit 3d96a86

Please sign in to comment.