All checks were successful
		
		
	
	Release Drafter / Update release notes draft (pull_request) Successful in 3s
				
			
		
			
				
	
	
		
			121 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| const debug = require('debug')('ipfs-pinner');
 | |
| const cliProgress = require('cli-progress');
 | |
| 
 | |
| function sleep(ms) {
 | |
|   return new Promise(resolve => setTimeout(resolve, ms));
 | |
| }
 | |
| 
 | |
| class IpfsPinner {
 | |
|   constructor (kredits, options={}) {
 | |
|     this.kredits = kredits;
 | |
|     this.ipfsApi = this.kredits.ipfs;
 | |
|     this.progressBars = !!options.progress && !process.env.DEBUG;
 | |
| 
 | |
|     if (this.progressBars) {
 | |
|       this.multibar = new cliProgress.MultiBar({
 | |
|         stopOnComplete: true,
 | |
|         clearOnComplete: false,
 | |
|         hideCursor: false,
 | |
|         etaBuffer: 30,
 | |
|         format: '{entity} [{bar}] {percentage}% | ETA: {eta_formatted} | {value}/{total}'
 | |
|       }, cliProgress.Presets.shades_grey);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   async pinAll () {
 | |
|     console.log('Pinning IPFS documents for all known items...\n')
 | |
|     const cids = [];
 | |
|     const promises = [];
 | |
|     const contracts = [
 | |
|       this.kredits.Contributor,
 | |
|       this.kredits.Contribution,
 | |
|       this.kredits.Reimbursement
 | |
|     ]
 | |
| 
 | |
|     for (const contract of contracts) {
 | |
|       debug(`Pinning data from ${contract.constructor.name}...`);
 | |
|       const itemCount = await contract.count;
 | |
|       debug(`${contract.constructor.name} item count:`, itemCount);
 | |
|       let bar;
 | |
| 
 | |
|       if (this.progressBars) {
 | |
|         bar = this.multibar.create(itemCount, 0);
 | |
|         bar.update(0, {entity: `${contract.constructor.name}s`.padEnd(14)});
 | |
|       }
 | |
| 
 | |
|       promises.push(this._pinAllFromContract(contract, itemCount, bar)
 | |
|                         .then(res => { cids.push(...res); }));
 | |
|     }
 | |
| 
 | |
|     await Promise.all(promises);
 | |
| 
 | |
|     // Avoid console output race condition with progress bars finishing update
 | |
|     if (this.progressBars) await sleep(1000);
 | |
| 
 | |
|     return cids;
 | |
|   }
 | |
| 
 | |
|   watch (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);
 | |
|     });
 | |
|     this.kredits.Reimbursement.on('ReimbursementAdded', (id) => {
 | |
|       this.kredits.Reimbursement.getData(id)
 | |
|         .then(data => { return this.ipfsApi.pin(data); })
 | |
|         .then(callback);
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   async _pinAllFromContract (contract, itemCount, progressBar) {
 | |
|     const ipfsApi = this.ipfsApi;
 | |
|     const progressBars = this.progressBars;
 | |
|     const ids = [...Array(itemCount).keys()].map(i => i+1);
 | |
|     const cids = [];
 | |
|     const batchSize = 20;
 | |
|     let position = 0;
 | |
| 
 | |
|     async function loadAndPin(id) {
 | |
|       let cid;
 | |
| 
 | |
|       try {
 | |
|         const data = await contract.getData(id);
 | |
|         debug(`Loaded ${contract.constructor.name} #${id}`);
 | |
|         cid = await ipfsApi.pin(data);
 | |
|         debug(`Pinned ${contract.constructor.name} #${id} at ${cid}`);
 | |
|       } catch(e) {
 | |
|         debug(`Error while trying to load and pin ${contract.constructor.name} #${id}:`)
 | |
|         debug(e);
 | |
|         debug(`\nTrying again...`);
 | |
|         loadAndPin(id);
 | |
|       } finally {
 | |
|         cids.push(cid);
 | |
|         if (progressBars) { progressBar.increment(); }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     while (position < itemCount) {
 | |
|       const batchIds = ids.slice(position, position + batchSize);
 | |
| 
 | |
|       await Promise.all(batchIds.map(async id => loadAndPin(id)));
 | |
| 
 | |
|       position += batchSize;
 | |
|     }
 | |
| 
 | |
|     return cids;
 | |
|   }
 | |
| }
 | |
| 
 | |
| module.exports = IpfsPinner;
 |