import { Schema } from '@cardano-ogmios/client'
-
import { exec } from 'child_process'
import util, { DataFetcher, ModuleState } from '@cardano-graphql/util'
import fetch from 'cross-fetch'
import { DocumentNode, GraphQLSchema, print } from 'graphql'
import { GraphQLClient, gql } from 'graphql-request'
import { introspectSchema, wrapSchema } from '@graphql-tools/wrap'
import pRetry from 'p-retry'
export class HasuraClient {
private client: GraphQLClient
-
private applyingSchemaAndMetadata: boolean
public adaPotsToCalculateSupplyFetcher: DataFetcher<AdaPotsToCalculateSupply>
private state: ModuleState
public schema: GraphQLSchema
-
readonly hasuraCliPath: string,
readonly hasuraUri: string,
private logger: Logger = dummyLogger
-
this.applyingSchemaAndMetadata = false
this.adaPotsToCalculateSupplyFetcher = new DataFetcher<AdaPotsToCalculateSupply>(
'AdaPotsToCalculateSupply',
-
private async hasuraCli (command: string) {
-
return new Promise((resolve, reject) => {
-
`${this.hasuraCliPath} --skip-update-check --project ${path.resolve(__dirname, '..', 'hasura', 'project')} --endpoint ${this.hasuraUri} ${command}`,
-
this.logger.debug({ module: 'HasuraClient' }, stdout)
public async initialize () {
if (this.state !== null) return
this.state = 'initializing'
this.logger.info({ module: 'HasuraClient' }, 'Initializing')
-
await this.applySchemaAndMetadata()
await pRetry(async () => {
this.schema = await this.buildHasuraSchema()
this.logger.debug({ module: 'HasuraClient' }, 'graphql-engine setup')
-
await pRetry(async () => {
-
const result = await this.client.request(
-
epochs (limit: 1, order_by: { number: desc }) {
-
if (result.epochs.length === 0) {
-
this.logger.debug({ module: 'HasuraClient' }, epochInformationNotYetAvailable)
-
throw new Error(epochInformationNotYetAvailable)
-
onFailedAttempt: util.onFailedAttemptFor(
-
'Detecting DB sync state has reached minimum progress',
-
this.logger.debug({ module: 'HasuraClient' }, 'DB sync state has reached minimum progress')
await this.adaPotsToCalculateSupplyFetcher.initialize()
this.state = 'initialized'
this.logger.info({ module: 'HasuraClient' }, 'Initialized')
await this.adaPotsToCalculateSupplyFetcher.shutdown()
-
public async applySchemaAndMetadata (): Promise<void> {
-
if (this.applyingSchemaAndMetadata) return
-
this.applyingSchemaAndMetadata = true
-
await pRetry(async () => {
-
await this.hasuraCli('migrate apply --down all')
-
await this.hasuraCli('migrate apply --up all')
-
onFailedAttempt: util.onFailedAttemptFor(
-
'Applying PostgreSQL schema migrations',
-
await pRetry(async () => {
-
await this.hasuraCli('metadata clear')
-
await this.hasuraCli('metadata apply')
-
onFailedAttempt: util.onFailedAttemptFor('Applying Hasura metadata', this.logger)
-
this.applyingSchemaAndMetadata = false
public async buildHasuraSchema () {
const executor = async ({ document, variables }: { document: DocumentNode, variables?: Object }) => {
const query = print(document)