fix: ensure we have local data for server endpoint fallback

This commit is contained in:
Alexis Tyler
2020-06-18 15:42:03 +09:30
parent 44db2dd6e7
commit 0fd14b701b
4 changed files with 94 additions and 24 deletions
+20 -16
View File
@@ -6,20 +6,24 @@ type URL = string;
type IpAddress = string;
type Status = 'online' | 'offline';
export interface CachedUser {
profile: {
username: string;
url: URL;
avatar: URL;
},
servers: [{
guid: string;
apikey: string;
name: string;
status: Status;
wanip: IpAddress;
lanip: IpAddress;
localurl: URL;
remoteurl: string
}]
export interface Owner {
username: string;
url: URL;
avatar: URL;
};
export interface CachedServer {
owner: Owner;
guid: string;
apikey: string;
name: string;
status: Status;
wanip: IpAddress;
lanip: IpAddress;
localurl: URL;
remoteurl: string
};
export interface CachedServers {
servers: [CachedServer]
};
+49 -5
View File
@@ -3,18 +3,19 @@
* Written by: Alexis Tyler
*/
import { pluginManager, pubsub, utils, bus, errors, states, modules } from '@unraid/core';
import { pluginManager, pubsub, utils, bus, errors, states, modules, apiManager } from '@unraid/core';
import dee from '@gridplus/docker-events';
import { setIntervalAsync } from 'set-interval-async/dynamic';
import GraphQLJSON from 'graphql-type-json';
import GraphQLLong from 'graphql-type-long';
import GraphQLUUID from 'graphql-type-uuid';
import { run, publish } from '../../run';
import { userCache, CachedUser } from '../../cache';
import { userCache, CachedServer, CachedServers } from '../../cache';
import { hasSubscribedToChannel, canPublishToChannel } from '../../ws';
import { networkState } from '@unraid/core/dist/lib/states';
const { ensurePermission } = utils;
const { usersState } = states;
const { usersState, varState } = states;
const { AppError, PluginError } = errors;
// Update array values when slots change
@@ -88,6 +89,49 @@ const createSubscription = (channel, resource?) => ({
}
});
// Add null to types
type makeNullUndefinedAndOptional<T> = {
[K in keyof T]?: T[K] | null | undefined;
};
type Server = makeNullUndefinedAndOptional<CachedServer>;
const getServers = (): Server[] => {
const servers = userCache.get<CachedServers>('mine')?.servers ?? [];
// Fall back to locally generated data
if (servers.length === 0) {
const guid = varState?.data?.regGuid;
// @todo: Verify this is correct
const apikey = apiManager.getValidKeys().find(key => {
console.log('----------');
console.log(`Sending ${key.name}`);
console.table(key);
console.log('----------');
})?.key.toString();
const name = varState?.data?.name;
const wanip = null;
const lanip = networkState.data['eth0']['ipaddr:0'];
const localurl = null;
const remoteurl = null;
return [{
owner: null,
guid,
apikey,
name,
status: 'online',
wanip,
lanip,
localurl,
remoteurl
}];
}
// Return servers from upstream cache
return servers;
};
export const resolvers = {
Query: {
info: () => ({}),
@@ -100,7 +144,7 @@ export const resolvers = {
});
// Single server
return userCache.get<CachedUser>('mine')?.servers.find(server => server.name === name);
return getServers().find(server => server.name === name);
},
servers(_, __, context) {
ensurePermission(context.user, {
@@ -110,7 +154,7 @@ export const resolvers = {
});
// All servers
return userCache.get<CachedUser>('mine')?.servers;
return getServers();
}
},
Subscription: {
@@ -22,7 +22,14 @@ enum Status {
offline
}
type Owner {
username: String;
url: String;
avatar: String;
}
type Server {
owner: Owner[]
guid: String
apikey: String
name: String
+18 -3
View File
@@ -17,7 +17,7 @@ import { ApolloServer } from 'apollo-server-express';
import { log, config, utils, paths, states } from '@unraid/core';
import { DynamixConfig } from '@unraid/core/dist/lib/types';
import { graphql } from './graphql';
import { userCache, CachedUser } from './cache';
import { userCache, CachedServer, Owner } from './cache';
const { getEndpoints, globalErrorHandler, exitApp, loadState } = utils;
const { varState } = states;
@@ -309,7 +309,13 @@ const connectToMothership = async (currentRetryAttempt: number = 0) => {
});
}
const isUserObject = (data): data is CachedUser => {
interface Server extends Omit<CachedServer, 'owner'>{};
interface User {
profile: Owner;
servers: Server[]
}
const isUserObject = (data): data is User => {
const keys = Object.keys(data);
return keys.includes('profile') && keys.includes('servers') && keys.length === 2;
};
@@ -319,7 +325,16 @@ const connectToMothership = async (currentRetryAttempt: number = 0) => {
// Cache the response
if (isUserObject(data)) {
userCache.set('mine', data);
const owner = data.profile;
const mine = {
servers: data.servers.map(server => {
return {
...server,
owner
};
})
};
userCache.set('mine', mine);
return;
}