rfactor federation clients

This commit is contained in:
Ulf Gebhardt 2023-05-03 13:02:32 +02:00
parent cb3b800d5c
commit 870c97ce71
Signed by: ulfgebhardt
GPG Key ID: DA6B843E748679C9
7 changed files with 118 additions and 143 deletions

View File

@ -1,42 +0,0 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { Community as DbCommunity } from '@entity/Community'
import { gql } from 'graphql-request'
import { GraphQLGetClient } from '@/federation/client/GraphQLGetClient'
import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger'
export async function requestGetPublicKey(dbCom: DbCommunity): Promise<string | undefined> {
let endpoint = dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/'
endpoint = `${endpoint}${dbCom.apiVersion}/`
logger.info(`requestGetPublicKey with endpoint='${endpoint}'...`)
const graphQLClient = GraphQLGetClient.getInstance(endpoint)
logger.debug(`graphQLClient=${JSON.stringify(graphQLClient)}`)
const query = gql`
query {
getPublicKey {
publicKey
}
}
`
const variables = {}
try {
const { data, errors, extensions, headers, status } = await graphQLClient.rawRequest(
query,
variables,
)
logger.debug(`Response-Data:`, data, errors, extensions, headers, status)
if (data) {
logger.debug(`Response-PublicKey:`, data.getPublicKey.publicKey)
logger.info(`requestGetPublicKey processed successfully`)
return data.getPublicKey.publicKey
}
logger.warn(`requestGetPublicKey processed without response data`)
} catch (err) {
throw new LogError(`Request-Error:`, err)
}
}

View File

@ -1,42 +0,0 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { Community as DbCommunity } from '@entity/Community'
import { gql } from 'graphql-request'
import { GraphQLGetClient } from '@/federation/client/GraphQLGetClient'
import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger'
export async function requestGetPublicKey(dbCom: DbCommunity): Promise<string | undefined> {
let endpoint = dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/'
endpoint = `${endpoint}${dbCom.apiVersion}/`
logger.info(`requestGetPublicKey with endpoint='${endpoint}'...`)
const graphQLClient = GraphQLGetClient.getInstance(endpoint)
logger.debug(`graphQLClient=${JSON.stringify(graphQLClient)}`)
const query = gql`
query {
getPublicKey {
publicKey
}
}
`
const variables = {}
try {
const { data, errors, extensions, headers, status } = await graphQLClient.rawRequest(
query,
variables,
)
logger.debug(`Response-Data:`, data, errors, extensions, headers, status)
if (data) {
logger.debug(`Response-PublicKey:`, data.getPublicKey.publicKey)
logger.info(`requestGetPublicKey processed successfully`)
return data.getPublicKey.publicKey
}
logger.warn(`requestGetPublicKey processed without response data`)
} catch (err) {
throw new LogError(`Request-Error:`, err)
}
}

View File

@ -0,0 +1,57 @@
import { Community as DbCommunity } from '@entity/Community'
import { ApiVersionType } from '@/federation/enum/apiVersionType'
// eslint-disable-next-line camelcase
import { Client_1_0 } from './Client_1_0'
// eslint-disable-next-line camelcase
import { Client_1_1 } from './Client_1_1'
// eslint-disable-next-line camelcase
type FederationClient = Client_1_0 | Client_1_1
type ClientInstance = {
dbCom: DbCommunity
// eslint-disable-next-line no-use-before-define
client: FederationClient
}
export class Client {
private static instanceArray: ClientInstance[] = []
/**
* The Singleton's constructor should always be private to prevent direct
* construction calls with the `new` operator.
*/
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
private constructor() {}
private static createFederationClient = (dbCom: DbCommunity) => {
switch (dbCom.apiVersion) {
case ApiVersionType.V1_0:
return new Client_1_0(dbCom)
case ApiVersionType.V1_1:
return new Client_1_1(dbCom)
default:
return null
}
}
/**
* The static method that controls the access to the singleton instance.
*
* This implementation let you subclass the Singleton class while keeping
* just one instance of each subclass around.
*/
public static getInstance(dbCom: DbCommunity): FederationClient | null {
const instance = Client.instanceArray.find((instance) => instance.dbCom === dbCom)
if (instance) {
return instance.client
}
const client = Client.createFederationClient(dbCom)
if (client) {
Client.instanceArray.push({ dbCom, client } as ClientInstance)
}
return client
}
}

View File

@ -0,0 +1,54 @@
import { Community as DbCommunity } from '@entity/Community'
import { GraphQLClient, gql } from 'graphql-request'
import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger'
// eslint-disable-next-line camelcase
export class Client_1_0 {
dbCom: DbCommunity
endpoint: string
client: GraphQLClient
constructor(dbCom: DbCommunity) {
this.dbCom = dbCom
this.endpoint = `${dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/'}${
dbCom.apiVersion
}/`
this.client = new GraphQLClient(this.endpoint, {
method: 'GET',
jsonSerializer: {
parse: JSON.parse,
stringify: JSON.stringify,
},
})
}
requestGetPublicKey = async (): Promise<string | undefined> => {
logger.info(`requestGetPublicKey with endpoint='${this.endpoint}'...`)
const query = gql`
query {
getPublicKey {
publicKey
}
}
`
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const { data, errors, headers, status } = await this.client.rawRequest(query)
logger.debug(`Response-Data:`, data, errors, headers, status)
if (data) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
logger.debug(`Response-PublicKey:`, data.getPublicKey.publicKey)
logger.info(`requestGetPublicKey processed successfully`)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
return data.getPublicKey.publicKey
}
logger.warn(`requestGetPublicKey processed without response data`)
} catch (err) {
throw new LogError(`Request-Error:`, err)
}
}
}

View File

@ -0,0 +1,5 @@
// eslint-disable-next-line camelcase
import { Client_1_0 } from './Client_1_0'
// eslint-disable-next-line camelcase
export class Client_1_1 extends Client_1_0 {}

View File

@ -1,43 +0,0 @@
import { GraphQLClient } from 'graphql-request'
import { PatchedRequestInit } from 'graphql-request/dist/types'
type ClientInstance = {
url: string
// eslint-disable-next-line no-use-before-define
client: GraphQLGetClient
}
export class GraphQLGetClient extends GraphQLClient {
private static instanceArray: ClientInstance[] = []
/**
* The Singleton's constructor should always be private to prevent direct
* construction calls with the `new` operator.
*/
// eslint-disable-next-line no-useless-constructor
private constructor(url: string, options?: PatchedRequestInit) {
super(url, options)
}
/**
* The static method that controls the access to the singleton instance.
*
* This implementation let you subclass the Singleton class while keeping
* just one instance of each subclass around.
*/
public static getInstance(url: string): GraphQLGetClient {
const instance = GraphQLGetClient.instanceArray.find((instance) => instance.url === url)
if (instance) {
return instance.client
}
const client = new GraphQLGetClient(url, {
method: 'GET',
jsonSerializer: {
parse: JSON.parse,
stringify: JSON.stringify,
},
})
GraphQLGetClient.instanceArray.push({ url, client } as ClientInstance)
return client
}
}

View File

@ -4,10 +4,7 @@ import { Community as DbCommunity } from '@entity/Community'
import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger'
// eslint-disable-next-line camelcase
import { requestGetPublicKey as v1_0_requestGetPublicKey } from './client/1_0/FederationClient'
// eslint-disable-next-line camelcase
import { requestGetPublicKey as v1_1_requestGetPublicKey } from './client/1_1/FederationClient'
import { Client } from './client/Client'
import { ApiVersionType } from './enum/apiVersionType'
export function startValidateCommunities(timerInterval: number): void {
@ -38,7 +35,7 @@ export async function validateCommunities(): Promise<void> {
`Federation: validate publicKey for dbCom: ${dbCom.id} with apiVersion=${dbCom.apiVersion}`,
)
try {
const pubKey = await invokeVersionedRequestGetPublicKey(dbCom)
const pubKey = await Client.getInstance(dbCom)?.requestGetPublicKey()
logger.info(
'Federation: received publicKey from endpoint',
pubKey,
@ -73,14 +70,3 @@ export async function validateCommunities(): Promise<void> {
function isLogError(err: unknown) {
return err instanceof LogError
}
async function invokeVersionedRequestGetPublicKey(dbCom: DbCommunity): Promise<string | undefined> {
switch (dbCom.apiVersion) {
case ApiVersionType.V1_0:
return v1_0_requestGetPublicKey(dbCom)
case ApiVersionType.V1_1:
return v1_1_requestGetPublicKey(dbCom)
default:
return undefined
}
}