refactor: cleanedup core importing and added better worker crashing

This commit is contained in:
Alexis Tyler
2020-05-31 12:11:39 +09:30
parent 07e3cd9020
commit 3dc9bd2db7
44 changed files with 332 additions and 704 deletions

View File

@@ -4,17 +4,15 @@
*/
import get from 'lodash.get';
// @ts-ignore
// import * as core from '../../../core/src/index';
import { v4 as uuid } from 'uuid';
import core from '@unraid/core';
import * as core from '@unraid/core';
import { apiManager, errors, log, states, config, pluginManager, modules } from '@unraid/core';
import { makeExecutableSchema, SchemaDirectiveVisitor } from 'graphql-tools'
import { mergeTypes } from 'merge-graphql-schemas';
import gql from 'graphql-tag';
import { typeDefs, resolvers } from './schema';
import { wsHasConnected, wsHasDisconnected } from '../ws';
const { apiManager, errors, log, states, config, pluginManager } = core;
const { AppError, FatalAppError, PluginError } = errors;
const { usersState } = states;
@@ -137,11 +135,11 @@ const types = mergeTypes([
]);
const getCoreModule = (moduleName) => {
if (!Object.keys(core.modules).includes(moduleName)) {
if (!Object.keys(modules).includes(moduleName)) {
throw new FatalAppError(`"${moduleName}" is not a valid core module.`);
}
return core.modules[moduleName];
return modules[moduleName];
};
const getPluginModule = (pluginName, pluginModuleName) => {

View File

@@ -3,9 +3,7 @@
* Written by: Alexis Tyler
*/
import core from '@unraid/core';
// @ts-ignore
// import * as core from '../../../../core/src/index';
import { pluginManager, pubsub, utils, bus, errors, states, modules } from '@unraid/core';
import dee from '@gridplus/docker-events';
import { setIntervalAsync } from 'set-interval-async/dynamic';
import GraphQLJSON from 'graphql-type-json';
@@ -15,7 +13,6 @@ import { run, publish } from '../../run';
import { cache } from '../../cache';
import { hasSubscribedToChannel, canPublishToChannel } from '../../ws';
const { pluginManager, pubsub, utils, log, bus, errors, states } = core;
const { ensurePermission } = utils;
const { usersState } = states;
const { AppError, PluginError } = errors;
@@ -26,7 +23,7 @@ bus.on('slots', async () => {
const user = usersState.findOne({ name: 'root' });
await run('array', 'UPDATED', {
moduleToRun: core.modules.getArray,
moduleToRun: modules.getArray,
context: {
user
}
@@ -45,7 +42,7 @@ dee.on('*', async (data) => {
return;
}
const { json } = await core.modules.getApps();
const { json } = await modules.getApps();
publish('info', 'UPDATED', json);
});
@@ -61,7 +58,7 @@ setIntervalAsync(async () => {
const user = usersState.findOne({ name: 'root' });
await run('services', 'UPDATED', {
moduleToRun: core.modules.getServices,
moduleToRun: modules.getServices,
context: {
user
}
@@ -76,7 +73,7 @@ setIntervalAsync(async () => {
const createSubscription = (channel, resource?) => ({
subscribe(_, __, context) {
if (!context.user) {
throw new AppError('<ws> No user found in context.');
throw new AppError('<ws> No user found in context.', 500);
}
// Check the user has permissison to subscribe to this endpoint
@@ -159,11 +156,11 @@ export const resolvers = {
// Verify plugin is installed and active
if (!pluginManager.isInstalled(pluginName, pluginModuleName)) {
throw new PluginError('Plugin not installed.');
throw new PluginError('Plugin not installed.', 500);
}
if (!pluginManager.isActive(pluginName, pluginModuleName)) {
throw new PluginError('Plugin disabled.');
throw new PluginError('Plugin disabled.', 500);
}
// It's up to the plugin to publish new data as needed

View File

@@ -4,16 +4,16 @@
*/
import am from 'am';
import core from '@unraid/core';
import { core, loadServer } from '@unraid/core';
import { server } from './server';
// Boot app
am(async () => {
// Load core
await core.core.load();
await core.load();
// Load server
await core.loadServer('graphql-api', server);
await loadServer('graphql-api', server);
}, (error: NodeJS.ErrnoException) => {
// We should only end here if core has an issue loading

View File

@@ -1,8 +1,7 @@
import { CoreResult } from '@unraid/core/dist/types';
import * as core from '@unraid/core'
import { CoreResult } from '@unraid/core/dist/lib/types';
import { pubsub, utils, log } from '@unraid/core';
import { canPublishToChannel } from './ws';
const { pubsub, utils, log } = core;
const { debugTimer } = utils;
/**

View File

@@ -5,18 +5,17 @@
import fs from 'fs';
import net from 'net';
import request = require('request');
import request from 'request';
import stoppable from 'stoppable';
import express from 'express';
import http from 'http';
import WebSocket from 'ws';
import core from '@unraid/core';
import { DynamixConfig } from '@unraid/core/dist/types';
import { log, config, utils, paths, states } from '@unraid/core';
import { DynamixConfig } from '@unraid/core/dist/lib/types';
import { createServer } from './patched-install-subscription-handlers';
import { graphql } from './graphql';
const { log, config, utils, paths, states } = core;
const { getEndpoints, globalErrorHandler, exitApp, loadState, sleep } = utils;
const { getEndpoints, globalErrorHandler, exitApp, loadState } = utils;
const { varState } = states;
/**

View File

@@ -1,6 +1,4 @@
import core from '@unraid/core';
const { log } = core;
import { log } from '@unraid/core';
interface subscription {
total: number

View File

@@ -22,6 +22,12 @@ const onWorkerExit = (_, code) => {
process.exit(0);
}
// Worker killed itself and doesn't want to be restarted
if (code === 130) {
log.debug(`Worker killed itself intentially. Exiting.`);
process.exit(130);
}
// Reload worker
if (code === null || code === 0) {
const newWorker = cluster.fork();
@@ -88,6 +94,26 @@ if (cluster.isMaster) {
if (cluster.isWorker) {
log.info(`<worker> pid = ${process.pid}`);
const isMissingMainFile = (error) => {
// Other error
if (error.code !== 'MODULE_NOT_FOUND') {
return false;
}
// Missing file but it's multiple levels deep
// This likely isn't main
if (error.requireStack.length >= 2) {
return false;
}
// It's a single require but for another file
if (error.requireStack[0] !== __filename) {
return false;
}
return true;
}
// @ts-ignore
const package = require('./package.json');
const { main } = package;
@@ -103,8 +129,10 @@ if (cluster.isWorker) {
log.info('<worker> loaded');
require(mainPath);
} catch (error) {
if (isMissingMainFile(error)) {
log.error(`<worker> Missing main file "${mainPath}".`);
process.exit(130);
}
log.error(error);
log.error(`<worker> Could not load main field "${mainPath}".`);
process.exit(1);
}
}

938
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -28,7 +28,7 @@
],
"dependencies": {
"@gridplus/docker-events": "github:OmgImAlexis/docker-events",
"@unraid/core": "github:unraid/core#master",
"@unraid/core": "github:unraid/core",
"accesscontrol": "^2.2.1",
"am": "^1.0.2",
"apollo-server": "2.13.1",
@@ -63,6 +63,7 @@
"source-map-support": "0.5.19",
"standard-version": "^7.1.0",
"ts-node": "8.10.1",
"tsup": "1.4.12",
"typescript": "3.8.3",
"xo": "0.30.0"
},

View File

@@ -1,13 +1,12 @@
{
"include": [
"src/**/*",
"index.d.ts"
"app/**/*"
],
"exclude": [
"node_modules"
],
"compilerOptions": {
"skipLibCheck": true,
"skipLibCheck": true,
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
@@ -21,7 +20,7 @@
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./dist", /* Redirect output structure to the directory. */
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
"rootDir": "./app", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
@@ -70,8 +69,5 @@
/* Advanced Options */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"typeAcquisition": {
"enable": true
}
}
}