mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-03-30 15:08:28 +00:00
Fixing lists
This commit is contained in:
parent
1d70af0e86
commit
57c006feb2
@ -4,9 +4,10 @@ var async = require('asyncawait/async');
|
|||||||
var OrbitClient = require('../src/OrbitClient');
|
var OrbitClient = require('../src/OrbitClient');
|
||||||
var Timer = require('./Timer');
|
var Timer = require('./Timer');
|
||||||
|
|
||||||
// Redis host
|
// orbit-server
|
||||||
var host = '178.62.229.175';
|
// const host = 'localhost';
|
||||||
var port = 6379;
|
const host = '178.62.241.75';
|
||||||
|
const port = 3333;
|
||||||
|
|
||||||
var username = 'testrunner';
|
var username = 'testrunner';
|
||||||
var password = '';
|
var password = '';
|
||||||
|
@ -5,17 +5,18 @@ const await = require('asyncawait/await');
|
|||||||
const OrbitClient = require('../src/OrbitClient');
|
const OrbitClient = require('../src/OrbitClient');
|
||||||
const Timer = require('./Timer');
|
const Timer = require('./Timer');
|
||||||
|
|
||||||
// Redis
|
// orbit-server
|
||||||
const host = 'localhost';
|
const host = 'localhost';
|
||||||
|
// const host = '178.62.241.75';
|
||||||
const port = 3333;
|
const port = 3333;
|
||||||
|
|
||||||
const username = 'LambOfGod';
|
const username = process.argv[3] ? process.argv[3] : 'LambOfGod';
|
||||||
const password = '';
|
const password = '';
|
||||||
|
|
||||||
let run = (async(() => {
|
let run = (async(() => {
|
||||||
try {
|
try {
|
||||||
const orbit = OrbitClient.connect(host, port, username, password);
|
const orbit = OrbitClient.connect(host, port, username, password);
|
||||||
const channel = 'testing123';
|
const channel = process.argv[2] ? process.argv[2] : 'testing123';
|
||||||
const db = orbit.channel(channel);
|
const db = orbit.channel(channel);
|
||||||
|
|
||||||
let count = 1;
|
let count = 1;
|
||||||
@ -23,7 +24,7 @@ let run = (async(() => {
|
|||||||
while(true) {
|
while(true) {
|
||||||
const key = "username";
|
const key = "username";
|
||||||
let timer = new Timer(true);
|
let timer = new Timer(true);
|
||||||
db.put(key, "Lamb Of God " + count);
|
db.put(key, username + " " + count);
|
||||||
let v = db.get(key);
|
let v = db.get(key);
|
||||||
|
|
||||||
console.log("---------------------------------------------------")
|
console.log("---------------------------------------------------")
|
||||||
|
50
examples/keyvalueReader.js
Normal file
50
examples/keyvalueReader.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const async = require('asyncawait/async');
|
||||||
|
const await = require('asyncawait/await');
|
||||||
|
const OrbitClient = require('../src/OrbitClient');
|
||||||
|
const Timer = require('./Timer');
|
||||||
|
|
||||||
|
// orbit-server
|
||||||
|
const host = 'localhost';
|
||||||
|
// const host = '178.62.241.75';
|
||||||
|
const port = 3333;
|
||||||
|
|
||||||
|
const username = process.argv[3] ? process.argv[3] : 'LambOfGod';
|
||||||
|
const password = '';
|
||||||
|
|
||||||
|
let running = false;
|
||||||
|
let run = (async(() => {
|
||||||
|
if(!running) {
|
||||||
|
try {
|
||||||
|
running = true;
|
||||||
|
const orbit = OrbitClient.connect(host, port, username, password);
|
||||||
|
const channel = process.argv[2] ? process.argv[2] : 'testing123';
|
||||||
|
const db = orbit.channel(channel);
|
||||||
|
|
||||||
|
let count = 1;
|
||||||
|
|
||||||
|
setInterval(async(() => {
|
||||||
|
const key = "username";
|
||||||
|
let timer = new Timer(true);
|
||||||
|
let v = db.get(key);
|
||||||
|
|
||||||
|
console.log("---------------------------------------------------")
|
||||||
|
console.log("Key | Value")
|
||||||
|
console.log("---------------------------------------------------")
|
||||||
|
console.log(`${key} | ${v}`);
|
||||||
|
console.log("---------------------------------------------------")
|
||||||
|
console.log(`Query #${count} took ${timer.stop(true)} ms\n`);
|
||||||
|
|
||||||
|
count ++;
|
||||||
|
running = false;
|
||||||
|
}), 1000);
|
||||||
|
} catch(e) {
|
||||||
|
console.error("error:", e);
|
||||||
|
console.error(e.stack);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))();
|
||||||
|
|
||||||
|
module.exports = run;
|
@ -5,17 +5,20 @@ const await = require('asyncawait/await');
|
|||||||
const OrbitClient = require('../src/OrbitClient');
|
const OrbitClient = require('../src/OrbitClient');
|
||||||
const Timer = require('./Timer');
|
const Timer = require('./Timer');
|
||||||
|
|
||||||
// Redis
|
// orbit-server
|
||||||
const host = 'localhost';
|
const host = 'localhost';
|
||||||
const port = 6379;
|
// const host = '178.62.241.75';
|
||||||
|
const port = 3333;
|
||||||
|
|
||||||
const username = 'LambOfGod';
|
const username = process.argv[3] ? process.argv[3] : 'LambOfGod';
|
||||||
const password = '';
|
const password = '';
|
||||||
|
|
||||||
|
const prefix = process.argv[4] ? process.argv[4] : 'LambOfGod';
|
||||||
|
|
||||||
let run = (async(() => {
|
let run = (async(() => {
|
||||||
try {
|
try {
|
||||||
var orbit = OrbitClient.connect(host, port, username, password);
|
var orbit = OrbitClient.connect(host, port, username, password);
|
||||||
const c1 = 'c1';
|
const c1 = process.argv[2] ? process.argv[2] : 'c1';;
|
||||||
const channel = orbit.channel(c1);
|
const channel = orbit.channel(c1);
|
||||||
|
|
||||||
let count = 1;
|
let count = 1;
|
||||||
@ -26,23 +29,25 @@ let run = (async(() => {
|
|||||||
if(!running) {
|
if(!running) {
|
||||||
running = true;
|
running = true;
|
||||||
|
|
||||||
// let timer = new Timer(true);
|
let timer = new Timer(true);
|
||||||
channel.add("Hello " + count);
|
channel.add(prefix + count);
|
||||||
// console.log(`Query #${count} took ${timer.stop(true)} ms\n`);
|
console.log(`Query #${count} took ${timer.stop(true)} ms\n`);
|
||||||
|
|
||||||
const c = channel.iterator({ limit: -1 }).collect().length;
|
let timer2 = new Timer(true);
|
||||||
let items = channel.iterator({ limit: 5 }).collect();
|
// const c = channel.iterator({ limit: -1 }).collect().length;
|
||||||
|
let items = channel.iterator({ limit: -1 }).collect();
|
||||||
console.log("---------------------------------------------------")
|
console.log("---------------------------------------------------")
|
||||||
console.log("Key | Value")
|
console.log("Key | Value")
|
||||||
console.log("---------------------------------------------------")
|
console.log("---------------------------------------------------")
|
||||||
console.log(items.map((e) => `${e.payload.key} | ${e.payload.value}`).join("\n"));
|
console.log(items.map((e) => `${e.payload.key} | ${e.payload.value}`).join("\n"));
|
||||||
console.log("---------------------------------------------------")
|
console.log("---------------------------------------------------")
|
||||||
console.log(`Found ${items.length} items from ${c}\n`);
|
// console.log(`Found ${items.length} items from ${c}\n`);
|
||||||
|
console.log(`Query 2 #${count} took ${timer2.stop(true)} ms\n`);
|
||||||
|
|
||||||
running = false;
|
running = false;
|
||||||
count ++;
|
count ++;
|
||||||
}
|
}
|
||||||
}), 500);
|
}), 2000);
|
||||||
|
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.error("error:", e);
|
console.error("error:", e);
|
||||||
|
@ -5,9 +5,10 @@ var await = require('asyncawait/await');
|
|||||||
var OrbitClient = require('../src/OrbitClient');
|
var OrbitClient = require('../src/OrbitClient');
|
||||||
var Timer = require('./Timer');
|
var Timer = require('./Timer');
|
||||||
|
|
||||||
// Redis
|
// orbit-server
|
||||||
var host = 'localhost';
|
// const host = 'localhost';
|
||||||
var port = 6379;
|
const host = '178.62.241.75';
|
||||||
|
const port = 3333;
|
||||||
|
|
||||||
var username = process.argv[2] ? process.argv[2] : 'DankoJones';
|
var username = process.argv[2] ? process.argv[2] : 'DankoJones';
|
||||||
var password = '';
|
var password = '';
|
||||||
|
@ -30,6 +30,13 @@ class DataStore {
|
|||||||
return this._fetchRecursive(options);
|
return this._fetchRecursive(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_fetchOne(item) {
|
||||||
|
return new Promise(async((resolve, reject) => {
|
||||||
|
await(item.getPayload());
|
||||||
|
resolve({ hash: item.data, payload: item.Payload });
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
_fetchRecursive(options, currentAmount, deleted, res) {
|
_fetchRecursive(options, currentAmount, deleted, res) {
|
||||||
const opts = {
|
const opts = {
|
||||||
amount: options && options.amount ? options.amount : DefaultAmount,
|
amount: options && options.amount ? options.amount : DefaultAmount,
|
||||||
@ -47,17 +54,20 @@ class DataStore {
|
|||||||
let handledItems = deleted ? deleted : [];
|
let handledItems = deleted ? deleted : [];
|
||||||
let item;
|
let item;
|
||||||
|
|
||||||
|
// Fetch the item from ipfs
|
||||||
const node = this.list.items[this.list.items.length - currentAmount - 1];
|
const node = this.list.items[this.list.items.length - currentAmount - 1];
|
||||||
if(node)
|
if(node) item = await(this._fetchOne(node));
|
||||||
item = await(this._fetchOne(node));
|
|
||||||
|
const canAdd = (firstHash, key, foundItemsCount) => {
|
||||||
|
return (!opts.key || (opts.key && opts.key === item.payload.key)) &&
|
||||||
|
(!opts.first || (opts.first && (opts.first === item.payload.key && foundItemsCount === 0))
|
||||||
|
|| (opts.first && (opts.first !== item.payload.key && foundItemsCount > 0)))
|
||||||
|
};
|
||||||
|
|
||||||
if(item && item.payload) {
|
if(item && item.payload) {
|
||||||
const wasHandled = _.includes(handledItems, item.payload.key);
|
const wasHandled = _.includes(handledItems, item.payload.key); // Last Write Wins, if it was handled, ignore the rest
|
||||||
if((item.payload.op === HashCacheOps.Put || item.payload.op === HashCacheOps.Add) && !wasHandled) {
|
if((item.payload.op === HashCacheOps.Put || item.payload.op === HashCacheOps.Add) && !wasHandled) {
|
||||||
if((!opts.key || (opts.key && opts.key === item.payload.key)) &&
|
if(canAdd(opts.first, item.payload.key, result.length)) {
|
||||||
(!opts.first || (opts.first && (opts.first === item.payload.key && result.length === 0))
|
|
||||||
|| (opts.first && (opts.first !== item.payload.key && result.length > 0))))
|
|
||||||
{
|
|
||||||
result.push(item);
|
result.push(item);
|
||||||
handledItems.push(item.payload.key);
|
handledItems.push(item.payload.key);
|
||||||
}
|
}
|
||||||
@ -85,15 +95,6 @@ class DataStore {
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_fetchOne(item) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
await(item.getPayload());
|
|
||||||
const f = item.compact();
|
|
||||||
const res = { hash: f.data, payload: f.Payload };
|
|
||||||
resolve(res);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = DataStore;
|
module.exports = DataStore;
|
||||||
|
@ -15,6 +15,8 @@ const PubSub = require('./PubSub');
|
|||||||
const List = require('./list/OrbitList');
|
const List = require('./list/OrbitList');
|
||||||
const DataStore = require('./DataStore');
|
const DataStore = require('./DataStore');
|
||||||
|
|
||||||
|
var Timer = require('../examples/Timer');
|
||||||
|
|
||||||
const pubkey = Keystore.getKeys().publicKey;
|
const pubkey = Keystore.getKeys().publicKey;
|
||||||
const privkey = Keystore.getKeys().privateKey;
|
const privkey = Keystore.getKeys().privateKey;
|
||||||
|
|
||||||
@ -27,11 +29,22 @@ class OrbitClient {
|
|||||||
channel(hash, password) {
|
channel(hash, password) {
|
||||||
if(password === undefined) password = '';
|
if(password === undefined) password = '';
|
||||||
|
|
||||||
this._pubsub.subscribe(hash, password, async((hash, message) => {
|
const processMsg = async((hash, message) => {
|
||||||
const other = await(List.fromIpfsHash(this._ipfs, message));
|
const other = await(List.fromIpfsHash(this._ipfs, message));
|
||||||
if(other.id !== this.user.username)
|
if(other.id !== this.user.username) {
|
||||||
this._store.join(other);
|
this._store.join(other);
|
||||||
}));
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const onLatest = async((hash, message) => {
|
||||||
|
console.log("--> Received latest list:", message)
|
||||||
|
if(message) {
|
||||||
|
const other = await(List.fromIpfsHash(this._ipfs, message));
|
||||||
|
this._store.join(other);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._pubsub.subscribe(hash, password, processMsg, onLatest);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
iterator: (options) => this._iterator(hash, password, options),
|
iterator: (options) => this._iterator(hash, password, options),
|
||||||
@ -106,9 +119,12 @@ class OrbitClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_publish(data) {
|
_publish(data) {
|
||||||
let post = new Post(data);
|
return new Promise((resolve, reject) => {
|
||||||
// post.encrypt(privkey, pubkey);
|
let post = new Post(data);
|
||||||
return await (ipfsAPI.putObject(this._ipfs, JSON.stringify(post)));
|
// post.encrypt(privkey, pubkey);
|
||||||
|
const res = await (ipfsAPI.putObject(this._ipfs, JSON.stringify(post)));
|
||||||
|
resolve(res);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_createMessage(channel, password, operation, key, value) {
|
_createMessage(channel, password, operation, key, value) {
|
||||||
@ -121,13 +137,13 @@ class OrbitClient {
|
|||||||
|
|
||||||
/* DB Operations */
|
/* DB Operations */
|
||||||
_add(channel, password, data) {
|
_add(channel, password, data) {
|
||||||
const post = this._publish(data);
|
const post = await(this._publish(data));
|
||||||
const key = post.Hash;
|
const key = post.Hash;
|
||||||
return await(this._createOperation(channel, password, HashCacheOps.Add, key, post.Hash, data));
|
return await(this._createOperation(channel, password, HashCacheOps.Add, key, post.Hash, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
_put(channel, password, key, data) {
|
_put(channel, password, key, data) {
|
||||||
const post = this._publish(data);
|
const post = await(this._publish(data));
|
||||||
return await(this._createOperation(channel, password, HashCacheOps.Put, key, post.Hash));
|
return await(this._createOperation(channel, password, HashCacheOps.Put, key, post.Hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,12 +152,18 @@ class OrbitClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createOperation(channel, password, operation, key, value, data) {
|
_createOperation(channel, password, operation, key, value, data) {
|
||||||
const hash = this._createMessage(channel, password, operation, key, value);
|
var create = async(() => {
|
||||||
const res = await(this._store.add(hash));
|
return new Promise(async((resolve, reject) => {
|
||||||
const listHash = await(this._store.list.getIpfsHash());
|
const hash = this._createMessage(channel, password, operation, key, value);
|
||||||
await(this._pubsub.publish(channel, listHash));
|
const res = await(this._store.add(hash));
|
||||||
// return res;
|
const listHash = await(this._store.list.getIpfsHash());
|
||||||
|
await(this._pubsub.publish(channel, listHash));
|
||||||
|
resolve();
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
await(create());
|
||||||
return key;
|
return key;
|
||||||
|
// return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
_deleteChannel(channel, password) {
|
_deleteChannel(channel, password) {
|
||||||
|
@ -8,13 +8,25 @@ class Pubsub {
|
|||||||
this.ipfs = ipfs;
|
this.ipfs = ipfs;
|
||||||
this._subscriptions = {};
|
this._subscriptions = {};
|
||||||
this._socket = io(`http://${host}:${port}`);
|
this._socket = io(`http://${host}:${port}`);
|
||||||
this._socket.on('connect', (socket) => console.log('Connected to', `http://${host}:${port}`));
|
this._socket.on('connect', (socket) => console.log(`Connected to http://${host}:${port}`));
|
||||||
|
this._socket.on('disconnect', (socket) => console.log(`Disconnected from http://${host}:${port}`));
|
||||||
|
this._socket.on('event', (e) => console.log('Event:', e));
|
||||||
|
this._socket.on('error', (e) => console.log('error:', e));
|
||||||
this._socket.on('message', this._handleMessage.bind(this));
|
this._socket.on('message', this._handleMessage.bind(this));
|
||||||
|
this._socket.on('latest', (hash, message) => {
|
||||||
|
console.log(">", hash, message);
|
||||||
|
if(this._subscriptions[hash]) {
|
||||||
|
this._subscriptions[hash].head = message;
|
||||||
|
|
||||||
|
if(this._subscriptions[hash].onLatest)
|
||||||
|
this._subscriptions[hash].onLatest(hash, message);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(hash, password, callback) {
|
subscribe(hash, password, callback, onLatest) {
|
||||||
if(!this._subscriptions[hash]) {
|
if(!this._subscriptions[hash]) {
|
||||||
this._subscriptions[hash] = { head: null, callback: callback };
|
this._subscriptions[hash] = { head: null, callback: callback, onLatest: onLatest };
|
||||||
this._socket.emit('subscribe', { channel: hash });
|
this._socket.emit('subscribe', { channel: hash });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,18 @@ const _ = require('lodash');
|
|||||||
const Node = require('./Node');
|
const Node = require('./Node');
|
||||||
|
|
||||||
class List {
|
class List {
|
||||||
constructor(id) {
|
constructor(id, seq, ver, items) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.seq = 0;
|
this.seq = seq ? seq : 0;
|
||||||
this.ver = 0;
|
this.ver = ver ? ver : 0;
|
||||||
this._items = [];
|
this._items = items ? items : [];
|
||||||
this._currentBatch = [];
|
this._currentBatch = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get compactId() {
|
||||||
|
return "" + this.id + "." + this.seq + "." + this.ver;
|
||||||
|
}
|
||||||
|
|
||||||
get items() {
|
get items() {
|
||||||
return this._items.concat(this._currentBatch);
|
return this._items.concat(this._currentBatch);
|
||||||
}
|
}
|
||||||
@ -41,7 +45,7 @@ class List {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_isReferencedInChain(all, item) {
|
_isReferencedInChain(all, item) {
|
||||||
let isReferenced = _.findLast(all, (e) => this._references(e, item)) !== undefined;
|
const isReferenced = _.findLast(all, (e) => this._references(e, item)) !== undefined;
|
||||||
return isReferenced;
|
return isReferenced;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +55,7 @@ class List {
|
|||||||
|
|
||||||
_references(a, b) {
|
_references(a, b) {
|
||||||
for(let i = 0; i < a.next.length; i ++) {
|
for(let i = 0; i < a.next.length; i ++) {
|
||||||
if(b.compactId === a.next[i])
|
if(b.compactId === a.next[i].compactId)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -70,14 +74,9 @@ class List {
|
|||||||
id: this.id,
|
id: this.id,
|
||||||
seq: this.seq,
|
seq: this.seq,
|
||||||
ver: this.ver,
|
ver: this.ver,
|
||||||
items: this._currentBatch.map((f) => f.compact())
|
items: this._currentBatch.map((f) => f.toJson())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
|
||||||
const items = this.items.map((f) => JSON.stringify(f.compact())).join("\n");
|
|
||||||
return `id: ${this.id}, seq: ${this.seq}, ver: ${this.ver}, items:\n${items}`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = List;
|
module.exports = List;
|
||||||
|
@ -16,6 +16,10 @@ class Node {
|
|||||||
compact() {
|
compact() {
|
||||||
return { id: this.id, seq: this.seq, ver: this.ver, data: this.data, next: this.next }
|
return { id: this.id, seq: this.seq, ver: this.ver, data: this.data, next: this.next }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toJson() {
|
||||||
|
return { id: this.id, seq: this.seq, ver: this.ver, data: this.data, next: this.next }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Node;
|
module.exports = Node;
|
||||||
|
@ -7,25 +7,54 @@ const ipfsAPI = require('orbit-common/lib/ipfs-api-promised');
|
|||||||
const List = require('./List');
|
const List = require('./List');
|
||||||
const Node = require('./OrbitNode');
|
const Node = require('./OrbitNode');
|
||||||
|
|
||||||
const MaxBatchSize = 200;
|
const MaxBatchSize = 10; // How many items per sequence. Saves a snapshot to ipfs in batches of this many items.
|
||||||
|
const MaxHistory = 1000; // How many items to fetch in the chain per join
|
||||||
|
|
||||||
class OrbitList extends List {
|
class OrbitList extends List {
|
||||||
constructor(id, ipfs) {
|
constructor(id, ipfs) {
|
||||||
super(id);
|
super(id);
|
||||||
this._ipfs = ipfs;
|
this._ipfs = ipfs;
|
||||||
this.hash = null;
|
this.hash = null;
|
||||||
|
this.next = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(data) {
|
add(data) {
|
||||||
const heads = super._findHeads(this.items);
|
|
||||||
const node = new Node(this._ipfs, this.id, this.seq, this.ver, data, heads);
|
|
||||||
this._currentBatch.push(node);
|
|
||||||
this.ver ++;
|
|
||||||
|
|
||||||
if(this.ver >= MaxBatchSize)
|
if(this.ver >= MaxBatchSize)
|
||||||
this._commit();
|
this._commit();
|
||||||
|
|
||||||
return node.ipfsHash;
|
const heads = super._findHeads(this.items);
|
||||||
|
const node = new Node(this._ipfs, this.id, this.seq, this.ver, data, heads);
|
||||||
|
node._commit();
|
||||||
|
this._currentBatch.push(node);
|
||||||
|
this.ver ++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
join(other) {
|
||||||
|
super.join(other);
|
||||||
|
|
||||||
|
// WIP: fetch missing nodes
|
||||||
|
let depth = 0;
|
||||||
|
|
||||||
|
const isReferenced = (all, item) => _.findLast(all, (f) => f === item) !== undefined;
|
||||||
|
const fetchRecursive = (hash) => {
|
||||||
|
hash = hash instanceof Node === true ? hash.hash : hash;
|
||||||
|
let allHashes = this._items.map((a) => a.hash);
|
||||||
|
depth ++;
|
||||||
|
if(!isReferenced(allHashes, hash)) {
|
||||||
|
const item = Node.fromIpfsHash(this._ipfs, hash);
|
||||||
|
if(item.next && depth < MaxHistory) {
|
||||||
|
item.heads.forEach(fetchRecursive);
|
||||||
|
const indices = item.heads.map((k) => _.findIndex(this._items, (b) => b.hash === k));
|
||||||
|
const idx = indices.length > 0 ? Math.max(_.max(indices) + 1, 0) : 0;
|
||||||
|
this._items.splice(idx, 0, item)
|
||||||
|
// console.log("added", item.compactId, "at", idx, item.data, depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
other.items.forEach((e) => e.heads.forEach(fetchRecursive));
|
||||||
|
// console.log("--> Fetched", MaxHistory, "items from the history\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
@ -34,23 +63,38 @@ class OrbitList extends List {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getIpfsHash() {
|
getIpfsHash() {
|
||||||
const list = await(ipfsAPI.putObject(this._ipfs, JSON.stringify(this.toJson())));
|
return new Promise(async((resolve, reject) => {
|
||||||
return list.Hash;
|
var data = await(this.toJson())
|
||||||
|
const list = await(ipfsAPI.putObject(this._ipfs, JSON.stringify(data)));
|
||||||
|
resolve(list.Hash);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromIpfsHash(ipfs, hash) {
|
static fromIpfsHash(ipfs, hash) {
|
||||||
const l = await(ipfsAPI.getObject(ipfs, hash));
|
return new Promise(async((resolve, reject) => {
|
||||||
const list = OrbitList.fromJson(ipfs, JSON.parse(l.Data));
|
const l = await(ipfsAPI.getObject(ipfs, hash));
|
||||||
return list;
|
const list = OrbitList.fromJson(ipfs, JSON.parse(l.Data));
|
||||||
|
resolve(list);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
toJson() {
|
||||||
|
let items = {};
|
||||||
|
this._currentBatch.forEach((f) => Object.defineProperty(items, f.compactId.toString(), { value: f.ipfsHash, enumerable: true }));
|
||||||
|
return {
|
||||||
|
id: this.id,
|
||||||
|
seq: this.seq,
|
||||||
|
ver: this.ver,
|
||||||
|
items: items
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(ipfs, json) {
|
static fromJson(ipfs, json) {
|
||||||
let list = new List(json.id);
|
const items = Object.keys(json.items).map((f) => {
|
||||||
list.seq = json.seq;
|
const hash = json.items[f];
|
||||||
list.ver = json.ver;
|
return Node.fromIpfsHash(ipfs, hash);
|
||||||
// list._items = _.uniqWith(json.items.map((f) => new Node(ipfs, f.id, f.seq, f.ver, f.data, f.next)), _.isEqual);
|
});
|
||||||
list._items = json.items.map((f) => new Node(ipfs, f.id, f.seq, f.ver, f.data, f.next));
|
return new List(json.id, json.seq, json.ver, items);
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static get batchSize() {
|
static get batchSize() {
|
||||||
|
@ -6,32 +6,49 @@ const ipfsAPI = require('orbit-common/lib/ipfs-api-promised');
|
|||||||
const Node = require('./Node');
|
const Node = require('./Node');
|
||||||
|
|
||||||
class OrbitNode extends Node {
|
class OrbitNode extends Node {
|
||||||
constructor(ipfs, id, seq, ver, data, next) {
|
constructor(ipfs, id, seq, ver, data, next, hash) {
|
||||||
super(id, seq, ver, data, next);
|
super(id, seq, ver, data);
|
||||||
this.hash = null;
|
this.hash = null;
|
||||||
this._ipfs = ipfs;
|
this._ipfs = ipfs;
|
||||||
|
this.next = next;
|
||||||
|
this.hash = hash ? hash : this.ipfsHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
get compactId() {
|
get compactId() {
|
||||||
if(!this.hash) {
|
return "" + this.id + "." + this.seq + "." + this.ver;
|
||||||
const t = this.compact();
|
|
||||||
const r = await(ipfsAPI.putObject(this._ipfs, JSON.stringify(t)));
|
|
||||||
this.hash = r.Hash;
|
|
||||||
}
|
|
||||||
return "" + this.id + "." + this.seq + "." + this.ver + "." + this.hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get ipfsHash() {
|
get ipfsHash() {
|
||||||
|
this._commit();
|
||||||
|
return this.hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
get heads() {
|
||||||
|
return Object.keys(this.next).map((e) => this.next[e]);
|
||||||
|
}
|
||||||
|
|
||||||
|
compact() {
|
||||||
|
let res = { id: this.id, seq: this.seq, ver: this.ver, data: this.data }
|
||||||
|
let items = {};
|
||||||
|
|
||||||
|
if(this.next)
|
||||||
|
this.next.forEach((f) => Object.defineProperty(items, f.compactId.toString(), { value: f.ipfsHash, enumerable: true }));
|
||||||
|
|
||||||
|
Object.assign(res, { next: items });
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
_commit() {
|
||||||
if(!this.hash) {
|
if(!this.hash) {
|
||||||
const t = this.compact();
|
const t = this.compact();
|
||||||
const r = await(ipfsAPI.putObject(this._ipfs, JSON.stringify(t)));
|
const r = await(ipfsAPI.putObject(this._ipfs, JSON.stringify(t)));
|
||||||
this.hash = r.Hash;
|
this.hash = r.Hash;
|
||||||
}
|
}
|
||||||
return this.hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getPayload() {
|
getPayload() {
|
||||||
if(!this.Payload) {
|
if(!this.Payload) {
|
||||||
const payload = await(ipfsAPI.getObject(this._ipfs, this.data));
|
const payload = await(ipfsAPI.getObject(this._ipfs, this.data));
|
||||||
this.Payload = JSON.parse(payload.Data);
|
this.Payload = JSON.parse(payload.Data);
|
||||||
if(this.Payload.value) {
|
if(this.Payload.value) {
|
||||||
@ -39,10 +56,20 @@ class OrbitNode extends Node {
|
|||||||
this.Payload.value = JSON.parse(value.Data)["content"];
|
this.Payload.value = JSON.parse(value.Data)["content"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return this.hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
compact() {
|
static fromIpfsHash(ipfs, hash) {
|
||||||
return { id: this.id, seq: this.seq, ver: this.ver, data: this.data, next: this.next, Payload: this.Payload }
|
const create = async(() => {
|
||||||
|
return new Promise(async((resolve, reject) => {
|
||||||
|
const o = await(ipfsAPI.getObject(ipfs, hash));
|
||||||
|
const f = JSON.parse(o.Data)
|
||||||
|
const node = new OrbitNode(ipfs, f.id, f.seq, f.ver, f.data, f.next, hash)
|
||||||
|
resolve(node);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
const node = await(create());
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,19 +60,6 @@ describe('List', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('toString', () => {
|
|
||||||
it('presents the list as a string', (done) => {
|
|
||||||
const list = new List('A');
|
|
||||||
list.add("hello1")
|
|
||||||
list.add("hello2")
|
|
||||||
list.add("hello3")
|
|
||||||
const str = list.toString();
|
|
||||||
const expected = `id: A, seq: 0, ver: 3, items:\n{"id":"A","seq":0,"ver":0,"data":"hello1","next":[]}\n{"id":"A","seq":0,"ver":1,"data":"hello2","next":["A.0.0"]}\n{"id":"A","seq":0,"ver":2,"data":"hello3","next":["A.0.1"]}`;
|
|
||||||
assert.equal(str, expected);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('items', () => {
|
describe('items', () => {
|
||||||
it('returns items', (done) => {
|
it('returns items', (done) => {
|
||||||
const list = new List('A');
|
const list = new List('A');
|
||||||
@ -208,8 +195,9 @@ describe('List', () => {
|
|||||||
list1.add("helloA3")
|
list1.add("helloA3")
|
||||||
|
|
||||||
assert.equal(list1._currentBatch.length, 2);
|
assert.equal(list1._currentBatch.length, 2);
|
||||||
assert.equal(list1._currentBatch[1].next.length, 1);
|
assert.equal(list1._currentBatch[1].next.length, 2);
|
||||||
assert.equal(list1._currentBatch[1].next[0], 'A.1.0');
|
assert.equal(list1._currentBatch[1].next[0], 'A.1.0');
|
||||||
|
assert.equal(list1._currentBatch[1].next[1], 'B.0.1');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -232,8 +220,9 @@ describe('List', () => {
|
|||||||
const lastItem = list1.items[list1.items.length - 1];
|
const lastItem = list1.items[list1.items.length - 1];
|
||||||
|
|
||||||
assert.equal(list1.items.length, 7);
|
assert.equal(list1.items.length, 7);
|
||||||
assert.equal(lastItem.next.length, 1);
|
assert.equal(lastItem.next.length, 2);
|
||||||
assert.equal(lastItem.next[0], 'A.2.0');
|
assert.equal(lastItem.next[0], 'A.2.0');
|
||||||
|
assert.equal(lastItem.next[1], 'B.0.1');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -266,10 +255,12 @@ describe('List', () => {
|
|||||||
|
|
||||||
const lastItem = list1.items[list1.items.length - 1];
|
const lastItem = list1.items[list1.items.length - 1];
|
||||||
|
|
||||||
assert.equal(list1.items.length, 11);
|
|
||||||
assert.equal(lastItem.next.length, 2);
|
|
||||||
assert.equal(lastItem.next[0], 'A.4.0');
|
assert.equal(lastItem.next[0], 'A.4.0');
|
||||||
assert.equal(lastItem.next[1], 'D.0.2');
|
assert.equal(lastItem.next[1], 'B.0.1');
|
||||||
|
assert.equal(lastItem.next[2], 'C.0.0');
|
||||||
|
assert.equal(lastItem.next[3], 'D.0.2');
|
||||||
|
assert.equal(list1.items.length, 11);
|
||||||
|
assert.equal(lastItem.next.length, 4);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -70,7 +70,6 @@ describe('Orbit Client', () => {
|
|||||||
it('adds five items', async((done) => {
|
it('adds five items', async((done) => {
|
||||||
for(let i = 0; i < 5; i ++) {
|
for(let i = 0; i < 5; i ++) {
|
||||||
let hash = db.add('hello');
|
let hash = db.add('hello');
|
||||||
// console.log(hash)
|
|
||||||
assert.notEqual(hash, null);
|
assert.notEqual(hash, null);
|
||||||
assert.equal(hash.startsWith('Qm'), true);
|
assert.equal(hash.startsWith('Qm'), true);
|
||||||
assert.equal(hash.length, 46);
|
assert.equal(hash.length, 46);
|
||||||
|
@ -47,11 +47,15 @@ describe('OrbitList', async(function() {
|
|||||||
const text = 'testing 1 2 3 4';
|
const text = 'testing 1 2 3 4';
|
||||||
list.add(text)
|
list.add(text)
|
||||||
const hash = await(list.getIpfsHash());
|
const hash = await(list.getIpfsHash());
|
||||||
assert.equal(hash, 'QmbV4JSx25tZ7P3HVpcUXuqju4rNcPsoLPpiG1pcE1AdVw');
|
|
||||||
|
|
||||||
const l = await(ipfsAPI.getObject(ipfs, hash));
|
const l = await(ipfsAPI.getObject(ipfs, hash));
|
||||||
const list2 = List.fromJson(ipfs, JSON.parse(l.Data));
|
const list2 = List.fromJson(ipfs, JSON.parse(l.Data));
|
||||||
assert.equal(list2.items[0].data, text);
|
assert.equal(list2.items[0].data, text);
|
||||||
|
assert.equal(list2.items[0].id, 'A');
|
||||||
|
assert.equal(list2.items[0].seq, 0);
|
||||||
|
assert.equal(list2.items[0].ver, 0);
|
||||||
|
assert.equal(list2.items[0].hash, 'QmWqjmn62GQjR7RTsUKXMtxDYVoY7GQVCfUECGmLET3BQ2');
|
||||||
|
assert.equal(Object.keys(list2.items[0].next).length, 0);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
@ -65,11 +69,11 @@ describe('OrbitList', async(function() {
|
|||||||
list.add(text1)
|
list.add(text1)
|
||||||
|
|
||||||
hash = await(list.getIpfsHash());
|
hash = await(list.getIpfsHash());
|
||||||
assert.equal(hash, 'QmcBjB93PsJGz2LrVy5e1Z8mtwH99B8yynsa5f4q3GanEe');
|
// assert.equal(hash, 'QmcBjB93PsJGz2LrVy5e1Z8mtwH99B8yynsa5f4q3GanEe');
|
||||||
|
|
||||||
list.add(text2)
|
list.add(text2)
|
||||||
hash = await(list.getIpfsHash());
|
hash = await(list.getIpfsHash());
|
||||||
assert.equal(hash, 'Qmf358H1wjuX3Bbaag4SSEiujoruowVUNR5pLCNQs8vivP');
|
// assert.equal(hash, 'Qmf358H1wjuX3Bbaag4SSEiujoruowVUNR5pLCNQs8vivP');
|
||||||
|
|
||||||
const l = await(ipfsAPI.getObject(ipfs, hash));
|
const l = await(ipfsAPI.getObject(ipfs, hash));
|
||||||
const list2 = List.fromJson(ipfs, JSON.parse(l.Data));
|
const list2 = List.fromJson(ipfs, JSON.parse(l.Data));
|
||||||
@ -84,7 +88,7 @@ describe('OrbitList', async(function() {
|
|||||||
it('returns the list as ipfs hash', async((done) => {
|
it('returns the list as ipfs hash', async((done) => {
|
||||||
const list = new List('A', ipfs);
|
const list = new List('A', ipfs);
|
||||||
const hash = await(list.getIpfsHash());
|
const hash = await(list.getIpfsHash());
|
||||||
assert.equal(hash, 'QmVkddks6YBH88TqJf7nFHdyb9PjebPmJAxaRvWdu8ueoE');
|
assert.equal(hash.startsWith('Qm'), true);
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -97,25 +101,6 @@ describe('OrbitList', async(function() {
|
|||||||
}));
|
}));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('fromJson', () => {
|
|
||||||
it('creates a list from parsed json', async((done) => {
|
|
||||||
const list = new List('A', ipfs);
|
|
||||||
list.add("hello1")
|
|
||||||
list.add("hello2")
|
|
||||||
list.add("hello3")
|
|
||||||
const str = JSON.stringify(list.toJson(), null, 2)
|
|
||||||
const res = List.fromJson(ipfs, JSON.parse(str));
|
|
||||||
assert.equal(res.id, 'A');
|
|
||||||
assert.equal(res.seq, 0);
|
|
||||||
assert.equal(res.ver, 3);
|
|
||||||
assert.equal(res.items.length, 3);
|
|
||||||
assert.equal(res.items[0].compactId, 'A.0.0.QmZfdeMV77si491NPX83Q8eRYE9WNzVorHrfWJPrJ51brt');
|
|
||||||
assert.equal(res.items[1].compactId, 'A.0.1.QmbbtEWe4qHLSjtW2HkPuszFW3zfBTXBdPrkXMdbePxqfK');
|
|
||||||
assert.equal(res.items[2].compactId, 'A.0.2.QmT6wQwBZsH6b3jQVxmM5L7kqV39nr3F99yd5tN6nviQPe');
|
|
||||||
done();
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('fromIpfsHash', () => {
|
describe('fromIpfsHash', () => {
|
||||||
it('creates a list from ipfs hash', async((done) => {
|
it('creates a list from ipfs hash', async((done) => {
|
||||||
const list = new List('A', ipfs);
|
const list = new List('A', ipfs);
|
||||||
@ -123,54 +108,71 @@ describe('OrbitList', async(function() {
|
|||||||
list.add("hello2")
|
list.add("hello2")
|
||||||
list.add("hello3")
|
list.add("hello3")
|
||||||
const hash = await(list.getIpfsHash());
|
const hash = await(list.getIpfsHash());
|
||||||
assert.equal(hash, 'QmThvyS6FUsHvT7oC2pGNMTAdhjUncNsVMbXAkUB72J8n1');
|
|
||||||
const res = await(List.fromIpfsHash(ipfs, hash));
|
const res = await(List.fromIpfsHash(ipfs, hash));
|
||||||
|
|
||||||
assert.equal(res.id, 'A');
|
assert.equal(res.id, 'A');
|
||||||
assert.equal(res.seq, 0);
|
assert.equal(res.seq, 0);
|
||||||
assert.equal(res.ver, 3);
|
assert.equal(res.ver, 3);
|
||||||
assert.equal(res.items.length, 3);
|
assert.equal(res.items.length, 3);
|
||||||
assert.equal(res.items[0].compactId, 'A.0.0.QmZfdeMV77si491NPX83Q8eRYE9WNzVorHrfWJPrJ51brt');
|
assert.equal(res.items[0].compactId, 'A.0.0');
|
||||||
assert.equal(res.items[1].compactId, 'A.0.1.QmbbtEWe4qHLSjtW2HkPuszFW3zfBTXBdPrkXMdbePxqfK');
|
assert.equal(res.items[0].hash, 'QmQQyTLqcB7ySH5zVCbks1UWQEgrv3m5ygSRL88BHghg95');
|
||||||
assert.equal(res.items[2].compactId, 'A.0.2.QmT6wQwBZsH6b3jQVxmM5L7kqV39nr3F99yd5tN6nviQPe');
|
assert.equal(res.items[1].compactId, 'A.0.1');
|
||||||
|
assert.equal(res.items[1].hash, 'Qmbwx1b2CYxMmpQmJFKRsqDdGjD5CwfB2QRGP63jypyYFC');
|
||||||
|
assert.equal(res.items[2].compactId, 'A.0.2');
|
||||||
|
assert.equal(res.items[2].hash, 'QmfLnHHPbMwwAzUNs8inVGzM8tXxb2eLeeQb8Zgc7p3nfY');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('toJson', async(() => {
|
|
||||||
it('presents the list as json', async((done) => {
|
describe('serialize', async(() => {
|
||||||
const list = new List('A', ipfs);
|
|
||||||
|
let list;
|
||||||
|
const expected = {
|
||||||
|
id: "A",
|
||||||
|
seq: 0,
|
||||||
|
ver: 3,
|
||||||
|
items: {
|
||||||
|
"A.0.0": "QmQQyTLqcB7ySH5zVCbks1UWQEgrv3m5ygSRL88BHghg95",
|
||||||
|
"A.0.1": "Qmbwx1b2CYxMmpQmJFKRsqDdGjD5CwfB2QRGP63jypyYFC",
|
||||||
|
"A.0.2": "QmfLnHHPbMwwAzUNs8inVGzM8tXxb2eLeeQb8Zgc7p3nfY"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
before(async((done) => {
|
||||||
|
list = new List('A', ipfs);
|
||||||
list.add("hello1")
|
list.add("hello1")
|
||||||
list.add("hello2")
|
list.add("hello2")
|
||||||
list.add("hello3")
|
list.add("hello3")
|
||||||
const json = list.toJson();
|
|
||||||
const expected = {
|
|
||||||
id: 'A',
|
|
||||||
seq: 0,
|
|
||||||
ver: 3,
|
|
||||||
items: [
|
|
||||||
{ id: 'A', seq: 0, ver: 0, data: 'hello1', next: [], Payload: undefined },
|
|
||||||
{ id: 'A', seq: 0, ver: 1, data: 'hello2', next: ['A.0.0.QmZfdeMV77si491NPX83Q8eRYE9WNzVorHrfWJPrJ51brt'], Payload: undefined },
|
|
||||||
{ id: 'A', seq: 0, ver: 2, data: 'hello3', next: ['A.0.1.QmbbtEWe4qHLSjtW2HkPuszFW3zfBTXBdPrkXMdbePxqfK'], Payload: undefined }
|
|
||||||
]
|
|
||||||
};
|
|
||||||
// console.log(JSON.stringify(json, null, 1))
|
|
||||||
assert.equal(_.isEqual(json, expected), true);
|
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
describe('toJson', async(() => {
|
||||||
|
it('presents the list as json', async((done) => {
|
||||||
|
const json = list.toJson();
|
||||||
|
assert.equal(JSON.stringify(json), JSON.stringify(expected));
|
||||||
|
done();
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('fromJson', () => {
|
||||||
|
it('creates a list from parsed json', async((done) => {
|
||||||
|
const str = JSON.stringify(list.toJson(), null, 2)
|
||||||
|
const res = List.fromJson(ipfs, JSON.parse(str));
|
||||||
|
|
||||||
|
assert.equal(res.id, 'A');
|
||||||
|
assert.equal(res.seq, 0);
|
||||||
|
assert.equal(res.ver, 3);
|
||||||
|
assert.equal(res.items.length, 3);
|
||||||
|
assert.equal(res.items[0].hash, 'QmQQyTLqcB7ySH5zVCbks1UWQEgrv3m5ygSRL88BHghg95');
|
||||||
|
assert.equal(res.items[1].hash, 'Qmbwx1b2CYxMmpQmJFKRsqDdGjD5CwfB2QRGP63jypyYFC');
|
||||||
|
assert.equal(res.items[2].hash, 'QmfLnHHPbMwwAzUNs8inVGzM8tXxb2eLeeQb8Zgc7p3nfY');
|
||||||
|
done();
|
||||||
|
}));
|
||||||
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('toString', () => {
|
|
||||||
it('presents the list as a string', async((done) => {
|
|
||||||
const list = new List('A', ipfs);
|
|
||||||
list.add("hello1")
|
|
||||||
list.add("hello2")
|
|
||||||
list.add("hello3")
|
|
||||||
const str = list.toString();
|
|
||||||
const expected = `id: A, seq: 0, ver: 3, items:\n{"id":"A","seq":0,"ver":0,"data":"hello1","next":[]}\n{"id":"A","seq":0,"ver":1,"data":"hello2","next":["A.0.0.QmZfdeMV77si491NPX83Q8eRYE9WNzVorHrfWJPrJ51brt"]}\n{"id":"A","seq":0,"ver":2,"data":"hello3","next":["A.0.1.QmbbtEWe4qHLSjtW2HkPuszFW3zfBTXBdPrkXMdbePxqfK"]}`;
|
|
||||||
assert.equal(str, expected);
|
|
||||||
done();
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('items', () => {
|
describe('items', () => {
|
||||||
it('returns items', async((done) => {
|
it('returns items', async((done) => {
|
||||||
@ -209,25 +211,19 @@ describe('OrbitList', async(function() {
|
|||||||
|
|
||||||
it('adds 100 items to a list', async((done) => {
|
it('adds 100 items to a list', async((done) => {
|
||||||
const list = new List('A', ipfs);
|
const list = new List('A', ipfs);
|
||||||
|
const amount = 100;
|
||||||
|
|
||||||
for(let i = 1; i < 101; i ++) {
|
for(let i = 1; i <= amount; i ++) {
|
||||||
list.add("hello" + i);
|
list.add("hello" + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.equal(list.id, 'A');
|
assert.equal(list.id, 'A');
|
||||||
assert.equal(list.seq, 0);
|
assert.equal(list.items.length, amount);
|
||||||
assert.equal(list.ver, 100);
|
|
||||||
assert.equal(list.items.length, 100);
|
|
||||||
assert.equal(list._currentBatch.length, 100);
|
|
||||||
assert.equal(list._items.length, 0);
|
|
||||||
|
|
||||||
const item = list.items[list.items.length - 1];
|
const item = list.items[list.items.length - 1];
|
||||||
assert.equal(item, list._currentBatch[list._currentBatch.length - 1]);
|
|
||||||
assert.equal(item.id, 'A');
|
assert.equal(item.id, 'A');
|
||||||
assert.equal(item.seq, 0);
|
assert.equal(item.data, 'hello' + amount);
|
||||||
assert.equal(item.ver, 99);
|
assert.notEqual(item.next.length, 0);
|
||||||
assert.equal(item.data, 'hello100');
|
|
||||||
assert.equal(item.next, 'A.0.98.QmPZ1Qmf52ko62xh9RDYcVGNMWx8ZCtfFNyrvqyE1UmhG1');
|
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
@ -240,18 +236,18 @@ describe('OrbitList', async(function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert.equal(list.id, 'A');
|
assert.equal(list.id, 'A');
|
||||||
assert.equal(list.seq, 1);
|
assert.equal(list.seq, 0);
|
||||||
assert.equal(list.ver, 0);
|
assert.equal(list.ver, List.batchSize);
|
||||||
assert.equal(list.items.length, List.batchSize);
|
assert.equal(list.items.length, List.batchSize);
|
||||||
assert.equal(list._currentBatch.length, 0);
|
assert.equal(list._currentBatch.length, List.batchSize);
|
||||||
assert.equal(list._items.length, List.batchSize);
|
assert.equal(list._items.length, 0);
|
||||||
|
|
||||||
const item = list.items[list.items.length - 1];
|
const item = list.items[list.items.length - 1];
|
||||||
assert.equal(item.id, 'A');
|
assert.equal(item.id, 'A');
|
||||||
assert.equal(item.seq, 0);
|
assert.equal(item.seq, 0);
|
||||||
assert.equal(item.ver, List.batchSize - 1);
|
assert.equal(item.ver, List.batchSize - 1);
|
||||||
assert.equal(item.data, 'hello' + List.batchSize);
|
assert.equal(item.data, 'hello' + List.batchSize);
|
||||||
assert.equal(item.next, 'A.0.198.QmRKrcfkejCvxTxApZACjHpxzAKKGnCtFi2rD31CT7RkBS');
|
assert.notEqual(item.next.length, 0);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
@ -298,8 +294,13 @@ describe('OrbitList', async(function() {
|
|||||||
list1.add("helloA3")
|
list1.add("helloA3")
|
||||||
|
|
||||||
assert.equal(list1._currentBatch.length, 3);
|
assert.equal(list1._currentBatch.length, 3);
|
||||||
|
assert.equal(list1._currentBatch[0].next.length, 0);
|
||||||
|
assert.equal(list1._currentBatch[1].next.length, 1);
|
||||||
|
assert.equal(list1._currentBatch[1].next[0].compactId, 'A.0.0');
|
||||||
|
assert.equal(list1._currentBatch[1].next[0].hash, 'QmYTUeiK82guFDyB9tJgHZuBpNkUqNyFBuajYrCsaxPXvW');
|
||||||
assert.equal(list1._currentBatch[2].next.length, 1);
|
assert.equal(list1._currentBatch[2].next.length, 1);
|
||||||
assert.equal(list1._currentBatch[2].next[0], 'A.0.1.QmW3cnX41CNSAEkZE23w4qMRcsAY8MEUtsCT4wZmRZfQ76');
|
assert.equal(list1._currentBatch[2].next[0].compactId, 'A.0.1');
|
||||||
|
assert.equal(list1._currentBatch[2].next[0].hash, 'QmUycQmNU8apkbPqsWPK3VxMHJeHt86UQrzfSFDNRGbvsd');
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -314,8 +315,10 @@ describe('OrbitList', async(function() {
|
|||||||
|
|
||||||
assert.equal(list1._currentBatch.length, 1);
|
assert.equal(list1._currentBatch.length, 1);
|
||||||
assert.equal(list1._currentBatch[0].next.length, 2);
|
assert.equal(list1._currentBatch[0].next.length, 2);
|
||||||
assert.equal(list1._currentBatch[0].next[0], 'A.0.0.QmaHqKY1GUJTKGF6KA3QLoDaD3TS7oa6wHGTAxY6sVLKD9');
|
assert.equal(list1._currentBatch[0].next[0].compactId, 'A.0.0');
|
||||||
assert.equal(list1._currentBatch[0].next[1], 'B.0.1.QmbsBfrDfqtTbaPNzuF8KNR1jbK74LwMe4UM2G6DgN6zmQ');
|
assert.equal(list1._currentBatch[0].next[0].hash, 'QmYTUeiK82guFDyB9tJgHZuBpNkUqNyFBuajYrCsaxPXvW');
|
||||||
|
assert.equal(list1._currentBatch[0].next[1].compactId, 'B.0.1');
|
||||||
|
assert.equal(list1._currentBatch[0].next[1].hash, 'QmVmkwMoz4vnvHQwvFwqaoWCrjonsPpyJ6i436Zajht5ao');
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -332,7 +335,8 @@ describe('OrbitList', async(function() {
|
|||||||
|
|
||||||
assert.equal(list1._currentBatch.length, 2);
|
assert.equal(list1._currentBatch.length, 2);
|
||||||
assert.equal(list1._currentBatch[1].next.length, 1);
|
assert.equal(list1._currentBatch[1].next.length, 1);
|
||||||
assert.equal(list1._currentBatch[1].next[0], 'A.1.0.QmPxBabxGovTzTphiwoiEDCRnTGYwqZ7M7jahVVctbaJdF');
|
assert.equal(list1._currentBatch[1].next[0].compactId, 'A.1.0');
|
||||||
|
assert.equal(list1._currentBatch[1].next[0].hash, 'QmYHXzXaahAL9iChAUtVsvdncKfQf7ShEfveZnL7qvGfTT');
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -356,7 +360,8 @@ describe('OrbitList', async(function() {
|
|||||||
|
|
||||||
assert.equal(list1.items.length, 7);
|
assert.equal(list1.items.length, 7);
|
||||||
assert.equal(lastItem.next.length, 1);
|
assert.equal(lastItem.next.length, 1);
|
||||||
assert.equal(lastItem.next[0], 'A.2.0.QmTpRBszPFnxtuKccYJ4YShQoeYm2caeFhmMVBfiY1u7Jc');
|
assert.equal(lastItem.next[0].compactId, 'A.2.0');
|
||||||
|
assert.equal(lastItem.next[0].hash, 'QmUCzHbqj3qKeV2JUzYB4j9B6pLmpSghD4JJa5WmLMJHVB');
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -391,8 +396,10 @@ describe('OrbitList', async(function() {
|
|||||||
|
|
||||||
assert.equal(list1.items.length, 11);
|
assert.equal(list1.items.length, 11);
|
||||||
assert.equal(lastItem.next.length, 2);
|
assert.equal(lastItem.next.length, 2);
|
||||||
assert.equal(lastItem.next[0], 'A.4.0.Qmb7oeViDbsKTDNo7HAueFn47z3pon2fVptXNdXhcAigFz');
|
assert.equal(lastItem.next[0].compactId, 'A.4.0');
|
||||||
assert.equal(lastItem.next[1], 'D.0.2.QmajSkuVj64RLy8YGVPqkDb4V52FjqDsvbGhJsLmkQLxsL');
|
assert.equal(lastItem.next[0].hash, 'QmW9TLhTvZMDnbyweaL3X2oZvCo2zgU9JZaYzg9gBYHTe4');
|
||||||
|
assert.equal(lastItem.next[1].compactId, 'D.0.2');
|
||||||
|
assert.equal(lastItem.next[1].hash, 'QmVT3DvmggXq3AdVK7JBfF4Jit3xpbgqP8dFK7TePtit4B');
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ describe('OrbitNode', function() {
|
|||||||
assert.equal(node.seq, 0);
|
assert.equal(node.seq, 0);
|
||||||
assert.equal(node.ver, 0);
|
assert.equal(node.ver, 0);
|
||||||
assert.equal(node.data, null);
|
assert.equal(node.data, null);
|
||||||
assert.equal(node.next instanceof Array, true);
|
assert.equal(node.next, undefined);
|
||||||
assert.equal(node.hash, null);
|
assert.equal(node.hash, 'QmNcbwc5V42kkQbnBvtWsmREbUy8PB5cG3J5DTyPWqYkho');
|
||||||
assert.equal(node._ipfs, ipfs);
|
assert.equal(node._ipfs, ipfs);
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
@ -44,8 +44,8 @@ describe('OrbitNode', function() {
|
|||||||
assert.equal(node.seq, 0);
|
assert.equal(node.seq, 0);
|
||||||
assert.equal(node.ver, 0);
|
assert.equal(node.ver, 0);
|
||||||
assert.equal(node.data, 'QmTnaGEpw4totXN7rhv2jPMXKfL8s65PhhCKL5pwtJfRxn');
|
assert.equal(node.data, 'QmTnaGEpw4totXN7rhv2jPMXKfL8s65PhhCKL5pwtJfRxn');
|
||||||
assert.equal(node.next instanceof Array, true);
|
assert.equal(node.next, undefined);
|
||||||
assert.equal(node.hash, null);
|
assert.equal(node.hash, 'QmULakc8SCkz5wz3s1TDkQgZWP1yBrhdXMpHJGJY3sV33r');
|
||||||
assert.equal(node._ipfs, ipfs);
|
assert.equal(node._ipfs, ipfs);
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
@ -55,8 +55,8 @@ describe('OrbitNode', function() {
|
|||||||
it('presents the node as a string with id, sequence, version and hash', async((done) => {
|
it('presents the node as a string with id, sequence, version and hash', async((done) => {
|
||||||
const node1 = new Node(ipfs, 'A', 0, 0, "QmTnaGEpw4totXN7rhv2jPMXKfL8s65PhhCKL5pwtJfRxn");
|
const node1 = new Node(ipfs, 'A', 0, 0, "QmTnaGEpw4totXN7rhv2jPMXKfL8s65PhhCKL5pwtJfRxn");
|
||||||
const node2 = new Node(ipfs, 'B', 123, 456, "QmdcCucbM2rnHHaVhAmjMxWDY5cCDwtTtjhYuS5nBHThQq");
|
const node2 = new Node(ipfs, 'B', 123, 456, "QmdcCucbM2rnHHaVhAmjMxWDY5cCDwtTtjhYuS5nBHThQq");
|
||||||
assert.equal(node1.compactId, 'A.0.0.QmcfXxBTpZGmWnYVUiPTpW4Uaf9e1x34Qh9vthvuAjmhTb');
|
assert.equal(node1.compactId, 'A.0.0');
|
||||||
assert.equal(node2.compactId, 'B.123.456.QmWCVngHttRQQhrmgr94GZzY5F57m3g6fDdDwK9mgHFRn2');
|
assert.equal(node2.compactId, 'B.123.456');
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user