import { JSONSchema4 } from 'json-schema' import winston from 'winston' import { MAX_CONCURRENT_RESPONSE_TIME_CHECKS } from '../services/networking/NetworkingService' export const bytesizeUnits = ['B', 'K', 'M', 'G', 'T'] export const bytesizeRegex = new RegExp(`^[0-9]+(${bytesizeUnits.join('|')})$`) export const configSchema: JSONSchema4 = { title: 'Distributor node configuration', description: 'Configuration schema for distirubtor CLI and node', type: 'object', required: ['id', 'endpoints', 'directories', 'buckets', 'keys', 'port', 'workerId', 'limits', 'intervals'], additionalProperties: false, properties: { id: { type: 'string', description: 'Node identifier used when sending elasticsearch logs and exposed on /status endpoint', minLength: 1, }, endpoints: { type: 'object', description: 'Specifies external endpoints that the distributor node will connect to', additionalProperties: false, required: ['queryNode', 'joystreamNodeWs'], properties: { queryNode: { description: 'Query node graphql server uri (for example: http://localhost:8081/graphql)', type: 'string', }, joystreamNodeWs: { description: 'Joystream node websocket api uri (for example: ws://localhost:9944)', type: 'string', }, elasticSearch: { description: 'Elasticsearch uri used for submitting the distributor node logs (if enabled via `log.elastic`)', type: 'string', }, }, }, directories: { type: 'object', required: ['assets', 'cacheState'], additionalProperties: false, description: "Specifies paths where node's data will be stored", properties: { assets: { description: 'Path to a directory where all the cached assets will be stored', type: 'string', }, cacheState: { description: 'Path to a directory where information about the current cache state will be stored (LRU-SP cache data, stored assets mime types etc.)', type: 'string', }, logs: { description: 'Path to a directory where logs will be stored if logging to a file was enabled (via `log.file`).', type: 'string', }, }, }, log: { type: 'object', additionalProperties: false, description: 'Specifies minimum log levels by supported log outputs', properties: { file: { description: 'Minimum level of logs written to a file specified in `directories.logs`', type: 'string', enum: [...Object.keys(winston.config.npm.levels), 'off'], }, console: { description: 'Minimum level of logs outputted to a console', type: 'string', enum: [...Object.keys(winston.config.npm.levels), 'off'], }, elastic: { description: 'Minimum level of logs sent to elasticsearch endpoint specified in `endpoints.elasticSearch`', type: 'string', enum: [...Object.keys(winston.config.npm.levels), 'off'], }, }, }, limits: { type: 'object', required: [ 'storage', 'maxConcurrentStorageNodeDownloads', 'maxConcurrentOutboundConnections', 'outboundRequestsTimeout', ], description: 'Specifies node limits w.r.t. storage, outbound connections etc.', additionalProperties: false, properties: { storage: { description: 'Maximum total size of all (cached) assets stored in `directories.assets`', type: 'string', pattern: bytesizeRegex.source, }, maxConcurrentStorageNodeDownloads: { description: 'Maximum number of concurrent downloads from the storage node(s)', type: 'integer', minimum: 1, }, maxConcurrentOutboundConnections: { description: 'Maximum number of total simultaneous outbound connections to storage node(s)', type: 'integer', minimum: 1, }, outboundRequestsTimeout: { description: 'Timeout for all outbound storage node http requests in miliseconds', type: 'integer', minimum: 1, }, }, }, intervals: { type: 'object', required: ['saveCacheState', 'checkStorageNodeResponseTimes', 'cacheCleanup'], additionalProperties: false, description: 'Specifies how often periodic tasks (for example cache cleanup) are executed by the node.', properties: { saveCacheState: { description: 'How often, in seconds, will the cache state be saved in `directories.state`. ' + 'Independently of the specified interval, the node will always try to save cache state before exiting.', type: 'integer', minimum: 1, }, checkStorageNodeResponseTimes: { description: 'How often, in seconds, will the distributor node attempt to send requests to all current storage node endpoints ' + 'in order to check how quickly they respond. ' + `The node will never make more than ${MAX_CONCURRENT_RESPONSE_TIME_CHECKS} such requests concurrently.`, type: 'integer', minimum: 1, }, cacheCleanup: { description: 'How often, in seconds, will the distributor node fetch data about all its distribution obligations from the query node ' + 'and remove all the no-longer assigned data objects from local storage and cache state', type: 'integer', minimum: 1, }, }, }, port: { description: 'Distributor node http api port', type: 'integer', minimum: 0 }, keys: { description: 'Specifies the keys available within distributor node CLI.', type: 'array', items: { oneOf: [ { type: 'object', title: 'Substrate uri', description: "Keypair's substrate uri (for example: //Alice)", required: ['suri'], additionalProperties: false, properties: { type: { type: 'string', enum: ['ed25519', 'sr25519', 'ecdsa'], default: 'sr25519' }, suri: { type: 'string' }, }, }, { type: 'object', title: 'Mnemonic phrase', description: 'Menomonic phrase', required: ['mnemonic'], additionalProperties: false, properties: { type: { type: 'string', enum: ['ed25519', 'sr25519', 'ecdsa'], default: 'sr25519' }, mnemonic: { type: 'string' }, }, }, { type: 'object', title: 'JSON backup file', description: 'Path to JSON backup file from polkadot signer / polakdot/apps (relative to config file path)', required: ['keyfile'], additionalProperties: false, properties: { keyfile: { type: 'string' }, }, }, ], }, minItems: 1, }, buckets: { description: 'Specifies the buckets distributed by the node', oneOf: [ { title: 'Bucket ids', description: 'List of distribution bucket ids', type: 'array', items: { type: 'integer', minimum: 0 }, minItems: 1, }, { title: 'All buckets', description: 'Distribute all buckets assigned to worker specified in `workerId`', type: 'string', enum: ['all'], }, ], }, workerId: { description: 'ID of the node operator (distribution working group worker)', type: 'integer', minimum: 0, }, }, } export default configSchema