Browse Source

Merge pull request #1074 from mnaamani/storage-node/balance-and-synched-checks

Storage node/balance and synched checks
Mokhtar Naamani 4 years ago
parent
commit
121b0cb873

+ 15 - 16
storage-node/packages/colossus/bin/cli.js

@@ -142,21 +142,6 @@ function getStorage(runtimeApi) {
   return Storage.create(options)
 }
 
-async function untilChainIsSynched(api) {
-  while (true) {
-    const health = await api.api.rpc.system.health()
-
-    if (health.isSyncing.isTrue) {
-      debug('Waiting for chain to be synced...')
-      await new Promise((resolve) => {
-        setTimeout(resolve, 1 * 30 * 1000)
-      })
-    } else {
-      return
-    }
-  }
-}
-
 async function initApiProduction({ wsProvider, providerId, keyFile, passphrase }) {
   // Load key information
   const { RuntimeApi } = require('@joystream/storage-runtime-api')
@@ -180,7 +165,7 @@ async function initApiProduction({ wsProvider, providerId, keyFile, passphrase }
     throw new Error('Failed to unlock storage provider account')
   }
 
-  await untilChainIsSynched(api)
+  await api.untilChainIsSynced()
 
   if (!(await api.workers.isRoleAccountOfStorageProvider(api.storageProviderId, api.identities.key.address))) {
     throw new Error('storage provider role account and storageProviderId are not associated with a worker')
@@ -230,6 +215,18 @@ async function announcePublicUrl(api, publicUrl) {
     setTimeout(announcePublicUrl, timeoutMs, api, publicUrl)
   }
 
+  const chainIsSyncing = await api.chainIsSyncing()
+  if (chainIsSyncing) {
+    debug('Chain is syncing. Postponing announcing public url.')
+    return reannounce(10 * 60 * 1000)
+  }
+
+  const sufficientBalance = await api.providerHasMinimumBalance(1)
+  if (!sufficientBalance) {
+    debug('Provider role account does not have sufficient balance. Postponing announcing public url.')
+    return reannounce(10 * 60 * 1000)
+  }
+
   debug('announcing public url')
   const { publish } = require('@joystream/service-discovery')
 
@@ -291,11 +288,13 @@ const commands = {
     return startColossus({ api, publicUrl, port })
   },
   discovery: async () => {
+    banner()
     debug('Starting Joystream Discovery Service')
     const { RuntimeApi } = require('@joystream/storage-runtime-api')
     const wsProvider = cli.flags.wsProvider
     const api = await RuntimeApi.create({ provider_url: wsProvider })
     const port = cli.flags.port
+    await api.untilChainIsSynced()
     await startDiscoveryService({ api, port })
   },
 }

+ 18 - 0
storage-node/packages/colossus/lib/sync.js

@@ -92,6 +92,24 @@ async function syncCallback(api, storage) {
 async function syncPeriodic(api, flags, storage) {
   try {
     debug('Starting sync run...')
+
+    const chainIsSyncing = await api.chainIsSyncing()
+    if (chainIsSyncing) {
+      debug('Chain is syncing. Postponing sync run.')
+      return setTimeout(syncPeriodic, flags.syncPeriod, api, flags, storage)
+    }
+
+    const recommendedBalance = await api.providerHasMinimumBalance(300)
+    if (!recommendedBalance) {
+      debug('Warning: Provider role account is running low on balance.')
+    }
+
+    const sufficientBalance = await api.providerHasMinimumBalance(100)
+    if (!sufficientBalance) {
+      debug('Provider role account does not have sufficient balance. Postponing sync run!')
+      return setTimeout(syncPeriodic, flags.syncPeriod, api, flags, storage)
+    }
+
     await syncCallback(api, storage)
     debug('sync run complete')
   } catch (err) {

+ 7 - 0
storage-node/packages/colossus/paths/asset/v0/{id}.js

@@ -91,6 +91,13 @@ module.exports = function (storage, runtime) {
         return
       }
 
+      const sufficientBalance = await runtime.providerHasMinimumBalance(3)
+
+      if (!sufficientBalance) {
+        errorHandler(res, 'Insufficient balance to process upload!', 503)
+        return
+      }
+
       // We'll open a write stream to the backend, but reserve the right to
       // abort upload if the filters don't smell right.
       let stream

+ 24 - 0
storage-node/packages/runtime-api/index.js

@@ -31,6 +31,7 @@ const { DiscoveryApi } = require('@joystream/storage-runtime-api/discovery')
 const { SystemApi } = require('@joystream/storage-runtime-api/system')
 const AsyncLock = require('async-lock')
 const Promise = require('bluebird')
+const { sleep } = require('@joystream/storage-utils/sleep')
 
 Promise.config({
   cancellation: true,
@@ -86,6 +87,29 @@ class RuntimeApi {
     this.api.disconnect()
   }
 
+  async untilChainIsSynced() {
+    debug('Waiting for chain to be synced before proceeding.')
+    while (true) {
+      const isSyncing = await this.chainIsSyncing()
+      if (isSyncing) {
+        debug('Still waiting for chain to be synced.')
+        await sleep(1 * 30 * 1000)
+      } else {
+        return
+      }
+    }
+  }
+
+  async chainIsSyncing() {
+    const { isSyncing } = await this.api.rpc.system.health()
+    return isSyncing.isTrue
+  }
+
+  async providerHasMinimumBalance(minimumBalance) {
+    const providerAccountId = this.identities.key.address
+    return this.balances.hasMinimumBalanceOf(providerAccountId, minimumBalance)
+  }
+
   executeWithAccountLock(accountId, func) {
     return this.asyncLock.acquire(`${accountId}`, func)
   }

+ 1 - 0
storage-node/packages/runtime-api/package.json

@@ -45,6 +45,7 @@
     "temp": "^0.9.0"
   },
   "dependencies": {
+    "@joystream/storage-utils": "^0.1.0",
     "@joystream/types": "^0.12.0",
     "@polkadot/api": "^0.96.1",
     "async-lock": "^1.2.0",

+ 9 - 0
storage-node/packages/util/sleep.js

@@ -0,0 +1,9 @@
+function sleep(ms) {
+  return new Promise((resolve) => {
+    setTimeout(resolve, ms)
+  })
+}
+
+module.exports = {
+  sleep,
+}