mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-10-07 22:57:07 +00:00
Refactor OrbitClient and Pubsub to use Lists
This commit is contained in:
parent
3863150624
commit
8caf8cbb9a
52
examples/pubsubKeyValue.js
Normal file
52
examples/pubsubKeyValue.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var async = require('asyncawait/async');
|
||||||
|
var await = require('asyncawait/await');
|
||||||
|
var OrbitClient = require('../src/OrbitClient');
|
||||||
|
var Timer = require('./Timer');
|
||||||
|
|
||||||
|
// var host = '178.62.229.175';
|
||||||
|
var host = 'localhost';
|
||||||
|
var port = 6379;
|
||||||
|
|
||||||
|
var username = 'LambOfGod';
|
||||||
|
var password = '';
|
||||||
|
|
||||||
|
let run = (async(() => {
|
||||||
|
try {
|
||||||
|
var orbit = OrbitClient.connect(host, port, username, password);
|
||||||
|
const c1 = 'c1';
|
||||||
|
const channel = orbit.channel(c1);
|
||||||
|
|
||||||
|
let count = 1;
|
||||||
|
let id = 'Log: Query '
|
||||||
|
let running = false;
|
||||||
|
|
||||||
|
setInterval(async(() => {
|
||||||
|
if(!running) {
|
||||||
|
running = true;
|
||||||
|
|
||||||
|
// let timer = new Timer(true);
|
||||||
|
channel.put("lamb", "of god" + count);
|
||||||
|
// console.log(`Query #${count} took ${timer.stop(true)} ms\n`);
|
||||||
|
let v = channel.get("lamb");
|
||||||
|
|
||||||
|
console.log("---------------------------------------------------")
|
||||||
|
console.log("Id | Seq | Ver | Data")
|
||||||
|
console.log("---------------------------------------------------")
|
||||||
|
console.log(v);
|
||||||
|
console.log("---------------------------------------------------")
|
||||||
|
|
||||||
|
running = false;
|
||||||
|
count ++;
|
||||||
|
}
|
||||||
|
}), 500);
|
||||||
|
|
||||||
|
} catch(e) {
|
||||||
|
console.error("error:", e);
|
||||||
|
console.error(e.stack);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}))();
|
||||||
|
|
||||||
|
module.exports = run;
|
@ -27,16 +27,18 @@ let run = (async(() => {
|
|||||||
running = true;
|
running = true;
|
||||||
|
|
||||||
// let timer = new Timer(true);
|
// let timer = new Timer(true);
|
||||||
channel.add(id + count);
|
channel.add("Hello " + count);
|
||||||
// console.log(`Query #${count} took ${timer.stop(true)} ms\n`);
|
// console.log(`Query #${count} took ${timer.stop(true)} ms\n`);
|
||||||
|
|
||||||
// console.log("Query...");
|
|
||||||
const c = channel.iterator({ limit: -1 }).collect().length;
|
const c = channel.iterator({ limit: -1 }).collect().length;
|
||||||
let items = channel.iterator({ limit: 5 }).collect();
|
let items = channel.iterator({ limit: 5 }).collect();
|
||||||
|
// console.log(items);
|
||||||
console.log("---------------------------------------------------")
|
console.log("---------------------------------------------------")
|
||||||
console.log("Id | Seq | Ver | Data")
|
// console.log("Id | Seq | Ver | Data")
|
||||||
|
console.log("Key | Value")
|
||||||
console.log("---------------------------------------------------")
|
console.log("---------------------------------------------------")
|
||||||
console.log(items.map((e) => `${e.id} | ${e.seq} | ${e.ver} | ${e.data}`).join("\n"));
|
// console.log(items.map((e) => `${e.id} | ${e.seq} | ${e.ver} | ${e.data}`).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`);
|
||||||
|
|
||||||
|
@ -16,14 +16,14 @@ 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 = 'c1';
|
||||||
|
let channel;
|
||||||
|
|
||||||
let count = 1;
|
let count = 1;
|
||||||
let id = 'Log: Query '
|
let id = 'Log: Query '
|
||||||
let channel;
|
|
||||||
|
|
||||||
setInterval(async(() => {
|
setInterval(async(() => {
|
||||||
if(channel) {
|
if(channel) {
|
||||||
channel.add(id + count);
|
channel.add(username + " " + count);
|
||||||
count ++;
|
count ++;
|
||||||
}
|
}
|
||||||
}), process.argv[3] ? process.argv[3] : 1000);
|
}), process.argv[3] ? process.argv[3] : 1000);
|
||||||
|
102
src/DataStore.js
Normal file
102
src/DataStore.js
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
|
const async = require('asyncawait/async');
|
||||||
|
const await = require('asyncawait/await');
|
||||||
|
const ipfsAPI = require('orbit-common/lib/ipfs-api-promised');
|
||||||
|
const OrbitList = require('./list/OrbitList');
|
||||||
|
const HashCacheOps = require('./HashCacheOps');
|
||||||
|
|
||||||
|
const DefaultAmount = 1;
|
||||||
|
|
||||||
|
class DataStore {
|
||||||
|
constructor(id, ipfs) {
|
||||||
|
this._ipfs = ipfs;
|
||||||
|
this.list = new OrbitList(id, this._ipfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
add(hash) {
|
||||||
|
this.list.add(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
join(other) {
|
||||||
|
this.list.join(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.list.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
get(options) {
|
||||||
|
return this._fetchRecursive(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
_fetchOne(index) {
|
||||||
|
const item = this.list.items[this.list.items.length - index - 1];
|
||||||
|
if(item) {
|
||||||
|
await(item.getPayload());
|
||||||
|
const f = item.compact();
|
||||||
|
return { hash: f.data, payload: f.Payload };
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_fetchRecursive(options, currentAmount, deleted, res) {
|
||||||
|
// console.log("-->")
|
||||||
|
// console.log("opts:", options, currentAmount)
|
||||||
|
const opts = {
|
||||||
|
amount: options && options.amount ? options.amount : DefaultAmount,
|
||||||
|
first: options && options.first ? options.first : null,
|
||||||
|
last: options && options.last ? options.last : null,
|
||||||
|
key: options && options.key ? options.key : null
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = res ? res : [];
|
||||||
|
let handledItems = deleted ? deleted : [];
|
||||||
|
|
||||||
|
if(!currentAmount) currentAmount = 0;
|
||||||
|
|
||||||
|
const item = this._fetchOne(currentAmount);
|
||||||
|
// console.log("ITEM", item)
|
||||||
|
|
||||||
|
if(item && item.payload) {
|
||||||
|
const wasHandled = _.includes(handledItems, item.payload.key);
|
||||||
|
if((item.payload.op === HashCacheOps.Put || item.payload.op === HashCacheOps.Add) && !wasHandled) {
|
||||||
|
if((!opts.key || (opts.key && opts.key === item.payload.key)) &&
|
||||||
|
(!opts.first || (opts.first && (opts.first === item.payload.key && result.length === 0))
|
||||||
|
|| (opts.first && (opts.first !== item.payload.key && result.length > 0))))
|
||||||
|
{
|
||||||
|
// console.log("PUSH!", item, currentAmount, result.length);
|
||||||
|
result.push(item);
|
||||||
|
handledItems.push(item.payload.key);
|
||||||
|
}
|
||||||
|
} else if(item.payload.op === HashCacheOps.Delete) {
|
||||||
|
// console.log("DELETE!", item);
|
||||||
|
handledItems.push(item.payload.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentAmount ++;
|
||||||
|
|
||||||
|
if(opts.key && item.payload.key === opts.key)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// console.log("ITEM", item.payload.key, opts.last)
|
||||||
|
if(opts.last && item.payload.key === opts.last)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if(!opts.last && opts.amount > -1 && result.length >= opts.amount)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if(currentAmount >= this.list.items.length)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// console.log("RES!", result)
|
||||||
|
result = this._fetchRecursive(opts, currentAmount, handledItems, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DataStore;
|
@ -2,6 +2,15 @@
|
|||||||
|
|
||||||
const Encryption = require('orbit-common/lib/Encryption');
|
const Encryption = require('orbit-common/lib/Encryption');
|
||||||
|
|
||||||
|
class OrbitDBItem {
|
||||||
|
constructor(operation, key, value, metaInfo) {
|
||||||
|
this.op = operation;
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
this.meta = metaInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class HashCacheItem {
|
class HashCacheItem {
|
||||||
constructor(operation, key, sequenceNumber, targetHash, metaInfo, next) {
|
constructor(operation, key, sequenceNumber, targetHash, metaInfo, next) {
|
||||||
this.op = operation;
|
this.op = operation;
|
||||||
@ -55,6 +64,7 @@ class EncryptedHashCacheItem extends HashCacheItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
OrbitDBItem: OrbitDBItem,
|
||||||
HashCacheItem: HashCacheItem,
|
HashCacheItem: HashCacheItem,
|
||||||
EncryptedHashCacheItem: EncryptedHashCacheItem
|
EncryptedHashCacheItem: EncryptedHashCacheItem
|
||||||
};
|
};
|
||||||
|
@ -6,56 +6,54 @@ var Keystore = require('orbit-common/lib/Keystore');
|
|||||||
var Encryption = require('orbit-common/lib/Encryption');
|
var Encryption = require('orbit-common/lib/Encryption');
|
||||||
var ipfsDaemon = require('orbit-common/lib/ipfs-daemon');
|
var ipfsDaemon = require('orbit-common/lib/ipfs-daemon');
|
||||||
var ipfsAPI = require('orbit-common/lib/ipfs-api-promised');
|
var ipfsAPI = require('orbit-common/lib/ipfs-api-promised');
|
||||||
var HashCache = require('./HashCacheClient');
|
var HashCacheItem = require('./HashCacheItem').HashCacheItem;
|
||||||
var HashCacheItem = require('./HashCacheItem').EncryptedHashCacheItem;
|
var OrbitDBItem = require('./HashCacheItem').OrbitDBItem;
|
||||||
var HashCacheOps = require('./HashCacheOps');
|
var HashCacheOps = require('./HashCacheOps');
|
||||||
var ItemTypes = require('./ItemTypes');
|
var ItemTypes = require('./ItemTypes');
|
||||||
var MetaInfo = require('./MetaInfo');
|
var MetaInfo = require('./MetaInfo');
|
||||||
var Post = require('./Post');
|
var Post = require('./Post');
|
||||||
var Aggregator = require('./Aggregator');
|
var Aggregator = require('./Aggregator');
|
||||||
var PubSub = require('./PubSub');
|
var PubSub = require('./PubSub');
|
||||||
const List = require('./list/OrbitList');
|
|
||||||
var Timer = require('../examples/Timer');
|
var Timer = require('../examples/Timer');
|
||||||
|
const List = require('./list/OrbitList');
|
||||||
|
const DataStore = require('./DataStore');
|
||||||
|
|
||||||
var pubkey = Keystore.getKeys().publicKey;
|
var pubkey = Keystore.getKeys().publicKey;
|
||||||
var privkey = Keystore.getKeys().privateKey;
|
var privkey = Keystore.getKeys().privateKey;
|
||||||
|
|
||||||
let vvv = {};
|
|
||||||
|
|
||||||
class OrbitClient {
|
class OrbitClient {
|
||||||
constructor(ipfs) {
|
constructor(ipfs) {
|
||||||
this.ipfs = ipfs;
|
this._ipfs = ipfs;
|
||||||
this.network = {};
|
this.network = {};
|
||||||
this.user = null;
|
this.user = null;
|
||||||
this.list = null; // TODO move to DataStore
|
|
||||||
}
|
}
|
||||||
|
|
||||||
channel(hash, password) {
|
channel(hash, password) {
|
||||||
if(password === undefined) password = '';
|
if(password === undefined) password = '';
|
||||||
|
|
||||||
this._pubsub.subscribe(hash, password, async((hash, message) => {
|
this._pubsub.subscribe(hash, password, async((hash, message) => {
|
||||||
const other = await(List.fromIpfsHash(this.ipfs, message));
|
const other = await(List.fromIpfsHash(this._ipfs, message));
|
||||||
// console.log(">", other.id, other.seq, other.ver);
|
// console.log(">", other.id, other.seq, other.ver);
|
||||||
if(other.id !== this.user.username) {
|
if(other.id !== this.user.username) {
|
||||||
let timer = new Timer(true);
|
// let timer = new Timer(true);
|
||||||
this.list.join(other); // TODO: move to DataStore
|
this._store.join(other);
|
||||||
console.log(`Join took ${timer.stop(true)} ms`);
|
// console.log(`Join took ${timer.stop(true)} ms`);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
info: (options) => this._info(hash, password),
|
// info: (options) => this._info(hash, password),
|
||||||
delete: () => this._deleteChannel(hash, password),
|
delete: () => this._deleteChannel(hash, password),
|
||||||
iterator: (options) => this._iterator(hash, password, options),
|
iterator: (options) => this._iterator(hash, password, options),
|
||||||
setMode: (mode) => this._setMode(hash, password, mode),
|
setMode: (mode) => this._setMode(hash, password, mode),
|
||||||
add: (data) => this._add(hash, password, data),
|
add: (data) => this._add(hash, password, data),
|
||||||
//TODO: tests
|
del: (key) => this._remove(hash, password, key),
|
||||||
del: (options) => this._remove(hash, password, options),
|
|
||||||
put: (key, data) => this._put(hash, password, key, data),
|
put: (key, data) => this._put(hash, password, key, data),
|
||||||
get: (key, options) => {
|
get: (key, options) => {
|
||||||
const items = this._iterator(hash, password, { key: key }).collect();
|
const items = this._iterator(hash, password, { key: key }).collect();
|
||||||
return items[0] ? items[0].item.Payload : null;
|
return items[0] ? items[0].payload.value : null;
|
||||||
},
|
},
|
||||||
|
//TODO: tests
|
||||||
leave: () => this._pubsub.unsubscribe(hash)
|
leave: () => this._pubsub.unsubscribe(hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,72 +93,45 @@ class OrbitClient {
|
|||||||
const reverse = options.reverse ? options.reverse : false;
|
const reverse = options.reverse ? options.reverse : false;
|
||||||
const key = options.key ? options.key : null;
|
const key = options.key ? options.key : null;
|
||||||
|
|
||||||
let startFromHash;
|
|
||||||
if(lte || lt) {
|
|
||||||
startFromHash = lte ? lte : lt;
|
|
||||||
} else {
|
|
||||||
var channel = this._info(channel, password);
|
|
||||||
startFromHash = channel.head ? channel.head : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((gt || lt) && limit > -1) limit += 1;
|
if((gt || lt) && limit > -1) limit += 1;
|
||||||
|
|
||||||
if(startFromHash) {
|
|
||||||
const opts = {
|
const opts = {
|
||||||
amount: limit,
|
amount: limit,
|
||||||
|
first: lte ? lte : lt,
|
||||||
last: gte ? gte : gt,
|
last: gte ? gte : gt,
|
||||||
key: key
|
key: key
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get messages
|
// Get messages
|
||||||
// messages = Aggregator.fetchRecursive(this.ipfs, startFromHash, password, opts);
|
messages = await(this._store.get(opts));
|
||||||
messages = this.list.items.map((f) => f.compact()); // TODO: move to DataStore
|
// console.log("M", messages)
|
||||||
|
|
||||||
// Slice the array
|
|
||||||
let startIndex = 0;
|
|
||||||
let endIndex = messages.length;
|
|
||||||
if(limit < 0) {
|
|
||||||
endIndex = messages.length - (gt ? 1 : 0);
|
|
||||||
} else {
|
|
||||||
startIndex = Math.max(0, messages.length - limit);
|
|
||||||
endIndex = messages.length - ((gt || lt) ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Remove the first/last item if greater/lesser than is set
|
||||||
|
let startIndex = lt ? 1 : 0;
|
||||||
|
let endIndex = gt ? messages.length - 1 : messages.length;
|
||||||
messages = messages.slice(startIndex, endIndex)
|
messages = messages.slice(startIndex, endIndex)
|
||||||
}
|
// console.log("M2", messages)
|
||||||
|
|
||||||
if(reverse) messages.reverse();
|
if(!reverse) messages.reverse();
|
||||||
|
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
_publish(data) {
|
_publish(data) {
|
||||||
let post = new Post(data);
|
let post = new Post(data);
|
||||||
post.encrypt(privkey, pubkey);
|
// post.encrypt(privkey, pubkey);
|
||||||
return await (ipfsAPI.putObject(this.ipfs, JSON.stringify(post)));
|
return await (ipfsAPI.putObject(this._ipfs, JSON.stringify(post)));
|
||||||
}
|
}
|
||||||
|
|
||||||
_createMessage(channel, password, operation, key, target) {
|
_createMessage(channel, password, operation, key, value) {
|
||||||
// Create meta info
|
// Create meta info
|
||||||
const size = -1;
|
const size = -1;
|
||||||
const metaInfo = new MetaInfo(ItemTypes.Message, size, this.user.id, new Date().getTime());
|
const metaInfo = new MetaInfo(ItemTypes.Message, size, this.user.id, new Date().getTime());
|
||||||
|
|
||||||
// Get the current channel head and bump the sequence number
|
|
||||||
let seq = this._info(channel, password).seq + 1;
|
|
||||||
let head = this._info(channel, password).head;
|
|
||||||
|
|
||||||
// Create the hash cache item
|
// Create the hash cache item
|
||||||
const hcItem = new HashCacheItem(operation, key, seq, target, metaInfo, null, pubkey, privkey, password);
|
const item = new OrbitDBItem(operation, key, value, metaInfo);
|
||||||
|
|
||||||
// Save the item to ipfs
|
// Save the item to ipfs
|
||||||
const data = await (ipfsAPI.putObject(this.ipfs, JSON.stringify(hcItem)));
|
const data = await (ipfsAPI.putObject(this._ipfs, JSON.stringify(item)));
|
||||||
let newHead = { Hash: data.Hash };
|
return data.Hash;
|
||||||
|
|
||||||
// If this is not the first item in the channel, patch with the previous (ie. link as next)
|
|
||||||
if(seq > 0)
|
|
||||||
newHead = await (ipfsAPI.patchObject(this.ipfs, data.Hash, head));
|
|
||||||
|
|
||||||
return { hash: newHead, seq: seq };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DB Operations */
|
/* DB Operations */
|
||||||
@ -175,48 +146,46 @@ class OrbitClient {
|
|||||||
return await(this._createOperation(channel, password, HashCacheOps.Put, key, post.Hash));
|
return await(this._createOperation(channel, password, HashCacheOps.Put, key, post.Hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
_remove(channel, password, options) {
|
_remove(channel, password, hash) {
|
||||||
const key = null;
|
return await(this._createOperation(channel, password, HashCacheOps.Delete, hash, null));
|
||||||
const target = options.key ? options.key : (options.hash ? options.hash : null);
|
|
||||||
return await(this._createOperation(channel, password, HashCacheOps.Delete, key, target));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_createOperation(channel, password, operation, key, value, data) {
|
_createOperation(channel, password, operation, key, value, data) {
|
||||||
let message = this._createMessage(channel, password, operation, key, value);
|
let hash = this._createMessage(channel, password, operation, key, value);
|
||||||
this.list.add(message.hash.Hash); // TODO: move to DataStore
|
this._store.add(hash);
|
||||||
const listHash = await(this.list.getIpfsHash());
|
const listHash = await(this._store.list.getIpfsHash());
|
||||||
await(this._pubsub.publish(channel, listHash));
|
await(this._pubsub.publish(channel, listHash));
|
||||||
return message.hash.Hash;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
_deleteChannel(channel, password) {
|
_deleteChannel(channel, password) {
|
||||||
this._pubsub.delete(channel, password);
|
this._store.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_setMode(channel, password, modes) {
|
// _setMode(channel, password, modes) {
|
||||||
let m = [];
|
// let m = [];
|
||||||
if(typeof modes !== 'Array')
|
// if(typeof modes !== 'Array')
|
||||||
m.push(modes);
|
// m.push(modes);
|
||||||
else
|
// else
|
||||||
m = modes;
|
// m = modes;
|
||||||
// const res = await(this.client.linkedList(channel, password).setMode(m));
|
// // const res = await(this.client.linkedList(channel, password).setMode(m));
|
||||||
// return res.modes;
|
// // return res.modes;
|
||||||
return { todo: 'TODO!' }
|
// return { todo: 'TODO!' }
|
||||||
}
|
// }
|
||||||
|
|
||||||
_info(channel, password) {
|
// _info(channel, password) {
|
||||||
var l = this._pubsub.latest(channel);
|
// var l = this._pubsub.latest(channel);
|
||||||
return l;
|
// return l;
|
||||||
}
|
// }
|
||||||
|
|
||||||
_connect(host, port, username, password) {
|
_connect(host, port, username, password) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this._pubsub = new PubSub(this.ipfs, host, port, username, password);
|
this._pubsub = new PubSub(this._ipfs, host, port, username, password);
|
||||||
// this.client = this._pubsub._client;
|
// this.client = this._pubsub._client;
|
||||||
// this.user = this.client.info.user;
|
// this.user = this.client.info.user;
|
||||||
this.user = { id: 'hello-todo', username: username }
|
this.user = { id: 'hello-todo', username: username }
|
||||||
this.list = new List(username, this.ipfs); // TODO: move to DataStore
|
this._store = new DataStore(username, this._ipfs);
|
||||||
resolve();
|
resolve();
|
||||||
// this.network = {
|
// this.network = {
|
||||||
// id: this.client.info.networkId,
|
// id: this.client.info.networkId,
|
||||||
|
140
src/PubSub.js
140
src/PubSub.js
@ -1,9 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var async = require('asyncawait/async');
|
const redis = require("redis");
|
||||||
var await = require('asyncawait/await');
|
|
||||||
var redis = require("redis");
|
|
||||||
var Aggregator = require('./Aggregator');
|
|
||||||
const List = require('./list/OrbitList');
|
const List = require('./list/OrbitList');
|
||||||
|
|
||||||
class Pubsub2 {
|
class Pubsub2 {
|
||||||
@ -13,17 +10,13 @@ class Pubsub2 {
|
|||||||
this.client1 = redis.createClient({ host: host, port: port });
|
this.client1 = redis.createClient({ host: host, port: port });
|
||||||
this.client2 = redis.createClient({ host: host, port: port });
|
this.client2 = redis.createClient({ host: host, port: port });
|
||||||
this.client1.on("message", this._handleMessage.bind(this));
|
this.client1.on("message", this._handleMessage.bind(this));
|
||||||
this.client1.on('connect', () => {
|
// this.client1.on('connect', () => console.log('redis connected'));
|
||||||
console.log('redis connected');
|
// this.client1.on("subscribe", (channel, count) => console.log(`subscribed to ${channel}`));
|
||||||
});
|
|
||||||
// this.client1.on("subscribe", (channel, count) => {
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(hash, password, callback) {
|
subscribe(hash, password, callback) {
|
||||||
if(!this._subscriptions[hash] || this._subscriptions[hash].password !== password) {
|
if(!this._subscriptions[hash] || this._subscriptions[hash].password !== password) {
|
||||||
this._subscriptions[hash] = {
|
this._subscriptions[hash] = {
|
||||||
topic: hash,
|
|
||||||
password: password,
|
password: password,
|
||||||
head: null,
|
head: null,
|
||||||
callback: callback
|
callback: callback
|
||||||
@ -46,10 +39,6 @@ class Pubsub2 {
|
|||||||
return { head: this._subscriptions[hash] ? this._subscriptions[hash].head : null };
|
return { head: this._subscriptions[hash] ? this._subscriptions[hash].head : null };
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(hash, password) {
|
|
||||||
delete this._subscriptions[hash];
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleMessage(hash, message) {
|
_handleMessage(hash, message) {
|
||||||
if(this._subscriptions[hash]) {
|
if(this._subscriptions[hash]) {
|
||||||
this._subscriptions[hash].head = message;
|
this._subscriptions[hash].head = message;
|
||||||
@ -60,127 +49,4 @@ class Pubsub2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
class PubSub {
|
|
||||||
constructor(ipfs, host, port, username, password, resolve) {
|
|
||||||
this.ipfs = ipfs;
|
|
||||||
this._subscriptions = {};
|
|
||||||
this.client1 = redis.createClient({ host: host, port: port });
|
|
||||||
this.client2 = redis.createClient({ host: host, port: port });
|
|
||||||
this.client3 = redis.createClient({ host: host, port: port });
|
|
||||||
this.client1.on("message", this._handleMessage.bind(this));
|
|
||||||
this.publishQueue = [];
|
|
||||||
|
|
||||||
this.client1.on('connect', function() {
|
|
||||||
console.log('redis connected');
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.client1.on("subscribe", function (channel, count) {
|
|
||||||
console.log("subscribed to pubsub topic '" + channel + "' (" + count + " peers)");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
subscribe(hash, password, head, callback) {
|
|
||||||
if(!this._subscriptions[hash] || this._subscriptions[hash].password !== password) {
|
|
||||||
this._subscriptions[hash] = {
|
|
||||||
topic: hash,
|
|
||||||
password: password,
|
|
||||||
head: null,
|
|
||||||
callback: callback,
|
|
||||||
seq: -1
|
|
||||||
};
|
|
||||||
// this.client3.get("orbit." + hash, (err, reply) => {
|
|
||||||
// if(reply) {
|
|
||||||
// let d = JSON.parse(reply);
|
|
||||||
// this._subscriptions[hash].seq = d.seq;
|
|
||||||
// this._subscriptions[hash].head = d.head;
|
|
||||||
// if(err) console.log(err);
|
|
||||||
// console.log(`head of '${hash}' is`, this._subscriptions[hash].head, "seq:", this._subscriptions[hash].seq);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
this.client1.subscribe(hash);
|
|
||||||
this.client2.publish(hash, JSON.stringify({ r: "HEAD" }));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
console.log("pubsub initialized")
|
|
||||||
resolve();
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
unsubscribe(hash) {
|
|
||||||
delete this._subscriptions[hash];
|
|
||||||
this.client1.unsubscribe();
|
|
||||||
this.client2.unsubscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
publish(hash, message, seq, callback) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if(this.publishQueue.length === 0) {
|
|
||||||
this.publishQueue.splice(0, 0, { hash: message.Hash, callback: resolve });
|
|
||||||
console.log("...")
|
|
||||||
this.client2.publish(hash, JSON.stringify({ hash: message.Hash, seq: seq }));
|
|
||||||
console.log("published")
|
|
||||||
} else {
|
|
||||||
console.log("queue full!")
|
|
||||||
resolve(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
latest(hash) {
|
|
||||||
return { head: this._subscriptions[hash].head, modes: {}, seq: this._subscriptions[hash].seq };
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(hash, password) {
|
|
||||||
delete this._subscriptions[hash];
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleMessage(hash, event) {
|
|
||||||
if(this._subscriptions[hash]) {
|
|
||||||
var message = JSON.parse(event)
|
|
||||||
if(message.hash) {
|
|
||||||
var newHead = message.hash;
|
|
||||||
var seq = message.seq;
|
|
||||||
var isNewer = seq > this._subscriptions[hash].seq;
|
|
||||||
var item = this.publishQueue[this.publishQueue.length - 1];
|
|
||||||
|
|
||||||
// console.log(".", newHead, item ? item.hash : '', seq, this._subscriptions[hash].seq, isNewer)
|
|
||||||
|
|
||||||
if(item) {
|
|
||||||
this.publishQueue.pop();
|
|
||||||
item.callback(isNewer && newHead === item.hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isNewer)
|
|
||||||
this._updateSubscription(hash, newHead, seq);
|
|
||||||
} else if(message.r === 'HEAD') {
|
|
||||||
console.log("SEND HEAD!")
|
|
||||||
this.client2.publish(hash, JSON.stringify(this.latest(hash)));
|
|
||||||
} else {
|
|
||||||
console.log("GOT HEAD!", message)
|
|
||||||
var isNewer = message.seq > this._subscriptions[hash].seq;
|
|
||||||
if(isNewer) {
|
|
||||||
console.log("NEW HEAD!")
|
|
||||||
this.publishQueue.pop();
|
|
||||||
this._updateSubscription(hash, message.head, message.seq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateSubscription(hash, message, seq) {
|
|
||||||
// this.client3.set("orbit." + hash, JSON.stringify({ head: message, seq: seq }));
|
|
||||||
this._subscriptions[hash].seq = seq;
|
|
||||||
this._subscriptions[hash].head = message;
|
|
||||||
|
|
||||||
if(this._subscriptions[hash].callback)
|
|
||||||
this._subscriptions[hash].callback(hash, message, seq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = Pubsub2;
|
module.exports = Pubsub2;
|
||||||
|
@ -21,6 +21,11 @@ class OrbitList extends List {
|
|||||||
this.ver ++;
|
this.ver ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this._items = [];
|
||||||
|
this._currentBatch = [];
|
||||||
|
}
|
||||||
|
|
||||||
getIpfsHash() {
|
getIpfsHash() {
|
||||||
return new Promise(async((resolve, reject) => {
|
return new Promise(async((resolve, reject) => {
|
||||||
const list = await(ipfsAPI.putObject(this._ipfs, JSON.stringify(this.toJson())));
|
const list = await(ipfsAPI.putObject(this._ipfs, JSON.stringify(this.toJson())));
|
||||||
@ -28,6 +33,14 @@ class OrbitList extends List {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fromIpfsHash(ipfs, hash) {
|
||||||
|
return new Promise(async((resolve, reject) => {
|
||||||
|
const l = await(ipfsAPI.getObject(ipfs, hash));
|
||||||
|
const list = OrbitList.fromJson(ipfs, JSON.parse(l.Data));
|
||||||
|
resolve(list);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
static fromJson(ipfs, json) {
|
static fromJson(ipfs, json) {
|
||||||
let list = new List(json.id);
|
let list = new List(json.id);
|
||||||
list.seq = json.seq;
|
list.seq = json.seq;
|
||||||
@ -35,14 +48,6 @@ class OrbitList extends List {
|
|||||||
list._items = _.uniqWith(json.items.map((f) => new Node(ipfs, f.id, f.seq, f.ver, f.data, f.next)), _.isEqual);
|
list._items = _.uniqWith(json.items.map((f) => new Node(ipfs, f.id, f.seq, f.ver, f.data, f.next)), _.isEqual);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromIpfsHash(ipfs, hash) {
|
|
||||||
return new Promise(async((resolve, reject) => {
|
|
||||||
const l = await(ipfsAPI.getObject(ipfs, hash));
|
|
||||||
const list = OrbitList.fromJson(ipfs, JSON.parse(l.Data));
|
|
||||||
resolve(list);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = OrbitList;
|
module.exports = OrbitList;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const ipfsAPI = require('orbit-common/lib/ipfs-api-promised');
|
const async = require('asyncawait/async');
|
||||||
const await = require('asyncawait/await');
|
const await = require('asyncawait/await');
|
||||||
|
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 {
|
||||||
@ -20,8 +21,24 @@ class OrbitNode extends Node {
|
|||||||
return "" + this.id + "." + this.seq + "." + this.ver + "." + this.hash;
|
return "" + this.id + "." + this.seq + "." + this.ver + "." + this.hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPayload() {
|
||||||
|
if(!this.Payload) {
|
||||||
|
return new Promise(async((resolve, reject) => {
|
||||||
|
const payload = await(ipfsAPI.getObject(this._ipfs, this.data));
|
||||||
|
this.Payload = JSON.parse(payload.Data);
|
||||||
|
if(this.Payload.value) {
|
||||||
|
const value = await(ipfsAPI.getObject(this._ipfs, this.Payload.value));
|
||||||
|
this.Payload.value = JSON.parse(value.Data)["content"];
|
||||||
|
}
|
||||||
|
resolve(this);
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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, Payload: this.Payload }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -148,9 +148,9 @@ describe('OrbitList', async(function() {
|
|||||||
seq: 0,
|
seq: 0,
|
||||||
ver: 3,
|
ver: 3,
|
||||||
items: [
|
items: [
|
||||||
{ id: 'A', seq: 0, ver: 0, data: 'hello1', next: [] },
|
{ id: 'A', seq: 0, ver: 0, data: 'hello1', next: [], Payload: undefined },
|
||||||
{ id: 'A', seq: 0, ver: 1, data: 'hello2', next: ['A.0.0.QmZfdeMV77si491NPX83Q8eRYE9WNzVorHrfWJPrJ51brt'] },
|
{ 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'] }
|
{ id: 'A', seq: 0, ver: 2, data: 'hello3', next: ['A.0.1.QmbbtEWe4qHLSjtW2HkPuszFW3zfBTXBdPrkXMdbePxqfK'], Payload: undefined }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
// console.log(JSON.stringify(json, null, 1))
|
// console.log(JSON.stringify(json, null, 1))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user