Also process loading and pinning functions in batches, to prevent stack size errors on RSK nodes.
69 lines
2.2 KiB
JavaScript
69 lines
2.2 KiB
JavaScript
const debug = require('debug')('ipfs-pinner');
|
|
|
|
async function promiseAllInBatches(task, items, batchSize) {
|
|
let position = 0;
|
|
let results = [];
|
|
while (position < items.length) {
|
|
const itemsForBatch = items.slice(position, position + batchSize);
|
|
results = [...results, ...await Promise.allSettled(itemsForBatch.map(item => task(item)))];
|
|
position += batchSize;
|
|
}
|
|
return results;
|
|
}
|
|
|
|
class IpfsPinner {
|
|
constructor (kredits, ipfsApi) {
|
|
this.kredits = kredits;
|
|
this.ipfsApi = ipfsApi || this.kredits.ipfs;
|
|
}
|
|
|
|
async pinAll () {
|
|
const contributorHashes = await this._pinAllFromContract(this.kredits.Contributor);
|
|
const contributionHashes = await this._pinAllFromContract(this.kredits.Contribution);
|
|
// const proposalHashes = await this._pinAllFromContract(this.kredits.Proposal);
|
|
|
|
return contributorHashes.concat(contributionHashes);
|
|
// .concat(proposalHashes);
|
|
}
|
|
|
|
monitor (callback) {
|
|
this.kredits.Contribution.on('ContributionAdded', (id) => {
|
|
this.kredits.Contribution.getData(id)
|
|
.then(data => { return this.ipfsApi.pin(data); })
|
|
.then(callback);
|
|
});
|
|
this.kredits.Contributor.on('ContributorAdded', (id) => {
|
|
this.kredits.Contribution.getData(id)
|
|
.then(data => { return this.ipfsApi.pin(data); })
|
|
.then(callback);
|
|
});
|
|
this.kredits.Contributor.on('ContributorProfileUpdated', (id) => {
|
|
this.kredits.Contributor.getData(id)
|
|
.then(data => { return this.ipfsApi.pin(data); })
|
|
.then(callback);
|
|
});
|
|
}
|
|
|
|
async _pinAllFromContract (contract) {
|
|
debug(`Pinning data from ${contract.constructor.name}...`);
|
|
const count = await contract.count;
|
|
debug('Item count:', count);
|
|
const ids = [...Array(count).keys()].map(i => i+1);
|
|
const cids = [];
|
|
|
|
async function loadAndPin (id) {
|
|
debug(`Loading ${contract.constructor.name} #${id}`);
|
|
return contract.getData(id).then(data => {
|
|
debug(`Pinning ${contract.constructor.name} #${id}`);
|
|
return this.ipfsApi.pin(data).then(cid => cids.push(cid));
|
|
});
|
|
}
|
|
|
|
await promiseAllInBatches(loadAndPin.bind(this), ids, 100);
|
|
|
|
return cids;
|
|
}
|
|
}
|
|
|
|
module.exports = IpfsPinner;
|