mirror of
https://github.com/amark/gun.git
synced 2025-03-30 15:08:33 +00:00
commit
6fd70c3e6a
126
gun.js
126
gun.js
@ -169,7 +169,7 @@
|
||||
// On event emitter generic javascript utility.
|
||||
module.exports = function onto(tag, arg, as){
|
||||
if(!tag){ return {to: onto} }
|
||||
var tag = (this.tag || (this.tag = {}))[tag] ||
|
||||
var u, tag = (this.tag || (this.tag = {}))[tag] ||
|
||||
(this.tag[tag] = {tag: tag, to: onto._ = {
|
||||
next: function(arg){ var tmp;
|
||||
if((tmp = this.to)){
|
||||
@ -200,7 +200,7 @@
|
||||
(be.back = tag.last || tag).to = be;
|
||||
return tag.last = be;
|
||||
}
|
||||
(tag = tag.to).next(arg);
|
||||
if((tag = tag.to) && u !== arg){ tag.next(arg) }
|
||||
return tag;
|
||||
};
|
||||
})(USE, './onto');
|
||||
@ -685,7 +685,9 @@
|
||||
var gun = at.gun.opt(at.opt);
|
||||
if(!at.once){
|
||||
at.on('in', root, at);
|
||||
at.on('out', root, at);
|
||||
at.on('out', root, obj_to(at, {out: root}));
|
||||
Gun.on('create', at);
|
||||
at.on('create', at);
|
||||
}
|
||||
at.once = 1;
|
||||
return gun;
|
||||
@ -695,7 +697,13 @@
|
||||
var ev = this, at = ev.as, gun = at.gun, dup, tmp;
|
||||
//if(!msg.gun){ msg.gun = at.gun }
|
||||
if(!(tmp = msg['#'])){ tmp = msg['#'] = text_rand(9) }
|
||||
if((dup = at.dup).check(tmp)){ return }
|
||||
if((dup = at.dup).check(tmp)){
|
||||
if(at.out === msg.out){
|
||||
msg.out = u;
|
||||
ev.to.next(msg);
|
||||
}
|
||||
return;
|
||||
}
|
||||
dup.track(tmp);
|
||||
//msg = obj_to(msg);//, {gun: at.gun}); // can we delete this now?
|
||||
if(!at.ask(msg['@'], msg)){
|
||||
@ -708,7 +716,11 @@
|
||||
//at.on('put', put(msg));
|
||||
}
|
||||
}
|
||||
at.on('out', msg);
|
||||
ev.to.next(msg);
|
||||
if(!at.out){
|
||||
msg.out = root;
|
||||
at.on('out', msg);
|
||||
}
|
||||
}
|
||||
}());
|
||||
|
||||
@ -748,8 +760,11 @@
|
||||
function merge(node, soul){
|
||||
var ctx = this, cat = ctx.gun._, at = (cat.next || empty)[soul];
|
||||
if(!at){
|
||||
ctx.souls[soul] = false;
|
||||
return
|
||||
if(!(cat.opt||empty).super){
|
||||
ctx.souls[soul] = false;
|
||||
return;
|
||||
}
|
||||
at = (ctx.gun.get(soul)._);
|
||||
}
|
||||
var msg = ctx.map[soul] = {
|
||||
put: node,
|
||||
@ -936,6 +951,7 @@
|
||||
|
||||
function output(msg){
|
||||
var put, get, at = this.as, back = at.back, root = at.root;
|
||||
if(!msg.I){ msg.I = at.gun }
|
||||
if(!msg.gun){ msg.gun = at.gun }
|
||||
this.to.next(msg);
|
||||
if(get = msg.get){
|
||||
@ -1366,6 +1382,7 @@
|
||||
as.res = as.res || function(cb){ if(cb){ cb() } };
|
||||
as.res(function(){
|
||||
var cat = (as.gun.back(-1)._), ask = cat.ask(function(ack){
|
||||
cat.root.on('ack', ack);
|
||||
this.off(); // One response is good enough for us currently. Later we may want to adjust this.
|
||||
if(!as.ack){ return }
|
||||
as.ack(ack, this);
|
||||
@ -1742,7 +1759,72 @@
|
||||
If you update anything here, consider updating the other adapters as well.
|
||||
*/
|
||||
|
||||
Gun.on('opt', function(root){
|
||||
Gun.on('create', function(root){
|
||||
// This code is used to queue offline writes for resync.
|
||||
// See the next 'opt' code below for actual saving of data.
|
||||
var ev = this.to, opt = root.opt;
|
||||
if(root.once){ return ev.next(root) }
|
||||
if(false === opt.localStorage){ return ev.next(root) }
|
||||
opt.file = opt.file || 'gun/';
|
||||
var gap = Gun.obj.ify(store.getItem('gap/'+opt.file)) || {};
|
||||
var empty = Gun.obj.empty, id, to, go;
|
||||
// add re-sync command.
|
||||
if(!empty(gap)){
|
||||
root.on('localStorage', function(disk){
|
||||
this.off();
|
||||
var send = {}
|
||||
Gun.obj.map(gap, function(node, soul){
|
||||
Gun.obj.map(node, function(val, key){
|
||||
send[soul] = Gun.state.to(disk[soul], key, send[soul]);
|
||||
});
|
||||
});
|
||||
setTimeout(function(){
|
||||
root.on('out', {put: send, '#': root.ask(ack), I: root.gun});
|
||||
},10);
|
||||
});
|
||||
}
|
||||
|
||||
root.on('out', function(msg){
|
||||
if(msg.lS){ return }
|
||||
if(msg.I && msg.put && !msg['@'] && !empty(opt.peers)){
|
||||
id = msg['#'];
|
||||
Gun.graph.is(msg.put, null, map);
|
||||
if(!to){ to = setTimeout(flush, opt.wait || 1) }
|
||||
}
|
||||
this.to.next(msg);
|
||||
});
|
||||
root.on('ack', ack);
|
||||
|
||||
function ack(ack){ // TODO: This is experimental, not sure if we should keep this type of event hook.
|
||||
if(ack.err || !ack.ok){ return }
|
||||
var id = ack['@'];
|
||||
setTimeout(function(){
|
||||
Gun.obj.map(gap, function(node, soul){
|
||||
Gun.obj.map(node, function(val, key){
|
||||
if(id !== val){ return }
|
||||
delete node[key];
|
||||
});
|
||||
if(empty(node)){
|
||||
delete gap[soul];
|
||||
}
|
||||
});
|
||||
flush();
|
||||
}, opt.wait || 1);
|
||||
};
|
||||
ev.next(root);
|
||||
|
||||
var map = function(val, key, node, soul){
|
||||
(gap[soul] || (gap[soul] = {}))[key] = id;
|
||||
}
|
||||
var flush = function(){
|
||||
clearTimeout(to);
|
||||
to = false;
|
||||
try{store.setItem('gap/'+opt.file, JSON.stringify(gap));
|
||||
}catch(e){ Gun.log(err = e || "localStorage failure") }
|
||||
}
|
||||
});
|
||||
|
||||
Gun.on('create', function(root){
|
||||
this.to.next(root);
|
||||
var opt = root.opt;
|
||||
if(root.once){ return }
|
||||
@ -1750,6 +1832,8 @@
|
||||
opt.file = opt.file || opt.prefix || 'gun/'; // support old option name.
|
||||
var graph = root.graph, acks = {}, count = 0, to;
|
||||
var disk = Gun.obj.ify(store.getItem(opt.file)) || {};
|
||||
var lS = function(){}, u;
|
||||
root.on('localStorage', disk); // NON-STANDARD EVENT!
|
||||
|
||||
root.on('put', function(at){
|
||||
this.to.next(at);
|
||||
@ -1763,12 +1847,12 @@
|
||||
to = setTimeout(flush, opt.wait || 1);
|
||||
});
|
||||
|
||||
root.on('get', function(at){
|
||||
this.to.next(at);
|
||||
var lex = at.get, soul, data, u;
|
||||
root.on('get', function(msg){
|
||||
this.to.next(msg);
|
||||
var lex = msg.get, soul, data, u;
|
||||
//setTimeout(function(){
|
||||
if(!lex || !(soul = lex['#'])){ return }
|
||||
//if(0 >= at.cap){ return }
|
||||
//if(0 >= msg.cap){ return }
|
||||
var has = lex['.'];
|
||||
data = disk[soul] || u;
|
||||
if(data && has){
|
||||
@ -1777,7 +1861,7 @@
|
||||
if(!data && !Gun.obj.empty(opt.peers)){ // if data not found, don't ack if there are peers.
|
||||
return; // Hmm, what if we have peers but we are disconnected?
|
||||
}
|
||||
root.on('in', {'@': at['#'], put: Gun.graph.node(data), how: 'lS'});
|
||||
root.on('in', {'@': msg['#'], put: Gun.graph.node(data), how: 'lS', lS: msg.I});
|
||||
//},1);
|
||||
});
|
||||
|
||||
@ -1813,7 +1897,9 @@
|
||||
var mesh = function(){};
|
||||
|
||||
mesh.out = function(msg){ var tmp;
|
||||
//console.log("count:", msg['#'], msg);
|
||||
if(this.to){ this.to.next(msg) }
|
||||
//if(mesh.last != msg['#']){ return mesh.last = msg['#'], this.to.next(msg) }
|
||||
if((tmp = msg['@'])
|
||||
&& (tmp = ctx.dup.s[tmp])
|
||||
&& (tmp = tmp.it)
|
||||
@ -1886,7 +1972,8 @@
|
||||
return; // TODO: this still needs to be tested in the browser!
|
||||
}
|
||||
}
|
||||
if((tmp = msh.to) && (tmp[peer.url] || tmp[peer.id])){ return } // TODO: still needs to be tested
|
||||
if((tmp = msh.to) && (tmp[peer.url] || tmp[peer.id])){ return } // TODO: still needs to be tested
|
||||
//console.log('out', JSON.parse(raw));
|
||||
if(peer.batch){
|
||||
peer.batch.push(raw);
|
||||
return;
|
||||
@ -1898,14 +1985,16 @@
|
||||
peer.batch = null;
|
||||
if(!tmp.length){ return }
|
||||
send(JSON.stringify(tmp), peer);
|
||||
}, ctx.opt.wait || 1);
|
||||
}, ctx.opt.gap || ctx.opt.wait || 1);
|
||||
send(raw, peer);
|
||||
}
|
||||
|
||||
function send(raw, peer){
|
||||
var wire = peer.wire;
|
||||
try{
|
||||
if(wire.send){
|
||||
if(wire.readyState === wire.OPEN){
|
||||
//console.log("send:", raw);
|
||||
wire.send(raw);
|
||||
} else {
|
||||
(peer.queue = peer.queue || []).push(raw);
|
||||
@ -2019,7 +2108,10 @@
|
||||
opt.WebSocket = websocket;
|
||||
|
||||
var mesh = opt.mesh = opt.mesh || Gun.Mesh(root);
|
||||
root.on('out', mesh.out);
|
||||
root.on('create', function(at){
|
||||
this.to.next(at);
|
||||
root.on('out', mesh.out);
|
||||
});
|
||||
|
||||
opt.wire = opt.wire || open;
|
||||
function open(peer){
|
||||
@ -2041,7 +2133,9 @@
|
||||
mesh.hi(peer);
|
||||
}
|
||||
wire.onmessage = function(msg){
|
||||
//console.log('in', JSON.parse(msg.data || msg));
|
||||
if(!msg){ return }
|
||||
env.inLength = (env.inLength || 0) + (msg.data || msg).length; // TEMPORARY, NON-STANDARD, FOR DEBUG
|
||||
mesh.hear(msg.data || msg, peer);
|
||||
};
|
||||
return wire;
|
||||
|
2
gun.min.js
vendored
2
gun.min.js
vendored
File diff suppressed because one or more lines are too long
64
lib/debug.js
64
lib/debug.js
@ -1,13 +1,73 @@
|
||||
;(function(){
|
||||
if('debug' !== process.env.GUN_ENV){ return }
|
||||
|
||||
var db = {length: 0, hash: {}};
|
||||
|
||||
console.log("start :)");
|
||||
global.DEBUG = 1;
|
||||
setInterval(function(){
|
||||
var print = '', tmp;
|
||||
var mem = process.memoryUsage();
|
||||
var used = mem.rss / 1024 / 1024;
|
||||
used = used.toFixed(1);
|
||||
print += used +' MB rss. ';
|
||||
var used = mem.heapTotal / 1024 / 1024;
|
||||
used = used.toFixed(1);
|
||||
print += used +' MB hT. ';
|
||||
var used = mem.heapUsed / 1024 / 1024;
|
||||
used = used.toFixed(1);
|
||||
console.log(used, 'MB');
|
||||
}, 1000);
|
||||
print += used +' MB hU. ';
|
||||
if(db.root){
|
||||
db.concurrency = Object.keys(db.peers||{}).length;
|
||||
print += db.concurrency +' peers. ';
|
||||
db.nodes = Object.keys(db.root.graph||{}).length;
|
||||
print += db.nodes + ' nodes. ';
|
||||
if(db.count){ print += db.count + ' msgs. '}
|
||||
if(tmp = db.root.msgsLength){
|
||||
tmp = (tmp / 1024 / 1024).toFixed(2);
|
||||
print += tmp + ' length MB. ';
|
||||
}
|
||||
if(db.last){ print += '\n' + JSON.stringify(db.last, null, 2) }
|
||||
if(db.hash){
|
||||
print += '\nSome 100 Fast Hash Counts: \n' + JSON.stringify(db.hash, null, 2);
|
||||
var l = Object.keys(db.hash), i = l.length;
|
||||
if(i > 100){
|
||||
i = i - 100;
|
||||
Gun.list.map(l, function(k){
|
||||
if(--i <= 0){ return }
|
||||
delete db.hash[k];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
db.print = print;
|
||||
print = print.split('\n')[0];
|
||||
console.log(print);
|
||||
}, 2500);
|
||||
|
||||
var Gun = require('../gun');
|
||||
Gun.on('opt', function(root){
|
||||
this.to.next(root);
|
||||
if(root.once){ return }
|
||||
console.log(">>>>>>>>>", root);
|
||||
root.debug = db;
|
||||
db.root = root;
|
||||
db.peers = root.opt.peers;
|
||||
|
||||
db.count = 0;
|
||||
root.on('in', function(msg){
|
||||
this.to.next(msg);
|
||||
if(!msg.NTS){ db.last = msg }
|
||||
db.count++;
|
||||
var tmp = msg['##'];
|
||||
if(tmp && msg.put){
|
||||
if(!db.hash[tmp]){ db.hash[tmp] = [0, ''] }
|
||||
db.hash[tmp][0] = (db.hash[tmp][0] || 0) + 1;
|
||||
var preview = Object.keys(msg.put||{});
|
||||
db.hash[tmp][1] = preview.toString(', ').slice(0,500) + ' ...';
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
}());
|
46
lib/evict.js
Normal file
46
lib/evict.js
Normal file
@ -0,0 +1,46 @@
|
||||
;(function(){
|
||||
var Gun = (typeof window !== 'undefined')? window.Gun : require('../gun');
|
||||
|
||||
var ev = {}, empty = {}, u;
|
||||
Gun.on('opt', function(root){
|
||||
this.to.next(root);
|
||||
if(root.once){ return }
|
||||
if(typeof process == 'undefined'){ return }
|
||||
var util = process.memoryUsage;
|
||||
if(!util){ return }
|
||||
|
||||
ev.max = parseFloat(root.opt.memory || process.env.WEB_MEMORY || 512) * 0.8;
|
||||
|
||||
setInterval(check, 1000);
|
||||
function check(){
|
||||
var used = ev.used = util().rss / 1024 / 1024;
|
||||
if(used < ev.max){ return }
|
||||
setTimeout(GC, 1);
|
||||
}
|
||||
function GC(){
|
||||
var souls = Object.keys(root.graph||empty);
|
||||
var toss = Math.ceil(souls.length * 0.01);
|
||||
//var start = Gun.state(), i = toss;
|
||||
Gun.list.map(souls, function(soul){
|
||||
if(--toss < 0){ return }
|
||||
root.gun.get(soul).off();
|
||||
});
|
||||
//console.log("evicted", i, 'nodes in', ((Gun.state() - start)/1000).toFixed(2), 'sec.');
|
||||
}
|
||||
/*
|
||||
root.on('in', function(msg){
|
||||
this.to.next(msg);
|
||||
if(msg.get){
|
||||
return;
|
||||
}
|
||||
Gun.graph.is(msg, function(node, soul){
|
||||
var meta = (root.next||empty)[soul];
|
||||
if(!meta){ return }
|
||||
Gun.node.is(node, function(data, key){
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
*/
|
||||
});
|
||||
}());
|
@ -6,9 +6,9 @@ function Radisk(opt){
|
||||
|
||||
opt = opt || {};
|
||||
opt.file = String(opt.file || 'radata');
|
||||
opt.thrash = opt.thrash || opt.wait || 1;
|
||||
opt.until = opt.until || opt.wait || 1;
|
||||
opt.batch = opt.batch || 10 * 1000;
|
||||
opt.size = opt.size || (1024 * 1024 * 10); // 10MB
|
||||
opt.chunk = opt.chunk || (1024 * 1024 * 10); // 10MB
|
||||
opt.code = opt.code || {};
|
||||
opt.code.from = opt.code.from || '!';
|
||||
|
||||
@ -51,7 +51,7 @@ function Radisk(opt){
|
||||
if(cb){ r.batch.acks.push(cb) }
|
||||
if(++r.batch.ed >= opt.batch){ return r.thrash() } // (2)
|
||||
clearTimeout(r.batch.to); // (1)
|
||||
r.batch.to = setTimeout(r.thrash, opt.thrash || 1);
|
||||
r.batch.to = setTimeout(r.thrash, opt.until || 1);
|
||||
}
|
||||
|
||||
r.batch = Radix();
|
||||
@ -137,7 +137,7 @@ function Radisk(opt){
|
||||
f.each = function(val, key, k, pre){
|
||||
f.count++;
|
||||
var enc = Radisk.encode(pre.length) +'#'+ Radisk.encode(k) + (u === val? '' : '='+ Radisk.encode(val)) +'\n';
|
||||
if(opt.size < f.text.length + enc.length){
|
||||
if(opt.chunk < f.text.length + enc.length){
|
||||
f.text = '';
|
||||
f.limit = Math.ceil(f.count/2);
|
||||
f.count = 0;
|
||||
@ -204,7 +204,7 @@ function Radisk(opt){
|
||||
}
|
||||
g.ack = function(as){
|
||||
if(!as.ack){ return }
|
||||
as.ack(g.err, RAD(as.key));
|
||||
as.ack(g.err, (RAD || noop)(as.key));
|
||||
}
|
||||
opt.store.list(g.lex);
|
||||
}
|
||||
@ -257,7 +257,7 @@ function Radisk(opt){
|
||||
opt.store.get(file, p.read);
|
||||
}
|
||||
|
||||
var q = {}, RAD, u;
|
||||
var q = {}, noop = function(){}, RAD, u;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,8 @@ Gun.on('opt', function(ctx){
|
||||
if(ctx.once){ return }
|
||||
if(!process.env.AWS_S3_BUCKET){ return }
|
||||
opt.batch = opt.batch || (1000 * 10);
|
||||
opt.thrash = opt.thrash || (1000 * 15);
|
||||
opt.size = opt.size || (1024 * 1024 * 10); // 10MB
|
||||
opt.until = opt.until || (1000 * 15);
|
||||
opt.chunk = opt.chunk || (1024 * 1024 * 10); // 10MB
|
||||
|
||||
try{AWS = require('aws-sdk');
|
||||
}catch(e){
|
||||
|
@ -1,6 +1,13 @@
|
||||
;(function(){
|
||||
var Gun = require('../gun');
|
||||
var Gun = require('../gun'), u;
|
||||
Gun.serve = require('./serve');
|
||||
process.env.GUN_ENV = process.env.GUN_ENV || 'debug';
|
||||
Gun.on('opt', function(root){
|
||||
this.to.next(root);
|
||||
if(root.once){ return }
|
||||
if(u !== root.opt.super){ return }
|
||||
root.opt.super = true;
|
||||
})
|
||||
require('../nts');
|
||||
require('./store');
|
||||
require('./rs3');
|
||||
@ -9,6 +16,7 @@
|
||||
require('./verify');
|
||||
require('./file');
|
||||
require('./bye');
|
||||
require('./evict');
|
||||
if('debug' === process.env.GUN_ENV){ require('./debug') }
|
||||
module.exports = Gun;
|
||||
}());
|
@ -10,7 +10,7 @@ Gun.on('opt', function(ctx){
|
||||
if(ctx.once){ return }
|
||||
if(false !== opt.localStorage && !process.env.AWS_S3_BUCKET){ return } // TODO: Remove this after migration.
|
||||
if(false === opt.radisk){ return }
|
||||
console.log("BUG WARNING: Radix Storage Engine (RSE) has a known rare edge case, if data gets split between file chunks, a GET may only return the first chunk!!!");
|
||||
console.log("BUG WARNING: Radix Storage Engine (RAD) has a known rare edge case, if data gets split between file chunks, a GET may only return the first chunk!!!");
|
||||
opt.store = opt.store || Store(opt);
|
||||
var rad = Radisk(opt);
|
||||
|
||||
|
@ -77,6 +77,7 @@ Gun.on('opt', function(ctx){
|
||||
ctx.on('hi', peer);
|
||||
wire.on('message', function(msg){
|
||||
//console.log("MESSAGE", msg);
|
||||
ctx.msgsLength = (ctx.msgsLength || 0) + (msg.data || msg).length; // TEMPORARY, NON-STANDARD, FOR DEBUG
|
||||
opt.mesh.hear(msg.data || msg, peer);
|
||||
});
|
||||
wire.on('close', function(){
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gun",
|
||||
"version": "0.9.996",
|
||||
"version": "0.9.997",
|
||||
"description": "A realtime, decentralized, offline-first, graph data synchronization engine.",
|
||||
"main": "index.js",
|
||||
"browser": "gun.min.js",
|
||||
|
@ -10,7 +10,72 @@ var store = root.localStorage || {setItem: noop, removeItem: noop, getItem: noop
|
||||
If you update anything here, consider updating the other adapters as well.
|
||||
*/
|
||||
|
||||
Gun.on('opt', function(root){
|
||||
Gun.on('create', function(root){
|
||||
// This code is used to queue offline writes for resync.
|
||||
// See the next 'opt' code below for actual saving of data.
|
||||
var ev = this.to, opt = root.opt;
|
||||
if(root.once){ return ev.next(root) }
|
||||
if(false === opt.localStorage){ return ev.next(root) }
|
||||
opt.file = opt.file || 'gun/';
|
||||
var gap = Gun.obj.ify(store.getItem('gap/'+opt.file)) || {};
|
||||
var empty = Gun.obj.empty, id, to, go;
|
||||
// add re-sync command.
|
||||
if(!empty(gap)){
|
||||
root.on('localStorage', function(disk){
|
||||
this.off();
|
||||
var send = {}
|
||||
Gun.obj.map(gap, function(node, soul){
|
||||
Gun.obj.map(node, function(val, key){
|
||||
send[soul] = Gun.state.to(disk[soul], key, send[soul]);
|
||||
});
|
||||
});
|
||||
setTimeout(function(){
|
||||
root.on('out', {put: send, '#': root.ask(ack), I: root.gun});
|
||||
},10);
|
||||
});
|
||||
}
|
||||
|
||||
root.on('out', function(msg){
|
||||
if(msg.lS){ return }
|
||||
if(msg.I && msg.put && !msg['@'] && !empty(opt.peers)){
|
||||
id = msg['#'];
|
||||
Gun.graph.is(msg.put, null, map);
|
||||
if(!to){ to = setTimeout(flush, opt.wait || 1) }
|
||||
}
|
||||
this.to.next(msg);
|
||||
});
|
||||
root.on('ack', ack);
|
||||
|
||||
function ack(ack){ // TODO: This is experimental, not sure if we should keep this type of event hook.
|
||||
if(ack.err || !ack.ok){ return }
|
||||
var id = ack['@'];
|
||||
setTimeout(function(){
|
||||
Gun.obj.map(gap, function(node, soul){
|
||||
Gun.obj.map(node, function(val, key){
|
||||
if(id !== val){ return }
|
||||
delete node[key];
|
||||
});
|
||||
if(empty(node)){
|
||||
delete gap[soul];
|
||||
}
|
||||
});
|
||||
flush();
|
||||
}, opt.wait || 1);
|
||||
};
|
||||
ev.next(root);
|
||||
|
||||
var map = function(val, key, node, soul){
|
||||
(gap[soul] || (gap[soul] = {}))[key] = id;
|
||||
}
|
||||
var flush = function(){
|
||||
clearTimeout(to);
|
||||
to = false;
|
||||
try{store.setItem('gap/'+opt.file, JSON.stringify(gap));
|
||||
}catch(e){ Gun.log(err = e || "localStorage failure") }
|
||||
}
|
||||
});
|
||||
|
||||
Gun.on('create', function(root){
|
||||
this.to.next(root);
|
||||
var opt = root.opt;
|
||||
if(root.once){ return }
|
||||
@ -18,6 +83,8 @@ Gun.on('opt', function(root){
|
||||
opt.file = opt.file || opt.prefix || 'gun/'; // support old option name.
|
||||
var graph = root.graph, acks = {}, count = 0, to;
|
||||
var disk = Gun.obj.ify(store.getItem(opt.file)) || {};
|
||||
var lS = function(){}, u;
|
||||
root.on('localStorage', disk); // NON-STANDARD EVENT!
|
||||
|
||||
root.on('put', function(at){
|
||||
this.to.next(at);
|
||||
@ -31,12 +98,12 @@ Gun.on('opt', function(root){
|
||||
to = setTimeout(flush, opt.wait || 1);
|
||||
});
|
||||
|
||||
root.on('get', function(at){
|
||||
this.to.next(at);
|
||||
var lex = at.get, soul, data, u;
|
||||
root.on('get', function(msg){
|
||||
this.to.next(msg);
|
||||
var lex = msg.get, soul, data, u;
|
||||
//setTimeout(function(){
|
||||
if(!lex || !(soul = lex['#'])){ return }
|
||||
//if(0 >= at.cap){ return }
|
||||
//if(0 >= msg.cap){ return }
|
||||
var has = lex['.'];
|
||||
data = disk[soul] || u;
|
||||
if(data && has){
|
||||
@ -45,7 +112,7 @@ Gun.on('opt', function(root){
|
||||
if(!data && !Gun.obj.empty(opt.peers)){ // if data not found, don't ack if there are peers.
|
||||
return; // Hmm, what if we have peers but we are disconnected?
|
||||
}
|
||||
root.on('in', {'@': at['#'], put: Gun.graph.node(data), how: 'lS'});
|
||||
root.on('in', {'@': msg['#'], put: Gun.graph.node(data), how: 'lS', lS: msg.I});
|
||||
//},1);
|
||||
});
|
||||
|
||||
|
@ -5,7 +5,9 @@ function Mesh(ctx){
|
||||
var mesh = function(){};
|
||||
|
||||
mesh.out = function(msg){ var tmp;
|
||||
//console.log("count:", msg['#'], msg);
|
||||
if(this.to){ this.to.next(msg) }
|
||||
//if(mesh.last != msg['#']){ return mesh.last = msg['#'], this.to.next(msg) }
|
||||
if((tmp = msg['@'])
|
||||
&& (tmp = ctx.dup.s[tmp])
|
||||
&& (tmp = tmp.it)
|
||||
@ -78,7 +80,8 @@ function Mesh(ctx){
|
||||
return; // TODO: this still needs to be tested in the browser!
|
||||
}
|
||||
}
|
||||
if((tmp = msh.to) && (tmp[peer.url] || tmp[peer.id])){ return } // TODO: still needs to be tested
|
||||
if((tmp = msh.to) && (tmp[peer.url] || tmp[peer.id])){ return } // TODO: still needs to be tested
|
||||
//console.log('out', JSON.parse(raw));
|
||||
if(peer.batch){
|
||||
peer.batch.push(raw);
|
||||
return;
|
||||
@ -90,14 +93,16 @@ function Mesh(ctx){
|
||||
peer.batch = null;
|
||||
if(!tmp.length){ return }
|
||||
send(JSON.stringify(tmp), peer);
|
||||
}, ctx.opt.wait || 1);
|
||||
}, ctx.opt.gap || ctx.opt.wait || 1);
|
||||
send(raw, peer);
|
||||
}
|
||||
|
||||
function send(raw, peer){
|
||||
var wire = peer.wire;
|
||||
try{
|
||||
if(wire.send){
|
||||
if(wire.readyState === wire.OPEN){
|
||||
//console.log("send:", raw);
|
||||
wire.send(raw);
|
||||
} else {
|
||||
(peer.queue = peer.queue || []).push(raw);
|
||||
|
@ -18,7 +18,10 @@ Gun.on('opt', function(root){
|
||||
opt.WebSocket = websocket;
|
||||
|
||||
var mesh = opt.mesh = opt.mesh || Gun.Mesh(root);
|
||||
root.on('out', mesh.out);
|
||||
root.on('create', function(at){
|
||||
this.to.next(at);
|
||||
root.on('out', mesh.out);
|
||||
});
|
||||
|
||||
opt.wire = opt.wire || open;
|
||||
function open(peer){
|
||||
@ -40,7 +43,9 @@ Gun.on('opt', function(root){
|
||||
mesh.hi(peer);
|
||||
}
|
||||
wire.onmessage = function(msg){
|
||||
//console.log('in', JSON.parse(msg.data || msg));
|
||||
if(!msg){ return }
|
||||
env.inLength = (env.inLength || 0) + (msg.data || msg).length; // TEMPORARY, NON-STANDARD, FOR DEBUG
|
||||
mesh.hear(msg.data || msg, peer);
|
||||
};
|
||||
return wire;
|
||||
|
@ -16,6 +16,7 @@ Gun.chain.chain = function(sub){
|
||||
|
||||
function output(msg){
|
||||
var put, get, at = this.as, back = at.back, root = at.root;
|
||||
if(!msg.I){ msg.I = at.gun }
|
||||
if(!msg.gun){ msg.gun = at.gun }
|
||||
this.to.next(msg);
|
||||
if(get = msg.get){
|
||||
|
@ -2,7 +2,7 @@
|
||||
// On event emitter generic javascript utility.
|
||||
module.exports = function onto(tag, arg, as){
|
||||
if(!tag){ return {to: onto} }
|
||||
var tag = (this.tag || (this.tag = {}))[tag] ||
|
||||
var u, tag = (this.tag || (this.tag = {}))[tag] ||
|
||||
(this.tag[tag] = {tag: tag, to: onto._ = {
|
||||
next: function(arg){ var tmp;
|
||||
if((tmp = this.to)){
|
||||
@ -33,7 +33,7 @@ module.exports = function onto(tag, arg, as){
|
||||
(be.back = tag.last || tag).to = be;
|
||||
return tag.last = be;
|
||||
}
|
||||
(tag = tag.to).next(arg);
|
||||
if((tag = tag.to) && u !== arg){ tag.next(arg) }
|
||||
return tag;
|
||||
};
|
||||
|
@ -93,6 +93,7 @@ function batch(){ var as = this;
|
||||
as.res = as.res || function(cb){ if(cb){ cb() } };
|
||||
as.res(function(){
|
||||
var cat = (as.gun.back(-1)._), ask = cat.ask(function(ack){
|
||||
cat.root.on('ack', ack);
|
||||
this.off(); // One response is good enough for us currently. Later we may want to adjust this.
|
||||
if(!as.ack){ return }
|
||||
as.ack(ack, this);
|
||||
|
25
src/root.js
25
src/root.js
@ -34,7 +34,9 @@ Gun.dup = require('./dup');
|
||||
var gun = at.gun.opt(at.opt);
|
||||
if(!at.once){
|
||||
at.on('in', root, at);
|
||||
at.on('out', root, at);
|
||||
at.on('out', root, obj_to(at, {out: root}));
|
||||
Gun.on('create', at);
|
||||
at.on('create', at);
|
||||
}
|
||||
at.once = 1;
|
||||
return gun;
|
||||
@ -44,7 +46,13 @@ Gun.dup = require('./dup');
|
||||
var ev = this, at = ev.as, gun = at.gun, dup, tmp;
|
||||
//if(!msg.gun){ msg.gun = at.gun }
|
||||
if(!(tmp = msg['#'])){ tmp = msg['#'] = text_rand(9) }
|
||||
if((dup = at.dup).check(tmp)){ return }
|
||||
if((dup = at.dup).check(tmp)){
|
||||
if(at.out === msg.out){
|
||||
msg.out = u;
|
||||
ev.to.next(msg);
|
||||
}
|
||||
return;
|
||||
}
|
||||
dup.track(tmp);
|
||||
//msg = obj_to(msg);//, {gun: at.gun}); // can we delete this now?
|
||||
if(!at.ask(msg['@'], msg)){
|
||||
@ -57,7 +65,11 @@ Gun.dup = require('./dup');
|
||||
//at.on('put', put(msg));
|
||||
}
|
||||
}
|
||||
at.on('out', msg);
|
||||
ev.to.next(msg);
|
||||
if(!at.out){
|
||||
msg.out = root;
|
||||
at.on('out', msg);
|
||||
}
|
||||
}
|
||||
}());
|
||||
|
||||
@ -97,8 +109,11 @@ Gun.dup = require('./dup');
|
||||
function merge(node, soul){
|
||||
var ctx = this, cat = ctx.gun._, at = (cat.next || empty)[soul];
|
||||
if(!at){
|
||||
ctx.souls[soul] = false;
|
||||
return
|
||||
if(!(cat.opt||empty).super){
|
||||
ctx.souls[soul] = false;
|
||||
return;
|
||||
}
|
||||
at = (ctx.gun.get(soul)._);
|
||||
}
|
||||
var msg = ctx.map[soul] = {
|
||||
put: node,
|
||||
|
Loading…
x
Reference in New Issue
Block a user