@orbitdb/core
Version:
Distributed p2p database on IPFS
115 lines (97 loc) • 2.28 kB
JavaScript
/**
* @namespace module:Log~Heads
* @memberof module:Log
* @description The log's heads.
* @private
*/
import Entry from './entry.js'
import MemoryStorage from '../storage/memory.js'
const DefaultStorage = MemoryStorage
const Heads = async ({ storage, heads }) => {
storage = storage || await DefaultStorage()
const put = async (heads) => {
heads = findHeads(heads)
for (const head of heads) {
await storage.put(head.hash, head.bytes)
}
}
const set = async (heads) => {
await storage.clear()
await put(heads)
}
const add = async (head) => {
const currentHeads = await all()
if (currentHeads.find(e => Entry.isEqual(e, head))) {
return
}
const newHeads = findHeads([...currentHeads, head])
await set(newHeads)
return newHeads
}
const remove = async (hash) => {
const currentHeads = await all()
const newHeads = currentHeads.filter(e => e.hash !== hash)
await set(newHeads)
}
const iterator = async function * () {
const it = storage.iterator()
for await (const [, bytes] of it) {
const head = await Entry.decode(bytes)
yield head
}
}
const all = async () => {
const values = []
for await (const head of iterator()) {
values.push(head)
}
return values
}
const clear = async () => {
await storage.clear()
}
const close = async () => {
await storage.close()
}
// Initialize the heads if given as parameter
await put(heads || [])
return {
put,
set,
add,
remove,
iterator,
all,
clear,
close
}
}
/**
* Find heads from a collection of entries.
*
* Finds entries that are the heads of this collection,
* ie. entries that are not referenced by other entries.
*
* This function is private and not exposed in the Log API
*
* @param {Array<Entry>} entries Entries to search heads from
* @return {Array<Entry>}
* @private
*/
const findHeads = (entries) => {
entries = new Set(entries)
const items = {}
for (const entry of entries) {
for (const next of entry.next) {
items[next] = entry.hash
}
}
const res = []
for (const entry of entries) {
if (!items[entry.hash]) {
res.push(entry)
}
}
return res
}
export default Heads