|
@@ -2,6 +2,9 @@ import { flags } from '@oclif/command'
|
|
|
import { createApp } from '../services/webApi/app'
|
|
|
import ApiCommandBase from '../command-base/ApiCommandBase'
|
|
|
import logger from '../services/logger'
|
|
|
+import { performSync } from '../services/sync/synchronizer'
|
|
|
+import sleep from 'sleep-promise'
|
|
|
+import _ from 'lodash'
|
|
|
|
|
|
/**
|
|
|
* CLI command:
|
|
@@ -29,6 +32,27 @@ export default class Server extends ApiCommandBase {
|
|
|
required: true,
|
|
|
description: 'Server port.',
|
|
|
}),
|
|
|
+ sync: flags.boolean({
|
|
|
+ char: 's',
|
|
|
+ description: 'Enable data synchronization.',
|
|
|
+ default: false, // TODO: turn on by default
|
|
|
+ }),
|
|
|
+ syncInterval: flags.integer({
|
|
|
+ char: 'i',
|
|
|
+ description: 'Interval between syncronizations (in minutes)',
|
|
|
+ default: 1,
|
|
|
+ }),
|
|
|
+ queryNodeHost: flags.string({
|
|
|
+ char: 'q',
|
|
|
+ required: false,
|
|
|
+ description: 'Query node host and port (e.g.: some.com:8081)',
|
|
|
+ }),
|
|
|
+ syncWorkersNumber: flags.integer({
|
|
|
+ char: 'r',
|
|
|
+ required: false,
|
|
|
+ description: 'Sync workers number (max async operations in progress).',
|
|
|
+ default: 20,
|
|
|
+ }),
|
|
|
...ApiCommandBase.flags,
|
|
|
}
|
|
|
|
|
@@ -39,6 +63,25 @@ export default class Server extends ApiCommandBase {
|
|
|
await this.ensureDevelopmentChain()
|
|
|
}
|
|
|
|
|
|
+ if (flags.sync) {
|
|
|
+ logger.info(`Synchronization enabled.`)
|
|
|
+
|
|
|
+ if (_.isEmpty(flags.queryNodeHost)) {
|
|
|
+ this.error('Query node host parameter required with enabled sync.')
|
|
|
+ }
|
|
|
+
|
|
|
+ const queryNodeUrl = `http://${flags.queryNodeHost}/graphql`
|
|
|
+ logger.info(`Query node endpoint set: ${queryNodeUrl}`)
|
|
|
+
|
|
|
+ runSyncWithInterval(
|
|
|
+ flags.worker,
|
|
|
+ queryNodeUrl,
|
|
|
+ flags.uploads,
|
|
|
+ flags.syncWorkersNumber,
|
|
|
+ flags.syncInterval
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
const account = this.getAccount(flags)
|
|
|
const api = await this.getApi()
|
|
|
|
|
@@ -60,3 +103,37 @@ export default class Server extends ApiCommandBase {
|
|
|
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
|
async finally(): Promise<void> {}
|
|
|
}
|
|
|
+
|
|
|
+function runSyncWithInterval(
|
|
|
+ workerId: number,
|
|
|
+ queryNodeUrl: string,
|
|
|
+ uploadsDirectory: string,
|
|
|
+ syncWorkersNumber: number,
|
|
|
+ syncIntervalMinutes: number
|
|
|
+) {
|
|
|
+ setTimeout(async () => {
|
|
|
+ const sleepIntevalInSeconds = syncIntervalMinutes * 60 * 1000
|
|
|
+ logger.info(`Sync paused for ${syncIntervalMinutes} minute(s).`)
|
|
|
+ await sleep(sleepIntevalInSeconds)
|
|
|
+ logger.info(`Resume syncing....`)
|
|
|
+
|
|
|
+ try {
|
|
|
+ await performSync(
|
|
|
+ workerId,
|
|
|
+ syncWorkersNumber,
|
|
|
+ queryNodeUrl,
|
|
|
+ uploadsDirectory
|
|
|
+ )
|
|
|
+ } catch (err) {
|
|
|
+ logger.error(`Critical sync error: ${err}`)
|
|
|
+ }
|
|
|
+
|
|
|
+ runSyncWithInterval(
|
|
|
+ workerId,
|
|
|
+ queryNodeUrl,
|
|
|
+ uploadsDirectory,
|
|
|
+ syncWorkersNumber,
|
|
|
+ syncIntervalMinutes
|
|
|
+ )
|
|
|
+ }, 0)
|
|
|
+}
|