Improve app exit notifications and fix wiki location

* Refactor server so app is passed back to main index.js so we can handle SIGTERM in a central location and determine if exit was based on uncaught error or not
* Fix missing assignment of default wikiLocation to manager
* await discord notifier so on app exit the notification is actually sent before exit
This commit is contained in:
FoxxMD
2021-07-28 10:45:12 -04:00
parent 2616439f5f
commit 4865259ae8
6 changed files with 600 additions and 571 deletions

View File

@@ -165,16 +165,12 @@ export class App {
defaultModqueueStream.on('error', modStreamErrorListener('modqueue'));
CacheManager.modStreams.set('unmoderated', defaultUnmoderatedStream);
CacheManager.modStreams.set('modqueue', defaultModqueueStream);
}
const onTerm = () => {
for(const m of this.subManagers) {
m.notificationManager.handle('runStateChanged', 'Application Shutdown', 'The application was shutdown');
}
async onTerminate(reason = 'The application was shutdown') {
for(const m of this.subManagers) {
await m.notificationManager.handle('runStateChanged', 'Application Shutdown', reason);
}
process.on('SIGTERM', () => {
onTerm();
});
}
async testClient() {
@@ -235,7 +231,7 @@ export class App {
let subSchedule: Manager[] = [];
// get configs for subs we want to run on and build/validate them
for (const sub of subsToRun) {
const manager = new Manager(sub, this.client, this.logger, {dryRun: this.dryRun, sharedModqueue: this.sharedModqueue});
const manager = new Manager(sub, this.client, this.logger, {dryRun: this.dryRun, sharedModqueue: this.sharedModqueue, wikiLocation: this.wikiLocation});
try {
await manager.parseConfiguration('system', true, {suppressNotification: true});
} catch (err) {

View File

@@ -11,7 +11,7 @@ class DiscordNotifier {
this.url = url;
}
handle(val: NotificationContent) {
async handle(val: NotificationContent) {
const h = new webhook.Webhook(this.url);
const hook = new webhook.MessageBuilder();
@@ -39,7 +39,7 @@ class DiscordNotifier {
break;
}
h.send(hook);
await h.send(hook);
}
}

View File

@@ -64,7 +64,7 @@ class NotificationManager {
}
}
handle(name: NotificationEventType, title: string, body?: string, causedBy?: string, logLevel?: string) {
async handle(name: NotificationEventType, title: string, body?: string, causedBy?: string, logLevel?: string) {
if (this.notifiers.length === 0 || this.events.length === 0) {
return;
@@ -109,7 +109,7 @@ class NotificationManager {
this.logger.info(`Sending notification for ${name} to providers: ${notifiers.map(x => `${x.name} (${x.type})`).join(', ')}`);
for (const n of notifiers) {
n.handle({
await n.handle({
title: `${title} (${this.name})`,
body: body || '',
footer: footer.length > 0 ? footer.join('\n') : undefined,

File diff suppressed because it is too large Load Diff

View File

@@ -55,6 +55,7 @@ export interface CheckTask {
export interface RuntimeManagerOptions extends ManagerOptions {
sharedModqueue?: boolean;
wikiLocation?: string;
}
export class Manager {
@@ -65,7 +66,7 @@ export class Manager {
submissionChecks!: SubmissionCheck[];
commentChecks!: CommentCheck[];
resources!: SubredditResources;
wikiLocation: string = 'botconfig/contextbot';
wikiLocation: string;
lastWikiRevision?: DayjsObj
lastWikiCheck: DayjsObj = dayjs();
//wikiUpdateRunning: boolean = false;
@@ -177,7 +178,7 @@ export class Manager {
}
constructor(sub: Subreddit, client: Snoowrap, logger: Logger, opts: RuntimeManagerOptions = {}) {
const {dryRun, sharedModqueue = false} = opts;
const {dryRun, sharedModqueue = false, wikiLocation = 'botconfig/contextbot'} = opts;
this.displayLabel = opts.nickname || `${sub.display_name_prefixed}`;
const getLabels = this.getCurrentLabels;
const getDisplay = this.getDisplay;
@@ -192,6 +193,7 @@ export class Manager {
}
}, mergeArr);
this.globalDryRun = dryRun;
this.wikiLocation = wikiLocation;
this.sharedModqueue = sharedModqueue;
this.subreddit = sub;
this.client = client;

View File

@@ -41,6 +41,15 @@ preRunCmd.allowUnknownOption();
const program = new Command();
(async function () {
let app: App;
let errorReason: string | undefined;
process.on('SIGTERM', async () => {
debugger;
if(app !== undefined) {
await app.onTerminate(errorReason);
}
process.exit(errorReason === undefined ? 0 : 1);
});
try {
let runCommand = program
@@ -77,11 +86,12 @@ const program = new Command();
if (redirectUri === undefined) {
logger.warn(`No 'redirectUri' found in arg/env. Bot will still run but web interface will not be accessible.`);
}
const server = createWebServer(config);
await server;
const [server, bot] = createWebServer(config);
app = bot;
await server();
}
} else {
const app = new App(config);
app = new App(config);
await app.buildManagers();
await app.runManagers();
}
@@ -103,7 +113,7 @@ const program = new Command();
.action(async (activityIdentifier, type, commandOptions = {}) => {
const config = buildOperatorConfigWithDefaults(await parseOperatorConfigFromSources(commandOptions));
const {checks = []} = commandOptions;
const app = new App(config);
app = new App(config);
let a;
const commentId = commentReg(activityIdentifier);
@@ -164,7 +174,7 @@ const program = new Command();
const config = buildOperatorConfigWithDefaults(await parseOperatorConfigFromSources(opts));
const {checks = []} = opts;
const {subreddits: {names}} = config;
const app = new App(config);
app = new App(config);
await app.buildManagers(names);
@@ -193,6 +203,7 @@ const program = new Command();
}
console.log(err);
}
errorReason = `Application crashed due to an uncaught error: ${err.message}`;
process.kill(process.pid, 'SIGTERM');
}
}());