mirror of
https://github.com/aljazceru/pear-docs.git
synced 2025-12-17 14:34:19 +01:00
pearify
This commit is contained in:
@@ -23,7 +23,7 @@ pear init -y -t terminal
|
|||||||
npm install hypercore hyperswarm b4a
|
npm install hypercore hyperswarm b4a
|
||||||
```
|
```
|
||||||
|
|
||||||
Alter the generated `writer-app/index.js` to the following:
|
Alter the generated `writer-app/index.js` file to the following:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import Hyperswarm from 'hyperswarm'
|
import Hyperswarm from 'hyperswarm'
|
||||||
@@ -60,7 +60,7 @@ pear init -y -t terminal
|
|||||||
npm install hypercore hyperswarm
|
npm install hypercore hyperswarm
|
||||||
```
|
```
|
||||||
|
|
||||||
Alter the generated `reader-app/index.js` to the following:
|
Alter the generated `reader-app/index.js` file to the following:
|
||||||
|
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
|||||||
@@ -3,28 +3,37 @@
|
|||||||
|
|
||||||
[Hyperbee](../building-blocks/hyperbee.md) is an append-only B-tree based on Hypercore. It provides a key/value-store API with methods to insert and get key/value pairs, perform atomic batch insertions, and create sorted iterators.
|
[Hyperbee](../building-blocks/hyperbee.md) is an append-only B-tree based on Hypercore. It provides a key/value-store API with methods to insert and get key/value pairs, perform atomic batch insertions, and create sorted iterators.
|
||||||
|
|
||||||
The example consists of three files: `writer.js` , `bee-reader.js` and `core-reader.js`.
|
This How-to consists of three applications: `bee-writer-app` , `bee-reader-app` and `core-reader-app`.
|
||||||
|
|
||||||
`writer.js` stores 100k entries from a given dictionary file into a Hyperbee instance. The Corestore instance used to create the Hyperbee instance is replicated using Hyperswarm. This enables other peers to replicate their Corestore instance and download the dictionary data into their local Hyperbee instances.
|
The `bee-writer-app` stores 100k entries from a given dictionary file into a Hyperbee instance. The Corestore instance used to create the Hyperbee instance is replicated using Hyperswarm. This enables other peers to replicate their Corestore instance and sparsely (on-demand) download the dictionary data into their local Hyperbee instances.
|
||||||
|
|
||||||
> Download the `dict.json.gz` compressed file from the [GitHub repository](https://github.com/holepunchto/examples/blob/main/quick-start/hyperbee/dict.json.gz) to the folder where the `writer.js`is present. The compressed file contains 100K dictionary words.
|
Start the `bee-writer-app` project with the following commands:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir bee-writer-app
|
||||||
|
cd bee-writer-app
|
||||||
|
pear init -y -t terminal
|
||||||
|
npm install corestore hyperswarm hyperbee b4a
|
||||||
|
```
|
||||||
|
|
||||||
|
[Click here to save `dict.json`](./assets/dict.json).
|
||||||
|
|
||||||
|
Save it into `bee-writer-app` directory. The `dict.json` file contains 100K dictionary words.
|
||||||
|
|
||||||
|
Alter the generated `bee-writer-app/index.js` file to the following
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
//writer.js
|
import fsp from 'fs/promises'
|
||||||
import fs from 'fs'
|
|
||||||
import zlib from 'zlib'
|
|
||||||
|
|
||||||
import Hyperswarm from 'hyperswarm'
|
import Hyperswarm from 'hyperswarm'
|
||||||
import Corestore from 'corestore'
|
import Corestore from 'corestore'
|
||||||
import Hyperbee from 'hyperbee'
|
import Hyperbee from 'hyperbee'
|
||||||
import goodbye from 'graceful-goodbye'
|
|
||||||
import b4a from 'b4a'
|
import b4a from 'b4a'
|
||||||
|
|
||||||
// create a corestore instance with the given location
|
// create a corestore instance with the given location
|
||||||
const store = new Corestore('./writer-storage')
|
const store = new Corestore(Pear.config.storage)
|
||||||
|
|
||||||
const swarm = new Hyperswarm()
|
const swarm = new Hyperswarm()
|
||||||
goodbye(() => swarm.destroy())
|
Pear.teardown(() => swarm.destroy())
|
||||||
|
|
||||||
// replication of corestore instance
|
// replication of corestore instance
|
||||||
swarm.on('connection', conn => store.replicate(conn))
|
swarm.on('connection', conn => store.replicate(conn))
|
||||||
@@ -53,7 +62,7 @@ discovery.flushed().then(() => {
|
|||||||
// The first block will always be the Hyperbee header block
|
// The first block will always be the Hyperbee header block
|
||||||
if (core.length <= 1) {
|
if (core.length <= 1) {
|
||||||
console.log('importing dictionary...')
|
console.log('importing dictionary...')
|
||||||
const dict = await loadDictionary()
|
const dict = JSON.parse(await fsp.readFile('./dict.json'))
|
||||||
const batch = bee.batch()
|
const batch = bee.batch()
|
||||||
for (const { key, value } of dict) {
|
for (const { key, value } of dict) {
|
||||||
await batch.put(key, value)
|
await batch.put(key, value)
|
||||||
@@ -63,43 +72,51 @@ if (core.length <= 1) {
|
|||||||
// Otherwise just seed the previously-imported dictionary
|
// Otherwise just seed the previously-imported dictionary
|
||||||
console.log('seeding dictionary...')
|
console.log('seeding dictionary...')
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadDictionary() {
|
|
||||||
const compressed = await fs.promises.readFile('./dict.json.gz')
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// unzip the compressed file and return the content
|
|
||||||
zlib.unzip(compressed, (err, dict) => {
|
|
||||||
if (err) return reject(err)
|
|
||||||
return resolve(JSON.parse(b4a.toString(dict)))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Open the app with `pear dev`:
|
||||||
|
|
||||||
`bee-reader.js` creates a Corestore instance and replicates it using the Hyperswarm instance to the same topic as `writer.js`. On every word entered in the command line, it will download the respective data to the local Hyperbee instance.
|
```
|
||||||
|
cd bee-writer-app
|
||||||
|
pear dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Start the `bee-reader-app` project with the following commands:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir bee-reader-app
|
||||||
|
cd bee-reader-app
|
||||||
|
pear init -y -t terminal
|
||||||
|
npm install corestore hyperswarm hyperbee b4a
|
||||||
|
```
|
||||||
|
|
||||||
|
The `bee-reader-app` creates a `Corestore` instance and replicates it using the `Hyperswarm` instance to the same topic as `bee-writer-app`. On every word entered in the command line, it will download the respective data to the local `Hyperbee` instance.
|
||||||
|
|
||||||
|
|
||||||
|
Alter the generated `bee-reader-app/index.js` file to the following
|
||||||
|
|
||||||
Try looking at disk space the `reader-storage` directory is using after each query. notice that it's significantly smaller than `writer-storage`! This is because Hyperbee only downloads the Hypercore blocks it needs to satisfy each query, a feature we call **sparse downloading.**
|
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
bee-reader.js
|
|
||||||
import Hyperswarm from 'hyperswarm'
|
import Hyperswarm from 'hyperswarm'
|
||||||
import Corestore from 'corestore'
|
import Corestore from 'corestore'
|
||||||
import Hyperbee from 'hyperbee'
|
import Hyperbee from 'hyperbee'
|
||||||
import goodbye from 'graceful-goodbye'
|
|
||||||
import b4a from 'b4a'
|
import b4a from 'b4a'
|
||||||
|
|
||||||
|
const key = Pear.config.args[0]
|
||||||
|
|
||||||
|
if (!key) throw new Error('provide a key')
|
||||||
|
|
||||||
// creation of a corestore instance
|
// creation of a corestore instance
|
||||||
const store = new Corestore('./reader-storage')
|
const store = new Corestore(Pear.config.storage)
|
||||||
|
|
||||||
const swarm = new Hyperswarm()
|
const swarm = new Hyperswarm()
|
||||||
goodbye(() => swarm.destroy())
|
Pear.teardown(() => swarm.destroy())
|
||||||
|
|
||||||
// replication of the corestore instance on connection with other peers
|
// replication of the corestore instance on connection with other peers
|
||||||
swarm.on('connection', conn => store.replicate(conn))
|
swarm.on('connection', (conn) => store.replicate(conn))
|
||||||
|
|
||||||
// create or get the hypercore using the public key supplied as command-line argument
|
// create or get the hypercore using the public key supplied as command-line argument
|
||||||
const core = store.get({ key: b4a.from(process.argv[2], 'hex') })
|
const core = store.get({ key: b4a.from(key, 'hex') })
|
||||||
|
|
||||||
// create a hyperbee instance using the hypercore instance
|
// create a hyperbee instance using the hypercore instance
|
||||||
const bee = new Hyperbee(core, {
|
const bee = new Hyperbee(core, {
|
||||||
@@ -116,10 +133,7 @@ console.log('core key here is:', core.key.toString('hex'))
|
|||||||
// Attempt to connect to peers
|
// Attempt to connect to peers
|
||||||
swarm.join(core.discoveryKey)
|
swarm.join(core.discoveryKey)
|
||||||
|
|
||||||
// Do a single Hyperbee.get for every line of stdin data
|
Pear.stio.in.on('data', data => {
|
||||||
// Each `get` will only download the blocks necessary to satisfy the query
|
|
||||||
process.stdin.setEncoding('utf-8')
|
|
||||||
process.stdin.on('data', data => {
|
|
||||||
const word = data.trim()
|
const word = data.trim()
|
||||||
if (!word.length) return
|
if (!word.length) return
|
||||||
bee.get(word).then(node => {
|
bee.get(word).then(node => {
|
||||||
@@ -129,17 +143,34 @@ process.stdin.on('data', data => {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
Importantly, a Hyperbee is **just** a Hypercore, where the tree nodes are stored as Hypercore blocks. Now examine the Hyperbee as if it were just a Hypercore and log out a few blocks.
|
Open the `bee-reader-app` and pass it the core key:
|
||||||
|
|
||||||
`core-reader.js` will continually download and log the last block of the Hypercore containing the Hyperbee data. Note that these blocks are encoded using Hyperbee's Node encoding, which we can easily import and use.
|
```
|
||||||
|
cd bee-reader-app
|
||||||
|
pear dev -- <SUPPLY KEY HERE>
|
||||||
|
```
|
||||||
|
|
||||||
|
Query the database by entering a key to lookup into the `bee-reader-app` terminal and hitting return.
|
||||||
|
|
||||||
|
Each application has dedicated storage at `Pear.config.storage`. Try logging out `Pear.config.storage` for the `bee-reader-app` and then look at the disk space for that storage path after each query. notice that it's significantly smaller than `writer-storage`! This is because Hyperbee only downloads the Hypercore blocks it needs to satisfy each query, a feature we call **sparse downloading.**
|
||||||
|
|
||||||
|
Importantly, a Hyperbee is **just** a Hypercore, where the tree nodes are stored as Hypercore blocks.
|
||||||
|
|
||||||
|
Finally create a `core-reader-app` project:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir core-reader-app
|
||||||
|
cd core-reader-app
|
||||||
|
pear init -y -t terminal
|
||||||
|
npm install corestore hyperswarm b4a
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Alter the generated `core-reader-app/index.js` file to the following
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
core-reader.js
|
|
||||||
import Hypercore from 'hypercore'
|
|
||||||
import Hyperswarm from 'hyperswarm'
|
import Hyperswarm from 'hyperswarm'
|
||||||
import Corestore from 'corestore'
|
import Corestore from 'corestore'
|
||||||
import goodbye from 'graceful-goodbye'
|
|
||||||
import b4a from 'b4a'
|
import b4a from 'b4a'
|
||||||
|
|
||||||
import { Node } from 'hyperbee/lib/messages.js'
|
import { Node } from 'hyperbee/lib/messages.js'
|
||||||
@@ -148,7 +179,7 @@ import { Node } from 'hyperbee/lib/messages.js'
|
|||||||
const store = new Corestore('./reader-storage')
|
const store = new Corestore('./reader-storage')
|
||||||
|
|
||||||
const swarm = new Hyperswarm()
|
const swarm = new Hyperswarm()
|
||||||
goodbye(() => swarm.destroy())
|
Pear.teardown(() => swarm.destroy())
|
||||||
|
|
||||||
// replication of the corestore instance on connection with other peers
|
// replication of the corestore instance on connection with other peers
|
||||||
swarm.on('connection', conn => store.replicate(conn))
|
swarm.on('connection', conn => store.replicate(conn))
|
||||||
@@ -173,3 +204,14 @@ const lastBlock = await core.get(core.length - 1)
|
|||||||
console.log(`Raw Block ${seq}:`, lastBlock)
|
console.log(`Raw Block ${seq}:`, lastBlock)
|
||||||
console.log(`Decoded Block ${seq}`, Node.decode(lastBlock))
|
console.log(`Decoded Block ${seq}`, Node.decode(lastBlock))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Open the `core-reader-app` with `pear dev`, passing the core key to it:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd core-reader-app
|
||||||
|
pear dev -- <SUPPLY KEY HERE>
|
||||||
|
```
|
||||||
|
|
||||||
|
Now we can examine the Hyperbee as if it were just a Hypercore.
|
||||||
|
|
||||||
|
The `core-reader-app` will continually download and log the last block of the Hypercore containing the Hyperbee data. Note that these blocks are encoded using Hyperbee's `Node` encoding, which has been imported directly from `Hyperbee` here for the purposes of explanation.
|
||||||
@@ -16,7 +16,7 @@ pear init -y -t terminal
|
|||||||
npm install corestore hyperswarm b4a
|
npm install corestore hyperswarm b4a
|
||||||
```
|
```
|
||||||
|
|
||||||
Alter the generated `multicore-writer-app/index.js` to the following
|
Alter the generated `multicore-writer-app/index.js` file to the following
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import Hyperswarm from 'hyperswarm'
|
import Hyperswarm from 'hyperswarm'
|
||||||
@@ -73,10 +73,9 @@ mkdir multicore-reader-app
|
|||||||
cd multicore-reader-app
|
cd multicore-reader-app
|
||||||
pear init -y -t terminal
|
pear init -y -t terminal
|
||||||
npm install corestore hyperswarm b4a
|
npm install corestore hyperswarm b4a
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Alter the generated `multicore-reader-app/index.js` to the following
|
Alter the generated `multicore-reader-app/index.js` file to the following
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import Corestore from 'corestore'
|
import Corestore from 'corestore'
|
||||||
@@ -129,7 +128,6 @@ for (const key of otherKeys) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
In one terminal, open `multicore-writer-app` with `pear dev`.
|
In one terminal, open `multicore-writer-app` with `pear dev`.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user