Skip to content

Update Hypernews examples to reflect latest Autobase API #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 63 additions & 26 deletions problems/04b/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ console.log(chalk.green('\n(1) The Simplest Possible Index\n'))
const store = new Corestore(ram)
const userA = store.get({ name: 'userA' })
const userB = store.get({ name: 'userB' })
const viewCore = store.get({ name: 'view-core' })

await userA.ready();

// Make two Autobases with those two users as inputs.
const baseA = new Autobase([userA, userB], { input: userA })
const baseB = new Autobase([userA, userB], { input: userB })
const baseA = new Autobase({inputs: [userA, userB], localInput: userA, localOutput: viewCore, eagerUpdate: false })
const baseB = new Autobase({inputs: [userA, userB], localInput: userB })

// Append chat messages and read them out again, using the default options.
// This simulates two peers who are always completely up-to-date with each others messages.
Expand All @@ -22,8 +25,8 @@ console.log(chalk.green('\n(1) The Simplest Possible Index\n'))
await baseA.append('A1: likewise. fun exercise huh?')
await baseB.append('B1: yep. great time.')

const viewCore = store.get({ name: 'view-core' })
const view = baseA.linearize(viewCore)
baseA.start()
const view = baseA.view;
await view.update()

for (let i = 0; i < view.length; i++) {
Expand All @@ -38,6 +41,11 @@ console.log(chalk.green('\n(1) The Simplest Possible Index\n'))
await view.update()

console.log('\nStatus after the second update:', view.status)

for (let i = 0; i < view.length; i++) {
const node = await view.get(i)
console.log(node.value.toString())
}
}

// (2) The Simplest Index, but with Forks
Expand All @@ -50,11 +58,12 @@ console.log(chalk.green('\n(2) The Simplest Index, but with Forks\n'))
const viewCore = store.get({ name: 'view-core' })

// Make two Autobases with those two users as inputs.
const baseA = new Autobase([userA, userB], { input: userA })
const baseB = new Autobase([userA, userB], { input: userB })
const baseA = new Autobase({inputs: [userA, userB], localInput: userA, localOutput: viewCore })
const baseB = new Autobase({inputs: [userA, userB], localInput: userB })

// We can use either Autobase to create the index, so well just pick baseA
const view = baseA.linearize(viewCore)
baseA.start()
const view = baseA.view;

// Append chat messages and read them out again, manually specifying empty clocks.
// This simulates two peers creating independent forks.
Expand All @@ -64,6 +73,10 @@ console.log(chalk.green('\n(2) The Simplest Index, but with Forks\n'))
await baseB.append('B1: anybody home?', [])

await view.update()
for (let i = 0; i < view.length; i++) {
const node = await view.get(i)
console.log(node.value.toString())
}
console.log(chalk.blue('Index status after the first two independent messages:'), view.status)

// Add 3 more independent messages to A.
Expand All @@ -72,6 +85,10 @@ console.log(chalk.green('\n(2) The Simplest Index, but with Forks\n'))
}

await view.update()
for (let i = 0; i < view.length; i++) {
const node = await view.get(i)
console.log(node.value.toString())
}
console.log(chalk.blue('Index status after A appends 3 more messages:'), view.status)

// Add 5 more independent messages to B. Does its fork move to the beginning or the end?
Expand All @@ -80,7 +97,18 @@ console.log(chalk.green('\n(2) The Simplest Index, but with Forks\n'))
}

await view.update()
for (let i = 0; i < view.length; i++) {
const node = await view.get(i)
console.log(node.value.toString())
}
console.log(chalk.blue('Index status after B appends 5 more messages:'), view.status)
await baseA.append(`A5: also trying again... but causally`)
await view.update()
for (let i = 0; i < view.length; i++) {
const node = await view.get(i)
console.log(node.value.toString())
}
console.log(chalk.blue('Index status after A appends 1 more message:'), view.status)
}

// (3) A Mapping Indexer
Expand All @@ -90,10 +118,12 @@ console.log(chalk.green('\n(3) A Mapping Indexer\n'))
const store = new Corestore(ram)
const userA = store.get({ name: 'userA' })
const userB = store.get({ name: 'userB' })
const viewCore = store.get({ name: 'view-core' })
const secondViewCore = store.get({ name: 'second-view-core' })

// Make two Autobases with those two users as inputs.
const baseA = new Autobase([userA, userB], { input: userA })
const baseB = new Autobase([userA, userB], { input: userB })
const baseA = new Autobase({inputs: [userA, userB], localInput: userA, localOutput: viewCore })
const baseB = new Autobase({inputs: [userA, userB], localInput: userB, localOutput: secondViewCore })

// Append chat messages and read them out again, using the default options.
// This simulates two peers who are always completely up-to-date with each others messages.
Expand All @@ -102,13 +132,14 @@ console.log(chalk.green('\n(3) A Mapping Indexer\n'))
await baseA.append('A1: likewise. fun exercise huh?')
await baseB.append('B1: yep. great time.')

const viewCore = store.get({ name: 'view-core' })
const view = baseA.linearize(viewCore, {
baseA.start({
async apply (batch) {
batch = batch.map(({ value }) => Buffer.from(value.toString().toUpperCase()))
await view.append(batch)
const uppercasedBatch = batch.map(({ value }) => Buffer.from(value.toString().toUpperCase()))

return await baseA.view.append(uppercasedBatch)
}
})
const view = baseA.view;
await view.update()

// All the indexed nodes will be uppercased now.
Expand All @@ -118,14 +149,15 @@ console.log(chalk.green('\n(3) A Mapping Indexer\n'))
}

// Make another index that is stateful, and records the total message count alongside the message text.
const secondViewCore = store.get({ name: 'second-view-core' })
const secondView = baseA.linearize(secondViewCore, {
baseB.start({
async apply (batch) {
const view = baseB.view;

let count = 0

// First, we need to get the latest count from the last node in the view.
if (secondView.length > 0) {
const lastNode = await secondView.get(secondView.length - 1)
if (view.length > 0) {
const lastNode = await view.get(view.length - 1)
const lastRecord = JSON.parse(lastNode.value.toString())
count = lastRecord.count
}
Expand All @@ -140,10 +172,10 @@ console.log(chalk.green('\n(3) A Mapping Indexer\n'))
})

// Finally, append it just like before.
await secondView.append(batch)
await view.append(batch)
}
})

const secondView = baseB.view;

// Pull all the changes into the new, stateful index.
await secondView.update()
Expand All @@ -162,10 +194,11 @@ console.log(chalk.green('\n(1) Sharing Indexes with Others\n'))
const store = new Corestore(ram)
const userA = store.get({ name: 'userA' })
const userB = store.get({ name: 'userB' })
const viewCore = store.get({ name: 'view-core' })

// Make two Autobases with those two users as inputs.
const baseA = new Autobase([userA, userB], { input: userA })
const baseB = new Autobase([userA, userB], { input: userB })
const baseA = new Autobase({inputs: [userA, userB], localInput: userA, localOutput: viewCore })
const baseB = new Autobase({inputs: [userA, userB], localInput: userB })

// Append chat messages and read them out again, using the default options.
// This simulates two peers who are always completely up-to-date with each others messages.
Expand All @@ -174,16 +207,20 @@ console.log(chalk.green('\n(1) Sharing Indexes with Others\n'))
await baseA.append('A1: likewise. fun exercise huh?')
await baseB.append('B1: yep. great time.')

const viewCore = store.get({ name: 'view-core' })
const view = baseA.linearize(viewCore)
baseA.start()
const view = baseA.view;
await view.update()

// Now we will simulate a "reader" who will use the index above as a remote index.
// The reader will not be participating in the chat, but will be reading from the index.
const baseC = new Autobase([userA, userB])
const readerView = baseC.linearize([viewCore], {
autocommit: false // Ignore this for now
const baseC = new Autobase({inputs: [userA, userB], outputs: [viewCore]});
baseC.start({
eagerUpdate: false, // Ignore this for now
async apply (batch) {
return await baseC.view.append(batch)
}
})
const readerView = baseC.view;

// This will piggy-back off of the work `viewCore` has already done.
await readerView.update()
Expand Down
20 changes: 12 additions & 8 deletions problems/05/hypernews.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,19 @@ class Hypernews {
await writer.ready()

this.name = args.name || writer.key.slice(0, 8).toString('hex')
this.autobase = new Autobase([writer], { outputs: viewOutput })
this.autobase = new Autobase({
inputs: [writer],
localInput: writer,
outputs: [viewOutput],
localOutput: viewOutput
})

for (const w of [].concat(args.writers || [])) {
await this.autobase.addInput(this.store.get(Buffer.from(w, 'hex')))
}

for (const i of [].concat(args.indexes || [])) {
await this.autobase.addDefaultOutput(this.store.get(Buffer.from(i, 'hex')))
await this.autobase.addOutput(this.store.get(Buffer.from(i, 'hex')))
}

await this.autobase.ready()
Expand All @@ -60,9 +65,9 @@ class Hypernews {
this.info()

const self = this
const view = this.autobase.linearize({
unwrap: true,
async apply (batch) {
this.autobase.start({
unwrap: true,
async apply(batch) {
const b = self.bee.batch({ update: false })

for (const { value } of batch) {
Expand All @@ -72,14 +77,13 @@ class Hypernews {
const hash = sha256(op.data)
await b.put('posts!' + hash, { hash, votes: 0, data: op.data })
}

}

await b.flush()
}
})

this.bee = new Hyperbee(view, {
this.bee = new Hyperbee(this.autobase.view, {
extension: false,
keyEncoding: 'utf-8',
valueEncoding: 'json'
Expand All @@ -92,7 +96,7 @@ class Hypernews {
console.log('hrepl hypernews.js ' +
'-n ' + this.name + ' ' +
this.autobase.inputs.map(i => '-w ' + i.key.toString('hex')).join(' ') + ' ' +
this.autobase.defaultOutputs.map(i => '-i ' + i.key.toString('hex')).join(' ')
this.autobase.outputs.map(i => '-i ' + i.key.toString('hex')).join(' ')
)
console.log()
console.log('To use another storage directory use --storage ./another')
Expand Down
20 changes: 13 additions & 7 deletions problems/06/hypernews.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,19 @@ class Hypernews {
await writer.ready()

this.name = args.name || writer.key.slice(0, 8).toString('hex')
this.autobase = new Autobase([writer], { outputs: viewOutput })
this.autobase = new Autobase({
inputs: [writer],
localInput: writer,
outputs: [viewOutput],
localOutput: viewOutput
})

for (const w of [].concat(args.writers || [])) {
await this.autobase.addInput(this.store.get(Buffer.from(w, 'hex')))
}

for (const i of [].concat(args.indexes || [])) {
await this.autobase.addDefaultOutput(this.store.get(Buffer.from(i, 'hex')))
await this.autobase.addOutput(this.store.get(Buffer.from(i, 'hex')))
}

await this.autobase.ready()
Expand All @@ -59,9 +64,9 @@ class Hypernews {
this.info()

const self = this
const view = this.autobase.linearize({
unwrap: true,
async apply (batch) {
this.autobase.start({
unwrap: true,
async apply(batch) {
const b = self.bee.batch({ update: false })

for (const { value } of batch) {
Expand All @@ -77,7 +82,8 @@ class Hypernews {
}
})

this.bee = new Hyperbee(view, {

this.bee = new Hyperbee(this.autobase.view, {
extension: false,
keyEncoding: 'utf-8',
valueEncoding: 'json'
Expand All @@ -90,7 +96,7 @@ class Hypernews {
console.log('hrepl hypernews.js ' +
'-n ' + this.name + ' ' +
this.autobase.inputs.map(i => '-w ' + i.key.toString('hex')).join(' ') + ' ' +
this.autobase.defaultOutputs.map(i => '-i ' + i.key.toString('hex')).join(' ')
this.autobase.outputs.map(i => '-i ' + i.key.toString('hex')).join(' ')
)
console.log()
console.log('To use another storage directory use --storage ./another')
Expand Down
19 changes: 12 additions & 7 deletions problems/07/hypernews.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,19 @@ class Hypernews {
await writer.ready()

this.name = args.name || writer.key.slice(0, 8).toString('hex')
this.autobase = new Autobase([writer], { outputs: viewOutput })
this.autobase = new Autobase({
inputs: [writer],
localInput: writer,
outputs: [viewOutput],
localOutput: viewOutput
})

for (const w of [].concat(args.writers || [])) {
await this.autobase.addInput(this.store.get(Buffer.from(w, 'hex')))
}

for (const i of [].concat(args.indexes || [])) {
await this.autobase.addDefaultOutput(this.store.get(Buffer.from(i, 'hex')))
await this.autobase.addOutput(this.store.get(Buffer.from(i, 'hex')))
}

await this.autobase.ready()
Expand All @@ -60,9 +65,9 @@ class Hypernews {
this.info()

const self = this
const view = this.autobase.linearize({
unwrap: true,
async apply (batch) {
this.autobase.start({
unwrap: true,
async apply(batch) {
const b = self.bee.batch({ update: false })

for (const { value } of batch) {
Expand All @@ -88,7 +93,7 @@ class Hypernews {
}
})

this.bee = new Hyperbee(view, {
this.bee = new Hyperbee(this.autobase.view, {
extension: false,
keyEncoding: 'utf-8',
valueEncoding: 'json'
Expand All @@ -101,7 +106,7 @@ class Hypernews {
console.log('hrepl hypernews.js ' +
'-n ' + this.name + ' ' +
this.autobase.inputs.map(i => '-w ' + i.key.toString('hex')).join(' ') + ' ' +
this.autobase.defaultOutputs.map(i => '-i ' + i.key.toString('hex')).join(' ')
this.autobase.outputs.map(i => '-i ' + i.key.toString('hex')).join(' ')
)
console.log()
console.log('To use another storage directory use --storage ./another')
Expand Down
Loading