Skip to content
This repository has been archived by the owner on Feb 20, 2024. It is now read-only.

Commit

Permalink
Fix substrate healthcheck (#43)
Browse files Browse the repository at this point in the history
* Fix substrate healthcheck

The substrate promise `isReadyOrError` when resolved is never re-evaluated. Therefore the previous implmentation didn't work. This change instead uses the `isConnected` property which is maintained and updated by the library

* Wait for first connection or error

* Remove only on test

* Add tests for healthcheck service down

* Update readme and helm chart with new envs

* Move responses to fixture

* Fix quotes
  • Loading branch information
mattdean-digicatapult authored Apr 13, 2022
1 parent bd808a3 commit 55d0862
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 91 deletions.
40 changes: 21 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,27 @@ npm run test:integration

The following environment variables are used by `dscp-api` and can be configured. Entries marked as `required` are needed when running `dscp-api` in production mode.

| variable | required | default | description |
| :---------------------------- | :------: | :-------------------------------------------------: | :------------------------------------------------------------------------------------------- |
| PORT | N | `3001` | The port for the API to listen on |
| API_HOST | Y | - | The hostname of the `dscp-node` the API should connect to |
| API_PORT | N | `9944` | The port of the `dscp-node` the API should connect to |
| LOG_LEVEL | N | `info` | Logging level. Valid values are [`trace`, `debug`, `info`, `warn`, `error`, `fatal`] |
| USER_URI | Y | - | The Substrate `URI` representing the private key to use when making `dscp-node` transactions |
| IPFS_HOST | Y | - | Hostname of the `IPFS` node to use for metadata storage |
| IPFS_PORT | N | `15001` | Port of the `IPFS` node to use for metadata storage |
| AUTH_JWKS_URI | N | `https://inteli.eu.auth0.com/.well-known/jwks.json` | JSON Web Key Set containing public keys used by the Auth0 API |
| AUTH_AUDIENCE | N | `inteli-dev` | Identifier of the Auth0 API |
| AUTH_ISSUER | N | `https://inteli.eu.auth0.com/` | Domain of the Auth0 API ` |
| AUTH_TOKEN_URL | N | `https://inteli.eu.auth0.com/oauth/token` | Auth0 API endpoint that issues an Authorisation (Bearer) access token |
| METADATA_KEY_LENGTH | N | `32` | Fixed length of metadata keys |
| METADATA_VALUE_LITERAL_LENGTH | N | `32` | Fixed length of metadata LITERAL values |
| MAX_METADATA_COUNT | N | `16` | Maximum number of metadata items allowed per token |
| API_VERSION | N | `package.json version` | API version |
| API_MAJOR_VERSION | N | `v3` | API major version |
| FILE_UPLOAD_MAX_SIZE | N | `200 * 1024 * 1024` | The Maximum file upload size (bytes) |
| variable | required | default | description |
| :------------------------------ | :------: | :-------------------------------------------------: | :------------------------------------------------------------------------------------------- |
| PORT | N | `3001` | The port for the API to listen on |
| API_HOST | Y | - | The hostname of the `dscp-node` the API should connect to |
| API_PORT | N | `9944` | The port of the `dscp-node` the API should connect to |
| LOG_LEVEL | N | `info` | Logging level. Valid values are [`trace`, `debug`, `info`, `warn`, `error`, `fatal`] |
| USER_URI | Y | - | The Substrate `URI` representing the private key to use when making `dscp-node` transactions |
| IPFS_HOST | Y | - | Hostname of the `IPFS` node to use for metadata storage |
| IPFS_PORT | N | `15001` | Port of the `IPFS` node to use for metadata storage |
| AUTH_JWKS_URI | N | `https://inteli.eu.auth0.com/.well-known/jwks.json` | JSON Web Key Set containing public keys used by the Auth0 API |
| AUTH_AUDIENCE | N | `inteli-dev` | Identifier of the Auth0 API |
| AUTH_ISSUER | N | `https://inteli.eu.auth0.com/` | Domain of the Auth0 API ` |
| AUTH_TOKEN_URL | N | `https://inteli.eu.auth0.com/oauth/token` | Auth0 API endpoint that issues an Authorisation (Bearer) access token |
| METADATA_KEY_LENGTH | N | `32` | Fixed length of metadata keys |
| METADATA_VALUE_LITERAL_LENGTH | N | `32` | Fixed length of metadata LITERAL values |
| MAX_METADATA_COUNT | N | `16` | Maximum number of metadata items allowed per token |
| API_VERSION | N | `package.json version` | API version |
| API_MAJOR_VERSION | N | `v3` | API major version |
| FILE_UPLOAD_MAX_SIZE | N | `200 * 1024 * 1024` | The Maximum file upload size (bytes) |
| SUBSTRATE_STATUS_POLL_PERIOD_MS | N | `10 * 1000` | Number of ms between calls to check dscp-node status |
| SUBSTRATE_STATUS_TIMEOUT_MS | N | `2 * 1000` | Number of ms to wait for response to dscp-node health requests |

## Running the API

Expand Down
2 changes: 1 addition & 1 deletion app/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const vars = envalid.cleanEnv(process.env, {
API_VERSION: envalid.str({ default: version }),
API_MAJOR_VERSION: envalid.str({ default: 'v3' }),
FILE_UPLOAD_MAX_SIZE: envalid.num({ default: 200 * 1024 * 1024 }),
SUBSTRATE_STATUS_POLL_PERIOD_MS: envalid.num({ default: 30 * 1000 }),
SUBSTRATE_STATUS_POLL_PERIOD_MS: envalid.num({ default: 10 * 1000 }),
SUBSTRATE_STATUS_TIMEOUT_MS: envalid.num({ default: 2 * 1000 }),
})

Expand Down
45 changes: 20 additions & 25 deletions app/serviceStatus/apiStatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,30 @@ const { substrateApi } = require('../util/substrateApi')
const { SUBSTRATE_STATUS_POLL_PERIOD_MS, SUBSTRATE_STATUS_TIMEOUT_MS } = require('../env')

const getStatus = async () => {
try {
await substrateApi.isReadyOrError
const [chain, runtime] = await Promise.all([substrateApi.runtimeChain, substrateApi.runtimeVersion])
await substrateApi.isReadyOrError.catch(() => {})
if (!substrateApi.isConnected) {
return {
status: serviceState.UP,
status: serviceState.DOWN,
detail: {
chain,
runtime: {
name: runtime.specName,
versions: {
spec: runtime.specVersion.toNumber(),
impl: runtime.implVersion.toNumber(),
authoring: runtime.authoringVersion.toNumber(),
transaction: runtime.transactionVersion.toNumber(),
},
},
message: 'Cannot connect to substrate node',
},
}
} catch (err) {
return {
status: serviceState.DOWN,
detail: !substrateApi.isConnected
? {
message: 'Cannot connect to substrate node',
}
: {
message: 'Unknown error getting status from substrate node',
},
}
}
const [chain, runtime] = await Promise.all([substrateApi.runtimeChain, substrateApi.runtimeVersion])
return {
status: serviceState.UP,
detail: {
chain,
runtime: {
name: runtime.specName,
versions: {
spec: runtime.specVersion.toNumber(),
impl: runtime.implVersion.toNumber(),
authoring: runtime.authoringVersion.toNumber(),
transaction: runtime.transactionVersion.toNumber(),
},
},
},
}
}

Expand Down
4 changes: 2 additions & 2 deletions helm/dscp-api/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
apiVersion: v2
name: dscp-api
appVersion: '4.0.3'
appVersion: '4.0.4'
description: A Helm chart for dscp-api
version: '4.0.3'
version: '4.0.4'
type: application
dependencies:
- name: dscp-node
Expand Down
2 changes: 2 additions & 0 deletions helm/dscp-api/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ data:
authAudience: {{ .Values.config.auth.audience }}
authIssuer: {{ .Values.config.auth.issuer }}
authTokenUrl: {{ .Values.config.auth.tokenUrl }}
substrateStatusPollPeriodMs: {{ .Values.config.substrateStatusPollPeriodMs | quote }}
substrateStatusTimeoutMs: {{ .Values.config.substrateStatusTimeoutMs | quote }}
12 changes: 11 additions & 1 deletion helm/dscp-api/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ spec:
configMapKeyRef:
name: {{ include "dscp-api.fullname" . }}-config
key: authTokenUrl
- name: SUBSTRATE_STATUS_POLL_PERIOD_MS
valueFrom:
configMapKeyRef:
name: {{ include "dscp-api.fullname" . }}-config
key: substrateStatusPollPeriodMs
- name: SUBSTRATE_STATUS_TIMEOUT_MS
valueFrom:
configMapKeyRef:
name: {{ include "dscp-api.fullname" . }}-config
key: substrateStatusTimeoutMs
- name: USER_URI
valueFrom:
secretKeyRef:
Expand All @@ -88,4 +98,4 @@ spec:
failureThreshold: 5
timeoutSeconds: 3
periodSeconds: 10
{{- end }}
{{- end }}
4 changes: 3 additions & 1 deletion helm/dscp-api/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ config:
# externalIpfsHost: "" # This overrides dscpIpfs.enabled when setting the IPFS_HOST envar
# externalIpfsPort: 5001 # This overrides dscpIpfs.enabled when setting the IPFS_PORT envar
enableLivenessProbe: true
substrateStatusPollPeriodMs: 10000
substrateStatusTimeoutMs: 2000
auth:
jwksUri: https://inteli.eu.auth0.com/.well-known/jwks.json
audience: inteli-dev
Expand All @@ -24,7 +26,7 @@ replicaCount: 1
image:
repository: ghcr.io/digicatapult/dscp-api
pullPolicy: IfNotPresent
tag: 'v4.0.3'
tag: 'v4.0.4'

dscpNode:
enabled: false
Expand Down
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dscp-api",
"version": "4.0.3",
"version": "4.0.4",
"description": "DSCP API",
"repository": {
"type": "git",
Expand Down
47 changes: 47 additions & 0 deletions test/helper/healthcheckFixtures.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
const { API_VERSION } = require('../../app/env')

const responses = {
ok: {
code: 200,
body: {
status: 'ok',
version: API_VERSION,
details: {
api: {
status: 'ok',
detail: {
chain: 'Development',
runtime: {
name: 'dscp',
versions: {
authoring: 1,
impl: 1,
spec: 300,
transaction: 1,
},
},
},
},
},
},
},
down: {
code: 503,
body: {
status: 'down',
version: API_VERSION,
details: {
api: {
status: 'down',
detail: {
message: 'Cannot connect to substrate node',
},
},
},
},
},
}

module.exports = {
responses,
}
Loading

0 comments on commit 55d0862

Please sign in to comment.