mirror of
https://github.com/unraid/api.git
synced 2026-04-30 12:10:15 -05:00
fix(mothership): cleanup reconnection events
This commit is contained in:
@@ -60,5 +60,12 @@ You should get something like this back.
|
||||
Click the "Schema" and "Docs" button on the right side of the playground to learn more.
|
||||
For exploring the schema visually I'd suggest using [Voyager](https://apis.guru/graphql-voyager/).
|
||||
|
||||
# Development
|
||||
|
||||
## Running this locally
|
||||
```bash
|
||||
NCHAN=disable DEBUG=true LOG_LEVEL=info PATHS_STATES=$(pwd)/dev/states PATHS_DYNAMIX_CONFIG=$(pwd)/dev/dynamix.cfg PORT=5000 node index.js
|
||||
```
|
||||
|
||||
## License
|
||||
Copyright 2019 Lime Technology Inc. All rights reserved.
|
||||
|
||||
+16
-11
@@ -40,6 +40,7 @@ const baseTypes = [gql`
|
||||
type Query {
|
||||
# This should always be available even for guest users
|
||||
welcome: Welcome! @func(module: "getWelcome")
|
||||
online: Boolean!
|
||||
info: Info!
|
||||
pluginModule(plugin: String!, module: String!, params: JSON, result: String): JSON @func(result: "json")
|
||||
}
|
||||
@@ -279,19 +280,23 @@ const schema = makeExecutableSchema({
|
||||
});
|
||||
|
||||
const ensureApiKey = (apiKeyToCheck: string) => {
|
||||
// Check there is atleast one valid key
|
||||
if (core.apiManager.getValidKeys().length !== 0) {
|
||||
if (!apiKeyToCheck) {
|
||||
throw new AppError('Missing API key.');
|
||||
}
|
||||
try {
|
||||
// Check there is atleast one valid key
|
||||
if (core.apiManager.getValidKeys().length !== 0) {
|
||||
if (!apiKeyToCheck) {
|
||||
throw new AppError('Missing API key.');
|
||||
}
|
||||
|
||||
if (!apiManager.isValid(apiKeyToCheck)) {
|
||||
throw new AppError('Invalid API key.');
|
||||
}
|
||||
} else {
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
throw new AppError('No valid API keys active.');
|
||||
if (!apiManager.isValid(apiKeyToCheck)) {
|
||||
throw new AppError('Invalid API key.');
|
||||
}
|
||||
} else {
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
throw new AppError('No valid API keys active.');
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
throw new AppError('Invalid Api key.');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Written by: Alexis Tyler
|
||||
*/
|
||||
|
||||
import { pluginManager, pubsub, utils, bus, errors, states, modules, apiManager } from '@unraid/core';
|
||||
import { pluginManager, pubsub, utils, bus, errors, states, modules, apiManager, log } from '@unraid/core';
|
||||
import dee from '@gridplus/docker-events';
|
||||
import { setIntervalAsync } from 'set-interval-async/dynamic';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
@@ -105,6 +105,7 @@ const getServers = (): Server[] => {
|
||||
|
||||
// Fall back to locally generated data
|
||||
if (servers.length === 0) {
|
||||
log.debug('Falling back to local state for /servers endpoint');
|
||||
const guid = varState?.data?.regGuid;
|
||||
// For now use the my_servers key
|
||||
// Later we should return the correct one for the current user with the correct scope, etc.
|
||||
@@ -116,7 +117,11 @@ const getServers = (): Server[] => {
|
||||
const remoteurl = null;
|
||||
|
||||
return [{
|
||||
owner: null,
|
||||
owner: {
|
||||
username: 'root',
|
||||
url: '',
|
||||
avatar: ''
|
||||
},
|
||||
guid,
|
||||
apikey,
|
||||
name,
|
||||
@@ -128,12 +133,15 @@ const getServers = (): Server[] => {
|
||||
}];
|
||||
}
|
||||
|
||||
log.debug('Using upstream for /servers endpoint');
|
||||
|
||||
// Return servers from upstream cache
|
||||
return servers;
|
||||
};
|
||||
|
||||
export const resolvers = {
|
||||
Query: {
|
||||
online: () => true,
|
||||
info: () => ({}),
|
||||
vms: () => ({}),
|
||||
server(_: unknown, { name }, context: Context) {
|
||||
|
||||
+7
-4
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs';
|
||||
import request from 'request';
|
||||
import WebSocket from 'ws';
|
||||
import { log, utils, paths, states } from '@unraid/core';
|
||||
import { log, utils, paths, states, config } from '@unraid/core';
|
||||
import { DynamixConfig } from '@unraid/core/dist/lib/types';
|
||||
import { userCache, CachedServer } from './cache';
|
||||
|
||||
@@ -88,7 +88,10 @@ const isServersPayload = (payload: any): payload is Servers => payload.topic ===
|
||||
|
||||
const forwardMessageToLocalSocket = (message: Message, apiKey: string) => {
|
||||
log.debug(`Got a "${message.type}" request from mothership, forwarding to socket.`);
|
||||
request.post('http://unix:/var/run/graphql-api.sock:/graphql', {
|
||||
const port = config.get('graphql-api-port');
|
||||
const localEndpoint = (!isNaN(port as number)) ? `localhost:${port}` : `unix:${port}:`;
|
||||
const url = `http://${localEndpoint}/graphql`;
|
||||
request.post(url, {
|
||||
body: JSON.stringify({
|
||||
operationName: null,
|
||||
variables: {},
|
||||
@@ -170,7 +173,7 @@ export const connectToMothership = async (wsServer, currentRetryAttempt: number
|
||||
}
|
||||
|
||||
// Clear all listeners before running this again
|
||||
mothership.removeAllListeners();
|
||||
mothership?.removeAllListeners();
|
||||
|
||||
// Reconnect
|
||||
setTimeout(async () => {
|
||||
@@ -224,7 +227,7 @@ export const connectToMothership = async (wsServer, currentRetryAttempt: number
|
||||
* Disconnect from mothership.
|
||||
*/
|
||||
export const disconnectFromMothership = async () => {
|
||||
if (mothership) {
|
||||
if (mothership && mothership.readyState !== 0) {
|
||||
log.debug('Disconnecting from the proxy server.');
|
||||
try {
|
||||
mothership.close();
|
||||
|
||||
+19
-12
@@ -150,19 +150,26 @@ export const server = {
|
||||
const key = dotProp.get(loadState(filePath), 'remote.apikey');
|
||||
return (key === undefined || String(key).trim() === '') ? undefined : key;
|
||||
};
|
||||
const startWatcher = () => {
|
||||
watcher.on('raw', async () => {
|
||||
const key = getApiKey();
|
||||
const reconnect = async () => {
|
||||
const key = getApiKey();
|
||||
|
||||
// Try and stop the last connection if it's still open
|
||||
await disconnectFromMothership();
|
||||
|
||||
log.debug('my_servers API key was updated, restarting proxy connection.');
|
||||
process.nextTick(() => {
|
||||
if (key !== undefined) {
|
||||
connectToMothership(wsServer);
|
||||
}
|
||||
});
|
||||
// Try and stop the last connection if it's still open
|
||||
await disconnectFromMothership();
|
||||
|
||||
log.debug('my_servers API key was updated, restarting proxy connection.');
|
||||
process.nextTick(() => {
|
||||
if (key !== undefined) {
|
||||
connectToMothership(wsServer);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let timeout: NodeJS.Timeout;
|
||||
// If we detect an event wait 0.5s before doing anything
|
||||
const startWatcher = () => {
|
||||
watcher.on('all', () => {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(reconnect, 500);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Generated
+26
-25
@@ -1184,7 +1184,7 @@
|
||||
}
|
||||
},
|
||||
"@unraid/core": {
|
||||
"version": "github:unraid/core#b0d36f199b88e6eed1150985cf4b620394febf49",
|
||||
"version": "github:unraid/core#ef6dcac418b6313ac10cd1c042e82a541f88bace",
|
||||
"from": "github:unraid/core",
|
||||
"requires": {
|
||||
"accesscontrol": "^2.2.1",
|
||||
@@ -3825,6 +3825,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
@@ -3836,6 +3837,7 @@
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
@@ -6321,9 +6323,9 @@
|
||||
}
|
||||
},
|
||||
"docker-modem": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-2.1.3.tgz",
|
||||
"integrity": "sha512-cwaRptBmYZwu/FyhGcqBm2MzXA77W2/E6eVkpOZVDk6PkI9Bjj84xPrXiHMA+OWjzNy+DFjgKh8Q+1hMR7/OHg==",
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-2.1.4.tgz",
|
||||
"integrity": "sha512-vDTzZjjO1sXMY7m0xKjGdFMMZL7vIUerkC3G4l6rnrpOET2M6AOufM8ajmQoOB+6RfSn6I/dlikCUq/Y91Q1sQ==",
|
||||
"requires": {
|
||||
"debug": "^4.1.1",
|
||||
"readable-stream": "^3.5.0",
|
||||
@@ -6352,11 +6354,10 @@
|
||||
}
|
||||
},
|
||||
"dockerode": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dockerode/-/dockerode-3.2.0.tgz",
|
||||
"integrity": "sha512-C+y/W4Kks7YLBsfUOTMkk1IVilb4cdj+rE+UZ5hnE+rpcn2frSs7kX+6H8GteTqHcv8sln+GyxuP1qdno3IzIw==",
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dockerode/-/dockerode-3.2.1.tgz",
|
||||
"integrity": "sha512-XsSVB5Wu5HWMg1aelV5hFSqFJaKS5x1aiV/+sT7YOzOq1IRl49I/UwV8Pe4x6t0iF9kiGkWu5jwfvbkcFVupBw==",
|
||||
"requires": {
|
||||
"concat-stream": "~2.0.0",
|
||||
"docker-modem": "^2.1.0",
|
||||
"tar-fs": "~2.0.1"
|
||||
},
|
||||
@@ -8869,9 +8870,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "9.6.56",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.56.tgz",
|
||||
"integrity": "sha512-Cq4pUCsBL6H7X0HFAOap75lmQqcnSmUDSP0R03lz9UsxRvBu5QsnKLLgIoitlFBX+j6LmciWYQAbOSmGMi7vwA=="
|
||||
"version": "9.6.57",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.57.tgz",
|
||||
"integrity": "sha512-588MBlPWKeJFshLmnYbqMEaM3NaJFCVZFgpQ5rQxKCVXMNw2Gs7sTORvCDlaPBP6AabiIvmd22eT9fcIvTeZUw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -9449,11 +9450,11 @@
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
|
||||
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
|
||||
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
|
||||
"requires": {
|
||||
"ajv": "^6.5.5",
|
||||
"ajv": "^6.12.3",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
@@ -10385,9 +10386,9 @@
|
||||
}
|
||||
},
|
||||
"is-observable": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-observable/-/is-observable-2.0.0.tgz",
|
||||
"integrity": "sha512-fhBZv3eFKUbyHXZ1oHujdo2tZ+CNbdpdzzlENgCGZUC8keoGxUew2jYFLYcUB4qo7LDD03o4KK11m/QYD7kEjg=="
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-observable/-/is-observable-2.1.0.tgz",
|
||||
"integrity": "sha512-DailKdLb0WU+xX8K5w7VsJhapwHLZ9jjmazqCJq4X12CTgqq73TKnbRcnSLuXYPOoLQgV5IrD7ePiX/h1vnkBw=="
|
||||
},
|
||||
"is-path-cwd": {
|
||||
"version": "2.2.0",
|
||||
@@ -14667,7 +14668,7 @@
|
||||
}
|
||||
},
|
||||
"redact-secrets": {
|
||||
"version": "github:OmgImAlexis/redact-secrets#793a0bc696e1be69af6d65e6884177db9659976f",
|
||||
"version": "github:OmgImAlexis/redact-secrets#126cb8140fffe9b82e8864d191e24eedd0364a00",
|
||||
"from": "github:OmgImAlexis/redact-secrets",
|
||||
"requires": {
|
||||
"is-secret": "^1.0.0",
|
||||
@@ -15735,9 +15736,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "9.6.56",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.56.tgz",
|
||||
"integrity": "sha512-Cq4pUCsBL6H7X0HFAOap75lmQqcnSmUDSP0R03lz9UsxRvBu5QsnKLLgIoitlFBX+j6LmciWYQAbOSmGMi7vwA=="
|
||||
"version": "9.6.57",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.57.tgz",
|
||||
"integrity": "sha512-588MBlPWKeJFshLmnYbqMEaM3NaJFCVZFgpQ5rQxKCVXMNw2Gs7sTORvCDlaPBP6AabiIvmd22eT9fcIvTeZUw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -16578,9 +16579,9 @@
|
||||
}
|
||||
},
|
||||
"tracer": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/tracer/-/tracer-1.1.2.tgz",
|
||||
"integrity": "sha512-SlXPQJEozEvtPLwOX+viPh36WL9SaH3a2q459aRH41nqqR2QGgPZ9em/ZaCeKLeEQMxzYUsAmATmFID/INIL3g==",
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tracer/-/tracer-1.1.3.tgz",
|
||||
"integrity": "sha512-/h/dbzKRLtaAx07wwEGLg7dPzDKWQX6wcHnQEqlBTO7e/fLHhRcwxEcJd0+VITmn6pCK4CjDjXahCu0+TkKaDA==",
|
||||
"requires": {
|
||||
"colors": "1.4.0",
|
||||
"dateformat": "3.0.3",
|
||||
|
||||
Reference in New Issue
Block a user