fix(ipfs): Creating block & data store directories if they don't exit

This commit is contained in:
Chris Troutner
2023-10-23 09:16:06 -07:00
parent 18fe63a5ad
commit 825bc6d2de
4 changed files with 89 additions and 54 deletions
+9 -3
View File
@@ -4,7 +4,13 @@
## Overview
This is a 'boilerplate' repository. It's intended to be forked to start new projects. However, it can also be run as a stand-alone Circuit Relay, for supporting the PSF network.
This is a 'boilerplate' repository. It's intended to be forked to start new projects. Some code projects that are forks of this repository and regularly pull in changes:
- [pay-to-write database (P2WDB)](https://p2wdb.com/)
- [ipfs-bch-wallet-consumer](https://github.com/Permissionless-Software-Foundation/ipfs-bch-wallet-consumer)
- [ipfs-bch-wallet-service](https://github.com/Permissionless-Software-Foundation/ipfs-bch-wallet-service)
In addition to being forked as a boilerpalte, it can also be run as a stand-alone application to create a [Circuit Relay](https://cashstack.info/docs/local-back-end/circuit-relay), which can support the [PSF](https://psfoundation.info) IPFS network. It can also be used for experimenting with [helia-coord](https://github.com/Permissionless-Software-Foundation/helia-coord) and the [psf-bch-wallet](https://github.com/Permissionless-Software-Foundation/psf-bch-wallet) command-line wallet.
## Boilerplate
@@ -12,11 +18,11 @@ This repository has been forked from the [koa-api-boilerplate](https://github.co
- [Koa](https://koajs.com/) framework for REST APIs
- User management
- Access and rate-limit control using [JWT tokens](https://jwt.io/).
- Access and rate-limit control using [JWT tokens](https://jwt.io/)
This boilerplate extends that code to provide the basic features required to be a 'service provider' on the [IPFS](https://ipfs.io) network. This is a core concept in the [web3 Cash Stack](https://cashstack.info). These basic features include:
- [ipfs-coord](https://www.npmjs.com/package/ipfs-coord) for coordinating service providers and consumers across the IPFS network.
- [helia-coord](https://github.com/Permissionless-Software-Foundation/helia-coord) for coordinating service providers and consumers across the IPFS network.
- JSON RPC for creating an API between providers and consumers.
If you are interested in creating your own service provider on the IPFS network, fork this repository and start building.
+1 -1
View File
@@ -69,7 +69,7 @@
"chai": "4.3.0",
"coveralls": "3.1.0",
"husky": "4.3.8",
"lodash.clonedeep": "^4.5.0",
"lodash.clonedeep": "4.5.0",
"mocha": "10.0.0",
"semantic-release": "19.0.3",
"sinon": "9.2.4",
+28 -30
View File
@@ -28,8 +28,9 @@ import config from '../../../config/index.js'
// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/
import * as url from 'url'
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
console.log('__dirname: ', __dirname)
// console.log('__dirname: ', __dirname)
const ROOT_DIR = `${__dirname}../../../`
const IPFS_DIR = `${__dirname}../../../.ipfsdata/ipfs`
class IpfsAdapter {
@@ -37,13 +38,7 @@ class IpfsAdapter {
// Encapsulate dependencies
this.config = config
this.fs = fs
// this.create = create
// Choose the IPFS constructor based on the config settings.
// this.IPFS = IPFSembedded // default
// if (this.config.isProduction) {
// this.IPFS = IPFSexternal
// }
this.createLibp2p = createLibp2p
// Properties of this class instance.
this.isReady = false
@@ -52,11 +47,15 @@ class IpfsAdapter {
this.start = this.start.bind(this)
this.createNode = this.createNode.bind(this)
this.stop = this.stop.bind(this)
this.ensureBlocksDir = this.ensureBlocksDir.bind(this)
}
// Start an IPFS node.
async start () {
try {
// Ensure the directory structure exists that is needed by the IPFS node to store data.
this.ensureBlocksDir()
// Create an IPFS node
const ipfs = await this.createNode()
// console.log('ipfs: ', ipfs)
@@ -96,7 +95,7 @@ class IpfsAdapter {
const datastore = new FsDatastore(`${IPFS_DIR}/datastore`)
// libp2p is the networking layer that underpins Helia
const libp2p = await createLibp2p({
const libp2p = await this.createLibp2p({
datastore,
addresses: {
listen: [
@@ -125,8 +124,7 @@ class IpfsAdapter {
'/ip4/137.184.13.92/tcp/4001/p2p/12D3KooWMbpo92kSGwWiN6QH7fvstMWiLZKcxmReq3Hhbpya2bq4',
'/ip4/78.46.129.7/tcp/4001/p2p/12D3KooWJyc54njjeZGbLew4D8u1ghrmZTTPyh3QpBF7dxtd3zGY',
'/ip4/5.161.72.148/tcp/4001/p2p/12D3KooWAVG5kn46P9mjKCLUSPesmmLeKf2a79qRt6u22hJaEARJ',
'/ip4/161.35.99.207/tcp/4001/p2p/12D3KooWDtj9cfj1SKuLbDNKvKRKSsGN8qivq9M8CYpLPDpcD5pu',
'/ip4/192.168.2.173/tcp/4001/p2p/12D3KooWAz2hbriyU9o1wHNU2nxqG8mMgAdWnXCSfWiv5kxSfW49'
'/ip4/161.35.99.207/tcp/4001/p2p/12D3KooWDtj9cfj1SKuLbDNKvKRKSsGN8qivq9M8CYpLPDpcD5pu'
]
})
],
@@ -146,6 +144,8 @@ class IpfsAdapter {
return helia
} catch (err) {
console.error('Error creating Helia node: ', err)
throw err
}
}
@@ -155,25 +155,23 @@ class IpfsAdapter {
return true
}
// Remove the '/blocks' directory that is used to store IPFS data.
// Dev Note: It's assumed this node is not pinning any data and that
// everything in this directory is transient. This folder will regularly
// fill up and prevent IPFS from starting.
// rmBlocksDir () {
// try {
// const dir = `${IPFS_DIR}/blocks`
// console.log(`Deleting ${dir} directory...`)
//
// this.fs.rmdirSync(dir, { recursive: true })
//
// console.log(`${dir} directory is deleted!`)
//
// return true // Signal successful execution.
// } catch (err) {
// console.log('Error in rmBlocksDir()')
// throw err
// }
// }
// Ensure that the directories exist to store blocks from the IPFS network.
ensureBlocksDir () {
try {
!this.fs.existsSync(`${ROOT_DIR}.ipfsdata`) && this.fs.mkdirSync(`${ROOT_DIR}.ipfsdata`)
!this.fs.existsSync(`${IPFS_DIR}`) && this.fs.mkdirSync(`${IPFS_DIR}`)
!this.fs.existsSync(`${IPFS_DIR}/blockstore`) && this.fs.mkdirSync(`${IPFS_DIR}/blockstore`)
!this.fs.existsSync(`${IPFS_DIR}/datastore`) && this.fs.mkdirSync(`${IPFS_DIR}/datastore`)
return true
} catch (err) {
console.error('Error in adapters/ipfs.js/ensureBlocksDir(): ', err)
throw err
}
}
}
export default IpfsAdapter
+51 -20
View File
@@ -94,24 +94,55 @@ describe('#IPFS-adapter', () => {
})
})
// describe('#rmBlocksDir', () => {
// it('should delete the /blocks directory', () => {
// const result = uut.rmBlocksDir()
//
// assert.equal(result, true)
// })
//
// it('should catch and throw an error', () => {
// try {
// // Force an error
// sandbox.stub(uut.fs, 'rmdirSync').throws(new Error('test error'))
//
// uut.rmBlocksDir()
//
// assert.fail('Unexpected code path')
// } catch (err) {
// assert.equal(err.message, 'test error')
// }
// })
// })
describe('#ensureBlocksDir', () => {
it('should create directory if it does not exist', () => {
// Force desired code path
sandbox.stub(uut.fs, 'existsSync').returns(false)
sandbox.stub(uut.fs, 'mkdirSync').returns(true)
const result = uut.ensureBlocksDir()
assert.equal(result, true)
})
it('should report and throw errors', () => {
// Force an error
sandbox.stub(uut.fs, 'existsSync').throws(new Error('test error'))
try {
uut.ensureBlocksDir()
assert.fail('Unexpected code path')
} catch (err) {
assert.include(err.message, 'test error')
}
})
})
describe('#createNode', () => {
it('should report and throw errors', async () => {
// Force an error
sandbox.stub(uut, 'createLibp2p').rejects(new Error('test error'))
try {
await uut.createNode()
assert.fail('Unexpected code path')
} catch (err) {
assert.include(err.message, 'test error')
}
})
it('should create an IPFS node from Helia', async () => {
const result = await uut.createNode()
// console.log('result: ', result)
// Assert the returned IPFS node has expected properties
assert.property(result, 'libp2p')
assert.property(result, 'blockstore')
// Stop the IPFS node
await result.stop()
})
})
})