Skip to content

Commit

Permalink
feature: allow final shutdown notification (#17)
Browse files Browse the repository at this point in the history
* feature: allow final shutdown notification

* ensure shutdown URL is in debconf

* make shutdown URL not required

* add handling for errors in shutdown

* throw error object

* fix lint
  • Loading branch information
aaronkvanmeerten authored Apr 19, 2024
1 parent a20adc6 commit 833953c
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 0 deletions.
2 changes: 2 additions & 0 deletions debian/jitsi-autoscaler-sidecar.postinst
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ case "$1" in
INSTANCE_TYPE="JVB"
POLLING_URL="http://localhost:3000/sidecar/poll"
STATUS_URL="http://localhost:3000/sidecar/status"
SHUTDOWN_URL="http://localhost:3000/sidecar/shutdown"

# and we're done with debconf
db_stop
Expand Down Expand Up @@ -99,6 +100,7 @@ case "$1" in
sed -i s#INSTANCE_TYPE=#INSTANCE_TYPE=${INSTANCE_TYPE}#g $SIDECAR_CONFIG
sed -i s#POLLING_URL=#POLLING_URL=${POLLING_URL}#g $SIDECAR_CONFIG
sed -i s#STATUS_URL=#STATUS_URL=${STATUS_URL}#g $SIDECAR_CONFIG
sed -i s#SHUTDOWN_URL=#SHUTDOWN_URL=${SHUTDOWN_URL}#g $SIDECAR_CONFIG
fi
;;

Expand Down
4 changes: 4 additions & 0 deletions env.example
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ POLLING_URL=
# e.g. 'http://localhost:3000/sidecar/status'
STATUS_URL=

# The autoscaler URL used by the sidecar to report final shutdown status (required)
# e.g. 'http://localhost:3000/sidecar/shutdown'
SHUTDOWN_URL=

# The command the sidecar can run on the local instance to gracefully shut it down
#GRACEFUL_SHUTDOWN_SCRIPT=/usr/local/bin/graceful_shutdown.sh

Expand Down
36 changes: 36 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const autoscalePoller = new Poller({
pollUrl: config.PollingURL,
statusUrl: config.StatusURL,
statsUrl: config.StatsReportURL,
shutdownUrl: config.ShutdownURL,
instanceDetails,
asapRequest
});
Expand All @@ -52,6 +53,7 @@ let statsReport: StatsReport;

let reconfigureLock = false;
let shutdownLock = false;
let shutdownReported = false;

interface JibriMetadata {
[key: string]: string;
Expand Down Expand Up @@ -90,6 +92,32 @@ async function jibriStateWebhook(req: Request, res: Response) {
res.send('{"status":"OK"}');
}

/**
* The hook to report final shutdown to server
*
* @param req the request.
* @param res the response.
*/
async function instanceShutdownWebhook(req: Request, res: Response) {
// update global stats report with
if (shutdownReported) {
res.status(200);
shutdownReported = true;
res.send('{"status":"OK", "message":"Already reported shutdown"}');
} else {
const ret = await autoscalePoller.reportShutdown();

if (ret) {
res.status(200);
shutdownReported = true;
res.send('{"status":"OK"}');
} else {
res.status(500);
res.send('{"status":"FAILED"}');
}
}
}

/**
* Polls stats every 1 second.
*/
Expand Down Expand Up @@ -180,6 +208,14 @@ app.get('/health', (req: express.Request, res: express.Response) => {
res.send('healthy!');
});

app.post('/hook/v1/shutdown', async (req, res, next) => {
try {
await instanceShutdownWebhook(req, res);
} catch (err) {
next(err);
}
});

app.post('/hook/v1/status', async (req, res, next) => {
try {
await jibriStateWebhook(req, res);
Expand Down
22 changes: 22 additions & 0 deletions src/autoscale_poller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface AutoscalePollerOptions {
pollUrl: string;
statusUrl: string;
statsUrl: string;
shutdownUrl: string;
instanceDetails: InstanceDetails;
asapRequest: AsapRequest;
}
Expand All @@ -33,6 +34,7 @@ export default class AutoscalePoller {
private pollUrl: string;
private statusUrl: string;
private statsUrl: string;
private shutdownUrl: string;
private asapRequest: AsapRequest;

/**
Expand All @@ -43,12 +45,32 @@ export default class AutoscalePoller {
this.pollUrl = options.pollUrl;
this.statusUrl = options.statusUrl;
this.statsUrl = options.statsUrl;
this.shutdownUrl = options.shutdownUrl;
this.instanceDetails = options.instanceDetails;
this.asapRequest = options.asapRequest;

this.pollWithStats = this.pollWithStats.bind(this);
}

/**
* Reports shutdown status by sending a json.
*/
async reportShutdown(): Promise<boolean> {
try {
if (!this.shutdownUrl) {
throw new Error('No shutdown URL configured');
}
await this.asapRequest.postJson(this.shutdownUrl, this.instanceDetails);

return true;
} catch (err) {
logger.error('Error sending shutdown report', { err,
traceback: err.traceback });
}

return false;
}

/**
* Reports stats by sending a json.
* @param statsReport
Expand Down
8 changes: 8 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const env = envalid.cleanEnv(process.env, {
ASAP_JWT_AUD: envalid.str({ default: 'jitsi-autoscaler' }),
ENABLE_REPORT_STATS: envalid.bool({ default: false }),
POLLING_URL: envalid.str(),
SHUTDOWN_URL: envalid.str({ default: '' }),
STATUS_URL: envalid.str(),
STATS_RETRIEVE_URL: envalid.str({ default: '' }),
STATS_REPORT_URL: envalid.str({ default: '' }),
Expand All @@ -37,7 +38,14 @@ export default {

// number of seconds to wait between polling for shutdown
ShutdownPollingInterval: env.SHUTDOWN_POLLING_INTERVAL,

// url for reporting final shutdown
ShutdownURL: env.SHUTDOWN_URL,

// url to poll for server commands
PollingURL: env.POLLING_URL,

// url to report status and stats
StatusURL: env.STATUS_URL,

// number of seconds to wait before polling for stats
Expand Down

0 comments on commit 833953c

Please sign in to comment.