UNPKG

@kyve/core-beta

Version:

🚀 The base KYVE node implementation.

118 lines (102 loc) • 3.72 kB
import BigNumber from "bignumber.js"; import { Node } from "../.."; import { callWithBackoffStrategy, standardizeJSON, VOTE } from "../../utils"; /** * saveBundleDownload downloads a bundle from the storage provider. * The download should be aborted if the pool is not * active anymore or a new bundle proposal has been found * or the node is the current uploader and the upload interval * has passed. * * If there is an error retrieving the bundle from the storage provider * the node instantly votes with abstain and continues to try to retrieve * the bundle. * * @method saveBundleDownload * @param {Node} this * @param {number} updatedAt * @return {Promise<Buffer | null>} */ export async function saveBundleDownload( this: Node, updatedAt: number ): Promise<Buffer | null> { return await callWithBackoffStrategy( async () => { await this.syncPoolState(); const unixNow = new BigNumber(Date.now()); const unixIntervalEnd = new BigNumber( this.pool.bundle_proposal!.updated_at ) .plus(this.pool.data!.upload_interval) .multipliedBy(1000); // check if new proposal is available in the meantime if (parseInt(this.pool.bundle_proposal!.updated_at) > updatedAt) { return null; } // check if pool got inactive in the meantime if (this.validateIsPoolActive()) { return null; } // check if validator needs to upload if ( this.pool.bundle_proposal!.next_uploader === this.staker && unixNow.gte(unixIntervalEnd) ) { return null; } // get storage provider the proposed bundle was saved to this.logger.debug( `storageProviderFactory(${ this.pool.bundle_proposal?.storage_provider_id ?? 0 }, $STORAGE_PRIV)` ); const storageProvider = await this.storageProviderFactory( this.pool.bundle_proposal?.storage_provider_id ?? 0 ); // calculate download timeout for storage provider // the timeout should always be 20 seconds less than the upload interval // so that the node still has enough time to vote abstain when the // download timeout is reached const downloadTimeoutSec = Math.max( 0, parseInt(this.pool.data!.upload_interval) - 20 ); this.logger.debug( `this.storageProvider.retrieveBundle(${ this.pool.bundle_proposal!.storage_id },${downloadTimeoutSec * 1000})` ); const { storageData } = await storageProvider.retrieveBundle( this.pool.bundle_proposal!.storage_id, downloadTimeoutSec * 1000 ); this.m.storage_provider_retrieve_successful.inc(); this.logger.info( `Successfully downloaded bundle with id ${ this.pool.bundle_proposal!.storage_id } from StorageProvider:${storageProvider.name}` ); return storageData; }, { limitTimeoutMs: 5 * 60 * 1000, increaseByMs: 10 * 1000 }, async (err: any, ctx) => { this.logger.info( `Retrieving bundle from StorageProvider was unsuccessful. Retrying in ${( ctx.nextTimeoutInMs / 1000 ).toFixed(2)}s ...` ); this.logger.debug(standardizeJSON(err)); this.m.storage_provider_retrieve_failed.inc(); // vote abstain if bundle could not be retrieved from storage // provider. With voting abstain the network knows that the node // is still online but just could not vote if (!this.pool.bundle_proposal?.voters_abstain.includes(this.staker)) { await this.voteBundleProposal( this.pool.bundle_proposal!.storage_id, VOTE.ABSTAIN ); } } ); }