Skip to content

Commit

Permalink
Api fetching status indicator on tty (#768)
Browse files Browse the repository at this point in the history
  • Loading branch information
ermalkaleci committed Jun 3, 2024
1 parent 935bd77 commit ebd1dad
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 9 deletions.
4 changes: 4 additions & 0 deletions packages/chopsticks/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { BlockEntry, GenesisProvider, defaultLogger, isUrl, setup, timeTravel }
import { Config } from './schema/index.js'
import { HexString } from '@polkadot/util/types'
import { SqliteDatabase } from '@acala-network/chopsticks-db'
import { apiFetching } from './logger.js'
import { overrideStorage, overrideWasm } from './utils/override.js'
import { startFetchStorageWorker } from './utils/fetch-storages.js'
import axios from 'axios'
Expand Down Expand Up @@ -48,6 +49,9 @@ export const setupContext = async (argv: Config, overrideParent = false) => {
offchainWorker: argv['offchain-worker'],
maxMemoryBlockCount: argv['max-memory-block-count'],
processQueuedMessages: argv['process-queued-messages'],
hooks: {
apiFetching,
},
})

// load block from db
Expand Down
25 changes: 25 additions & 0 deletions packages/chopsticks/src/logger.ts
Original file line number Diff line number Diff line change
@@ -1 +1,26 @@
import _ from 'lodash'

export { defaultLogger, truncate } from '@acala-network/chopsticks-core'

const showProgress = process.stdout.isTTY && !process.env['CI'] && !process.env['TEST']

export const spinnerFrames =
process.platform === 'win32' ? ['-', '\\', '|', '/'] : ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
let index = 0

// clear to the right from cursor
const clearStatus = _.debounce(() => process.stdout.clearLine(1), 500, { trailing: true })

export const apiFetching = _.throttle(
() => {
if (!showProgress) return

// print ` ⠋ Fetching|` and move cursor at position 0 of the line `| ⠋ Fetching`
process.stdout.write(` ${spinnerFrames[index++]} Fetching`)
process.stdout.cursorTo(0)
index = ++index % spinnerFrames.length
clearStatus()
},
50,
{ leading: true },
)
32 changes: 23 additions & 9 deletions packages/core/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export class Api {

readonly signedExtensions: ExtDef

#apiHooks: {
fetching?: () => void
} = {}

constructor(provider: ProviderInterface, signedExtensions?: ExtDef) {
this.#provider = provider
this.signedExtensions = signedExtensions || {}
Expand Down Expand Up @@ -68,32 +72,42 @@ export class Api {
return this.#chainProperties
}

// Set the hook function to be called when api fetch endpoint.
onFetching(fetching?: () => void) {
this.#apiHooks.fetching = fetching
}

async send<T = any>(method: string, params: unknown[], isCacheable?: boolean): Promise<T> {
this.#apiHooks?.fetching?.()
return this.#provider.send(method, params, isCacheable)

Check failure on line 82 in packages/core/src/api.ts

View workflow job for this annotation

GitHub Actions / tests

packages/e2e/src/build-block.test.ts > Latest 'Acala' can build blocks > build blocks

Error: WebSocket is not connected ❯ node_modules/@polkadot/rpc-provider/ws/index.js:271:27 ❯ WsProvider.__internal__send node_modules/@polkadot/rpc-provider/ws/index.js:268:16 ❯ WsProvider.send node_modules/@polkadot/rpc-provider/ws/index.js:256:34 ❯ Api.send packages/core/src/api.ts:82:27 ❯ Api.getBlockHash packages/core/src/api.ts:98:17 ❯ setup packages/e2e/src/helper.ts:71:31 ❯ it.timeout packages/e2e/src/build-block.test.ts:44:45

Check failure on line 82 in packages/core/src/api.ts

View workflow job for this annotation

GitHub Actions / tests

packages/e2e/src/build-block.test.ts > Latest 'Acala' can build blocks > build blocks

Error: WebSocket is not connected ❯ node_modules/@polkadot/rpc-provider/ws/index.js:271:27 ❯ WsProvider.__internal__send node_modules/@polkadot/rpc-provider/ws/index.js:268:16 ❯ WsProvider.send node_modules/@polkadot/rpc-provider/ws/index.js:256:34 ❯ Api.send packages/core/src/api.ts:82:27 ❯ Api.getBlockHash packages/core/src/api.ts:98:17 ❯ setup packages/e2e/src/helper.ts:71:31 ❯ it.timeout packages/e2e/src/build-block.test.ts:44:45
}

async getSystemName() {
return this.#provider.send<string>('system_name', [])
return this.send<string>('system_name', [])
}

async getSystemProperties() {
return this.#provider.send<ChainProperties>('system_properties', [])
return this.send<ChainProperties>('system_properties', [])
}

async getSystemChain() {
return this.#provider.send<string>('system_chain', [])
return this.send<string>('system_chain', [])
}

async getBlockHash(blockNumber?: number) {
return this.#provider.send<HexString | null>(
return this.send<HexString | null>(
'chain_getBlockHash',
Number.isInteger(blockNumber) ? [blockNumber] : [],
!!blockNumber,
)
}

async getHeader(hash?: string) {
return this.#provider.send<Header | null>('chain_getHeader', hash ? [hash] : [], !!hash)
return this.send<Header | null>('chain_getHeader', hash ? [hash] : [], !!hash)
}

async getBlock(hash?: string) {
return this.#provider.send<SignedBlock | null>('chain_getBlock', hash ? [hash] : [], !!hash)
return this.send<SignedBlock | null>('chain_getBlock', hash ? [hash] : [], !!hash)
}

async getStorage(key: string, hash?: string) {
Expand All @@ -102,12 +116,12 @@ export class Api {
// child storage key, use childstate_getStorage
const params = [child, storageKey]
if (hash) params.push(hash as HexString)
return this.#provider.send<HexString | null>('childstate_getStorage', params, !!hash)
return this.send<HexString | null>('childstate_getStorage', params, !!hash)
} else {
// main storage key, use state_getStorage
const params = [key]
if (hash) params.push(hash)
return this.#provider.send<HexString | null>('state_getStorage', params, !!hash)
return this.send<HexString | null>('state_getStorage', params, !!hash)
}
}

Expand All @@ -125,7 +139,7 @@ export class Api {
// main storage key, use state_getKeysPaged
const params = [prefix, pageSize, startKey]
if (hash) params.push(hash)
return this.#provider.send<HexString[]>('state_getKeysPaged', params, !!hash)
return this.send<HexString[]>('state_getKeysPaged', params, !!hash)
}
}

Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export type SetupOptions = {
offchainWorker?: boolean
maxMemoryBlockCount?: number
processQueuedMessages?: boolean
hooks?: {
apiFetching?: () => void
}
}

export const processOptions = async (options: SetupOptions) => {
Expand All @@ -39,6 +42,10 @@ export const processOptions = async (options: SetupOptions) => {
provider = new WsProvider(options.endpoint, 3_000)
}
const api = new Api(provider)

// setup api hooks
api.onFetching(options.hooks?.apiFetching)

await api.isReady

let blockHash: string
Expand Down

0 comments on commit ebd1dad

Please sign in to comment.