Browse Source

storage-node: adding some jsdocs

Mokhtar Naamani 4 years ago
parent
commit
ee048e80a2

+ 3 - 1
storage-node/packages/colossus/bin/cli.js

@@ -217,7 +217,9 @@ async function announce_public_url (api, publicUrl) {
 
 // >> sometimes after tx is finalized.. we are not reaching here!
 
-    // Reannounce before expiery
+    // Reannounce before expiery. Here we are concerned primarily
+    // with keeping the account information refreshed and 'available' in
+    // the ipfs network. our record on chain is valid for 24hr
     reannounce(50 * 60 * 1000) // in 50 minutes
   } catch (err) {
     debug(`announcing public url failed: ${err.stack}`)

+ 88 - 10
storage-node/packages/discovery/discover.js

@@ -5,14 +5,38 @@ const stripEndingSlash = require('@joystream/util/stripEndingSlash')
 const ipfs = require('ipfs-http-client')('localhost', '5001', { protocol: 'http' })
 const BN = require('bn.js')
 
+/**
+ * Determines if code is running in a browser by testing for the global window object
+ */
 function inBrowser () {
   return typeof window !== 'undefined'
 }
 
+/**
+ * Map storage-provider id to a Promise of a discovery result. The purpose
+ * is to avoid concurrent active discoveries for the same provider.
+ */
 var activeDiscoveries = {}
+
+/**
+ * Map of storage provider id to string
+ * Cache of past discovery lookup results
+ */
 var accountInfoCache = {}
+
+/**
+ * After what period of time a cached record is considered stale, and would
+ * trigger a re-discovery, but only if a query is made for the same provider.
+ */
 const CACHE_TTL = 60 * 60 * 1000
 
+/**
+ * Queries the ipns id (service key) of the storage provider from the blockchain.
+ * If the storage provider is not registered it will return null.
+ * @param {number | BN | u64} storageProviderId - the provider id to lookup
+ * @param { RuntimeApi } runtimeApi - api instance to query the chain
+ * @returns { Promise<string | null> } - ipns multiformat address
+ */
 async function getIpnsIdentity (storageProviderId, runtimeApi) {
   storageProviderId = new BN(storageProviderId)
   // lookup ipns identity from chain corresponding to storageProviderId
@@ -26,7 +50,19 @@ async function getIpnsIdentity (storageProviderId, runtimeApi) {
   }
 }
 
-async function discover_over_ipfs_http_gateway (storageProviderId, runtimeApi, gateway) {
+/**
+ * Resolves provider id to its service information.
+ * Will use an IPFS HTTP gateway. If caller doesn't provide a url the default gateway on
+ * the local ipfs node will be used.
+ * If the storage provider is not registered it will throw an error
+ * @param {number | BN | u64} storageProviderId - the provider id to lookup
+ * @param {RuntimeApi} runtimeApi - api instance to query the chain
+ * @param {string} gateway - optional ipfs http gateway url to perform ipfs queries
+ * @returns { Promise<object> } - the published service information
+ */
+async function discover_over_ipfs_http_gateway (
+  storageProviderId, runtimeApi, gateway = 'http://localhost:8080') {
+
   storageProviderId = new BN(storageProviderId)
   let isProvider = await runtimeApi.workers.isStorageProvider(storageProviderId)
 
@@ -41,7 +77,6 @@ async function discover_over_ipfs_http_gateway (storageProviderId, runtimeApi, g
     throw new Error('no identity to resolve')
   }
 
-  gateway = gateway || 'http://localhost:8080'
   gateway = stripEndingSlash(gateway)
 
   const url = `${gateway}/ipns/${identity}`
@@ -51,6 +86,16 @@ async function discover_over_ipfs_http_gateway (storageProviderId, runtimeApi, g
   return response.data
 }
 
+/**
+ * Resolves id of provider to its service information.
+ * Will use the provided colossus discovery api endpoint. If no api endpoint
+ * is provided it attempts to use the configured endpoints from the chain.
+ * If the storage provider is not registered it will throw an error
+ * @param {number | BN | u64 } storageProviderId - provider id to lookup
+ * @param {RuntimeApi} runtimeApi - api instance to query the chain
+ * @param {string} discoverApiEndpoint - url for a colossus discovery api endpoint
+ * @returns { Promise<object> } - the published service information
+ */
 async function discover_over_joystream_discovery_service (storageProviderId, runtimeApi, discoverApiEndpoint) {
   storageProviderId = new BN(storageProviderId)
   let isProvider = await runtimeApi.workers.isStorageProvider(storageProviderId)
@@ -61,8 +106,8 @@ async function discover_over_joystream_discovery_service (storageProviderId, run
 
   const identity = await getIpnsIdentity(storageProviderId, runtimeApi)
 
+  // dont waste time trying to resolve if no identity was found
   if (identity == null) {
-    // dont waste time trying to resolve if no identity was found
     throw new Error('no identity to resolve')
   }
 
@@ -85,6 +130,14 @@ async function discover_over_joystream_discovery_service (storageProviderId, run
   return response.data
 }
 
+/**
+ * Resolves id of provider to its service information.
+ * Will use the local IPFS node over RPC interface.
+ * If the storage provider is not registered it will throw an error.
+ * @param {number | BN | u64 } storageProviderId - provider id to lookup
+ * @param {RuntimeApi} runtimeApi - api instance to query the chain
+ * @returns { Promise<object> } - the published service information
+ */
 async function discover_over_local_ipfs_node (storageProviderId, runtimeApi) {
   storageProviderId = new BN(storageProviderId)
   let isProvider = await runtimeApi.workers.isStorageProvider(storageProviderId)
@@ -103,10 +156,12 @@ async function discover_over_local_ipfs_node (storageProviderId, runtimeApi) {
   const ipns_address = `/ipns/${identity}/`
 
   debug('resolved ipns to ipfs object')
+  // Can this call hang forever!? can/should we set a timeout?
   let ipfs_name = await ipfs.name.resolve(ipns_address, {
-    recursive: false, // there should only be one indirection to service info file
+    // don't recurse, there should only be one indirection to the service info file
+    recursive: false,
     nocache: false
-  }) // this can hang forever!? can we set a timeout?
+  })
 
   debug('getting ipfs object', ipfs_name)
   let data = await ipfs.get(ipfs_name) // this can sometimes hang forever!?! can we set a timeout?
@@ -114,13 +169,23 @@ async function discover_over_local_ipfs_node (storageProviderId, runtimeApi) {
   // there should only be one file published under the resolved path
   let content = data[0].content
 
-  // verify information and if 'discovery' service found
-  // add it to our list of bootstrap nodes
-
-  // TODO cache result or flag
   return JSON.parse(content)
 }
 
+/**
+ * Cached discovery of storage provider service information. If useCachedValue is
+ * set to true, will always return the cached result if found. New discovery will be triggered
+ * if record is found to be stale. If a stale record is not desired (CACHE_TTL old) pass a non zero
+ * value for maxCacheAge, which will force a new discovery and return the new resolved value.
+ * This method in turn calls _discovery which handles concurrent discoveries and selects the appropriate
+ * protocol to perform the query.
+ * If the storage provider is not registered it will resolve to null
+ * @param {number | BN | u64} storageProviderId - provider to discover
+ * @param {RuntimeApi} runtimeApi - api instance to query the chain
+ * @param {bool} useCachedValue - optionaly use chached queries
+ * @param {number} maxCacheAge - maximum age of a cached query that triggers automatic re-discovery
+ * @returns { Promise<object | null> } - the published service information
+ */
 async function discover (storageProviderId, runtimeApi, useCachedValue = false, maxCacheAge = 0) {
   storageProviderId = new BN(storageProviderId)
   const id = storageProviderId.toNumber()
@@ -133,7 +198,7 @@ async function discover (storageProviderId, runtimeApi, useCachedValue = false,
         return _discover(storageProviderId, runtimeApi)
       }
     }
-    // refresh if cache is stale, new value returned on next cached query
+    // refresh if cache if stale, new value returned on next cached query
     if (Date.now() > (cached.updated + CACHE_TTL)) {
       _discover(storageProviderId, runtimeApi)
     }
@@ -144,6 +209,11 @@ async function discover (storageProviderId, runtimeApi, useCachedValue = false,
   }
 }
 
+/**
+ * Returns an object that contains a Promise and exposes its handlers, ie. resolve and reject methods
+ * so it can be fulfilled 'externally'. This is a bit of a hack, but most useful application is when
+ * concurrent async operations are initiated that are all waiting on the same result value.
+ */
 function createExternallyControlledPromise () {
   let resolve, reject
   const promise = new Promise((_resolve, _reject) => {
@@ -153,6 +223,14 @@ function createExternallyControlledPromise () {
   return ({ resolve, reject, promise })
 }
 
+/**
+ * Internal method that handles concurrent discoveries and caching of results. Will
+ * select the appropriate discovery protocol based on wether we are in a browser environemtn or not.
+ * If not in a browser it expects a local ipfs node to be running.
+ * @param {number | BN | u64} storageProviderId
+ * @param {RuntimeApi} runtimeApi - api instance for querying the chain
+ * @returns { Promise<object | null> } - the published service information
+ */
 async function _discover (storageProviderId, runtimeApi) {
   storageProviderId = new BN(storageProviderId)
   const id = storageProviderId.toNumber()

+ 10 - 1
storage-node/packages/discovery/publish.js

@@ -3,7 +3,12 @@ const ipfs = ipfsClient('localhost', '5001', { protocol: 'http' })
 
 const debug = require('debug')('joystream:discovery:publish')
 
-const PUBLISH_KEY = 'self' // 'services'
+/**
+ * The name of the key used for publishing. We use same key used by the ipfs node
+ * for the network identitiy, to make it possible to identify the ipfs node of the storage
+ * provider and use `ipfs ping` to check on the uptime of a particular node.
+ */
+const PUBLISH_KEY = 'self'
 
 function bufferFrom (data) {
   return Buffer.from(JSON.stringify(data), 'utf-8')
@@ -44,7 +49,11 @@ async function publish (service_info) {
     // ttl:      // string - Time duration this record should be cached
   })
 
+  // The hash of the published service information file
   debug(published)
+
+  // Return the key id under which the content was published. Which is used
+  // to lookup the actual ipfs content id of the published service information
   return services_key.id
 }