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 14dada8
Show file tree
Hide file tree
Showing 15 changed files with 389 additions and 288 deletions.
88 changes: 82 additions & 6 deletions 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,40 +129,115 @@ 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 })
getLogger().debug({ fn: 'stopServerUsingPID', pid: pid })

try {
const result = process.kill(pid, 'SIGTERM')
getLogger().debug({ fn: 'stopServer', pid: pid, stopped: result })
getLogger().debug({ fn: 'stopServerUsingPID', pid: pid, stopped: result })
return result
} catch (err) {
// @ts-ignore
if (err.code === 'ESRCH') {
getLogger().debug({
fn: 'stopServer',
fn: 'stopServerUsingPID',
msg: 'Server already stopped',
pid: pid,
})

return true
}

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

return false
}
}

getLogger().error({
fn: 'stopServer',
fn: 'stopServerUsingPID',
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
}
})
})
}
37 changes: 33 additions & 4 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 Down Expand Up @@ -66,8 +70,9 @@ export async function mochaGlobalSetup(): Promise<number | undefined> {
// don't fix viewport data length in tests
setAutoFixViewportDataLength(false)

const pid = await startServer(rootPath, getClientVersion(), testPort)
mochaGlobalTeardown()

const pid = await startServer(rootPath, getClientVersion(), testPort)
if (pid) {
fs.writeFileSync(pidFile, pid.toString(), 'utf8')
}
Expand All @@ -78,25 +83,47 @@ 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 (fs.existsSync(pidFile)) {
const pid = parseInt(fs.readFileSync(pidFile, 'utf8').toString())
if (stopServer(pid)) {

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

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

return true
}

getLogger().warn({
fn: 'mochaGlobalTeardown',
msg: 'api stop failed',
})

if (stopServerUsingPID(pid)) {
fs.unlinkSync(pidFile)

getLogger().debug({
fn: 'mochaGlobalTeardown',
msg: 'server stopped',
Expand All @@ -106,11 +133,13 @@ export function mochaGlobalTeardown(): boolean {
return true
}
}

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

return false
}
Loading

0 comments on commit 14dada8

Please sign in to comment.