mirror of
https://github.com/amark/gun.git
synced 2025-06-06 14:16:44 +00:00
towards recomposition
This commit is contained in:
parent
f63760b81b
commit
baf5a52b7d
Binary file not shown.
@ -1,7 +1,7 @@
|
||||
var fs = require('fs');
|
||||
var http = require('http');
|
||||
var qs = require('querystring');
|
||||
var sync = require('./shotgun');
|
||||
var sync = require('../../test/shotgun');
|
||||
|
||||
http.route = function(url){
|
||||
console.log(url);
|
@ -1,5 +1,5 @@
|
||||
var sign = {};
|
||||
var gun = require('./shotgun');
|
||||
var gun = require('../../test/shotgun');
|
||||
|
||||
sign.user = {}
|
||||
sign.user.create = function(form, cb, shell){ // TODO: REDO THIS TO MATCH GUN
|
||||
@ -7,13 +7,30 @@ sign.user.create = function(form, cb, shell){ // TODO: REDO THIS TO MATCH GUN
|
||||
if(err || !user){ return cb(err) }
|
||||
user = {key: user.key, salt: user.salt};
|
||||
user.account = {email: form.email, registered: new Date().getTime()};
|
||||
shell.set(user, function(){
|
||||
console.log("yo bro, that user creation totally worked.");
|
||||
}).index('email/' + user.account.email);
|
||||
gun.set(user).index('email/' + user.account.email);
|
||||
cb(null, user);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
gun.load('email/mark@accelsor.com')
|
||||
.path('friends')
|
||||
.match({name: "David Oliveros"})
|
||||
.path('friends')
|
||||
.match({activity: 'surfer'})
|
||||
.get(function(surfer){
|
||||
sendEmail("Mark wants to leanr how ot surf, and you are a friend of a friend");
|
||||
});
|
||||
*/
|
||||
|
||||
/*
|
||||
gun.load()
|
||||
|
||||
here is a bunch of node indices
|
||||
now for each combinatoric pair
|
||||
find all possible paths between them
|
||||
*/
|
||||
|
||||
sign.server = function(req, res){
|
||||
console.log("sign.server", req.body);
|
||||
if(!req.body || !req.body.email){ return res.emit('end', {err: "That email does not exist."}) }
|
94
gun2.js
94
gun2.js
@ -13,9 +13,13 @@
|
||||
Gun.chain._.opt = {};
|
||||
Gun.chain._.nodes = {};
|
||||
Gun.chain._.chain = {};
|
||||
Gun.chain._.trace = [];
|
||||
Gun.chain._.indices = {};
|
||||
Gun.chain.init = function(opt, stun){ // idempotently update or set options
|
||||
var gun = this;
|
||||
gun._.events = gun._.events || Gun.on.split(); // we may not want it global for each gun instance?
|
||||
gun._.events.trace = gun._.events.trace || 0;
|
||||
gun._.events.at = gun._.events.at || 0;
|
||||
if(Gun.text.is(opt)){ opt = {peers: opt} }
|
||||
if(Gun.list.is(opt)){ opt = {peers: opt} }
|
||||
if(Gun.text.is(opt.peers)){ opt.peers = [opt.peers] }
|
||||
@ -30,11 +34,11 @@
|
||||
if(!stun){ Gun.on('init').emit(gun, opt) }
|
||||
return gun;
|
||||
}
|
||||
Gun.chain.load = function(index, cb){
|
||||
Gun.chain.load = function(index, cb, opt){
|
||||
var gun = this;
|
||||
cb = cb || function(){};
|
||||
if(cb.node = gun._.indices[index]){ // set this to the current node, too!
|
||||
console.log("from gun");
|
||||
console.log("from gun"); // remember to do all the same stack stuff here also!
|
||||
return cb(cb.node), gun;
|
||||
}
|
||||
cb.fn = function(){}
|
||||
@ -45,10 +49,13 @@
|
||||
gun._.loaded = (gun._.loaded || 0) + 1; // TODO: loading should be idempotent even if we got an err or no data
|
||||
if(err){ return (gun._.chain.dud||cb.fn)(err) }
|
||||
if(!data){ return (gun._.chain.blank||cb.fn)() }
|
||||
var nodes = {}; nodes[data._[own.sym.id]] = data;// missing: transform data, merging it! NO, THIS IS DONE WRONG, do a real check.
|
||||
var nodes = {}, node;
|
||||
nodes[data._[own.sym.id]] = data;// missing: transform data, merging it! NO, THIS IS DONE WRONG, do a real check.
|
||||
Gun.union(gun._.nodes, nodes);
|
||||
return cb(gun._.indices[index] = gun._.nodes[data._[own.sym.id]]);
|
||||
});
|
||||
node = gun._.indices[index] = gun._.nodes[data._[own.sym.id]];
|
||||
cb(node); // WARNING: Need to return a frozen copy of the object! But now the internal system is using this too... :/
|
||||
gun._.events.on(gun._.events.at += 1).emit(node);
|
||||
}, opt);
|
||||
} else {
|
||||
console.log("Warning! You have no persistence layer to load from!");
|
||||
}
|
||||
@ -60,7 +67,7 @@
|
||||
this._.indices[index] = this._.node;
|
||||
if(Gun.fns.is(this._.opt.hook.index)){
|
||||
this._.opt.hook.index(index, this._.node, function(err, data){
|
||||
console.log("index made");
|
||||
console.log("index made", index);
|
||||
if(err){ return cb(err) }
|
||||
return cb(null);
|
||||
});
|
||||
@ -70,20 +77,51 @@
|
||||
return this;
|
||||
}
|
||||
Gun.chain.path = function(path){ // The focal point follows the path
|
||||
|
||||
var gun = this;
|
||||
path = path.split('.');
|
||||
console.log("PATH stack trace", gun._.events.trace + 1);
|
||||
gun._.events.on(gun._.events.trace += 1).event(function trace(node){
|
||||
console.log("stack at", gun._.events.at);
|
||||
if(!path.length){ // if the path resolves to another node, we finish here
|
||||
console.log("PATH resolved with node");
|
||||
gun._.events.on(gun._.events.at += 1).emit(node);
|
||||
return;
|
||||
}
|
||||
var key = path.shift()
|
||||
, val = node[key];
|
||||
if(key = Gun.ify.is.id(val)){ // we might end on a link, so we must resolve
|
||||
gun.load(key, trace, {id: true}).blank(function(){ }).dud(function(){ }); // TODO: Need to map these to the real blank/dud
|
||||
} else {
|
||||
if(path.length){ // we cannot go any further, despite the fact there is more path, which means the thing we wanted does not exist
|
||||
console.log("PATH failed to resolve");
|
||||
gun._.events.on(gun._.events.at += 1).emit();
|
||||
} else { // we are done, and this should be the value we wanted.
|
||||
console.log("PATH resolved", val);
|
||||
gun._.events.on(gun._.events.at += 1).emit(val);
|
||||
}
|
||||
}
|
||||
});
|
||||
return gun;
|
||||
}
|
||||
Gun.chain.get = function(cb){
|
||||
Gun.chain.get = function(cb){ // WARNING! Need to return a frozen copy of the object.
|
||||
var gun = this;
|
||||
console.log("GET stack trace", gun._.events.trace + 1);
|
||||
gun._.events.on(gun._.events.trace += 1).event(function(node){
|
||||
console.log("GOT", node);
|
||||
cb(node);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
/*
|
||||
ACID compliant, unfortunately ACID's vocabulary is confusing:
|
||||
ACID compliant, unfortunately the vocabulary is vague, as such the following is an explicit definition:
|
||||
A - Atomic, if you set a full node, or nodes of nodes, if any value is in error then nothing will be set.
|
||||
If you want sets to be independent of each other, you need to set individual keys with their value.
|
||||
C - Consistency, if you use any reserved symbols or similar, the operation will be rejected.
|
||||
I - Isolation, the hypothetical amnesia machine guarantees the relative state of each transaction, across every peer.
|
||||
D - Durability, if the acknowledgement receipt is received, then the data is guaranteed to have persisted.
|
||||
However, by the time it is received, the data that was set may already be out of date.
|
||||
The current data is already available to be checked and compared if need be.
|
||||
If you want sets to be independent of each other, you need to set each piece of the data individually.
|
||||
C - Consistency, if you use any reserved symbols or similar, the operation will be rejected as it could lead to an invalid read and thus an invalid state.
|
||||
I - Isolation, the conflict resolution algorithm guarantees idempotent transactions, across every peer, regardless of any partition,
|
||||
including a peer acting by itself or one having been disconnected from the network.
|
||||
D - Durability, if the acknowledgement receipt is received, then the state at which the final persistence hook was called on is guaranteed to have been written.
|
||||
The live state at point of confirmation may or may not be different than when it was called.
|
||||
If this causes any application-level concern, it can compare against the live data by immediately reading it, or accessing the logs if enabled.
|
||||
*/
|
||||
Gun.chain.set = function(val, cb){
|
||||
var gun = this, set;
|
||||
@ -218,7 +256,7 @@
|
||||
Gun.on = (function(){
|
||||
function On(on){
|
||||
var e = On.is(this)? this : events;
|
||||
return e._ = e._ || {}, e._.on = on, e;
|
||||
return e._ = e._ || {}, e._.on = Gun.text.ify(on), e;
|
||||
}
|
||||
On.is = function(on){ return (on instanceof On)? true : false }
|
||||
On.split = function(){ return new On() }
|
||||
@ -238,11 +276,11 @@
|
||||
}))){ delete this._.events[on] }
|
||||
}
|
||||
On.echo.event = function(as, i){
|
||||
var on = this._.on;
|
||||
var on = this._.on, e;
|
||||
if(!on || !as){ return }
|
||||
this._.events = this._.events || {};
|
||||
on = this._.events[on] = this._.events[on] || (this._.events[on] = [])
|
||||
, e = {as: as, i: i || 0, off: function(){ return !(e.as = false) }};
|
||||
on = this._.events[on] = this._.events[on] || (this._.events[on] = []);
|
||||
e = {as: as, i: i || 0, off: function(){ return !(e.as = false) }};
|
||||
return on.push(e), on.sort(On.sort), e;
|
||||
}
|
||||
On.echo.once = function(as, i){
|
||||
@ -294,10 +332,17 @@
|
||||
return {converge: true, incoming: true};
|
||||
}
|
||||
if(incomingState === currentState){
|
||||
if(incomingValue === currentValue){
|
||||
// Note: while these are practically the same, the deltas could be technically different
|
||||
if(incomingValue === currentValue){ // Note: while these are practically the same, the deltas could be technically different
|
||||
return {state: true};
|
||||
}
|
||||
/*
|
||||
The following is a naive implementation, but will always work.
|
||||
Never change it unless you have specific needs that absolutely require it.
|
||||
If changed, your data will diverge unless you guarantee every peer's algorithm has also been changed to be the same.
|
||||
As a result, it is highly discouraged to modify despite the fact that it is naive,
|
||||
because convergence (data integrity) is generally more important.
|
||||
Any difference in this algorithm must be given a new and different name.
|
||||
*/
|
||||
if(String(incomingValue) < String(currentValue)){ // String only works on primitive values!
|
||||
return {converge: true, current: true};
|
||||
}
|
||||
@ -479,6 +524,13 @@
|
||||
|| Gun.text.is(v)){
|
||||
return true; // simple values
|
||||
}
|
||||
var yes;
|
||||
if(yes = Gun.ify.is.id(v)){
|
||||
return yes;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Gun.ify.is.id = function(v){
|
||||
if(Gun.obj.is(v)){
|
||||
var yes;
|
||||
Gun.obj.map(v, function(id, key){
|
||||
|
15
shots2.js
15
shots2.js
@ -11,15 +11,20 @@
|
||||
s3.nodes = s3.nodes || opt.s3.nodes || '_/nodes/';
|
||||
gun._.opt.batch = opt.batch || gun._.opt.batch || 10;
|
||||
gun._.opt.throttle = opt.throttle || gun._.opt.throttle || 2;
|
||||
if(!gun._.opt.keepDefaultMaxSockets){ require('http').globalAgent.maxSockets = 999 } // because the default is 5, sad face.
|
||||
if(!gun._.opt.keepDefaultMaxSockets){ require('http').globalAgent.maxSockets = 999 } // we shouldn't do this globally! But because the default is 5, sad face.
|
||||
|
||||
s3.load = s3.load || function(index, cb, direct){
|
||||
s3.load = s3.load || function(index, cb, opt){
|
||||
cb = cb || function(){};
|
||||
s3.get(direct? index : s3.path + s3.indices + index, function(err, data, text, meta){
|
||||
opt = opt || {};
|
||||
if(opt.id){
|
||||
index = s3.path + s3.nodes + index;
|
||||
} else {
|
||||
index = s3.path + s3.indices + index;
|
||||
}
|
||||
s3.get(index, function(err, data, text, meta){
|
||||
console.log('via s3', index);
|
||||
if(meta && (index = meta[Gun.sym.id])){
|
||||
console.log("fetch pointer");
|
||||
return s3.load(s3.path + s3.nodes + index, cb, true);
|
||||
return s3.load(index, cb, {id: true});
|
||||
}
|
||||
if(err && err.statusCode == 404){
|
||||
err = null; // we want a difference between 'unfound' (data is null) and 'error' (keys are wrong)
|
||||
|
@ -1,7 +1,7 @@
|
||||
describe('Gun', function(){
|
||||
var Gun = require('../gun2');
|
||||
|
||||
it('ify', function(){return;
|
||||
it('ify', function(){
|
||||
var data, test;
|
||||
|
||||
data = {a: false, b: true, c: 0, d: 1, e: '', f: 'g', h: null};
|
||||
@ -51,7 +51,7 @@ describe('Gun', function(){
|
||||
console.log(test.nodes);
|
||||
});
|
||||
|
||||
it('ify', function(){
|
||||
it('union', function(){
|
||||
var graph, prime;
|
||||
|
||||
graph = Gun.ify({a: false, b: true, c: 0, d: 1, e: '', f: 'g', h: null}).nodes;
|
||||
@ -60,4 +60,16 @@ describe('Gun', function(){
|
||||
Gun.union(graph, prime);
|
||||
});
|
||||
|
||||
it('path', function(done){
|
||||
this.timeout(9000);
|
||||
var gun = require('./shotgun');
|
||||
gun.load('email/mark@accelsor.com')
|
||||
.path('account.email')
|
||||
.get(function(val){
|
||||
console.log("val!", val);
|
||||
done();
|
||||
});
|
||||
console.log("________________________");
|
||||
});
|
||||
|
||||
});
|
@ -4,12 +4,12 @@ if(process.env.LIVE || (process.env.NODE_ENV === 'production')){
|
||||
//process.env['redis-install'] = '/tmp';
|
||||
} else {
|
||||
// Keys are hosted outside this folder, you must provide your own with environment variables.
|
||||
if((require('fs').existsSync||require('path').existsSync)(keys = '../../../../linux/.ssh/keys-gun.js')){
|
||||
if((require('fs').existsSync||require('path').existsSync)(keys = __dirname + '/../../../linux/.ssh/keys-gun.js')){
|
||||
keys = require(keys);
|
||||
}
|
||||
}
|
||||
|
||||
var Gun = require('../../shots2');
|
||||
var Gun = require('../shots2');
|
||||
var gun = Gun({
|
||||
peers: 'http://localhost:8888/gun'
|
||||
,s3: keys
|
@ -1,4 +1,4 @@
|
||||
module.exports=require('theory')
|
||||
module.exports=require('theory');
|
||||
('tests',function(a){
|
||||
if(root.node){
|
||||
console.log("tests live!");
|
||||
|
Loading…
x
Reference in New Issue
Block a user