get example on heroku

This commit is contained in:
Mark Nadal
2014-09-10 13:33:40 -07:00
parent 85697ed0c3
commit 30a75831fd
16 changed files with 319 additions and 152 deletions

View File

@@ -1 +1 @@
web: node init.js
web: node examples/admin/app.js

25
examples/admin/app.js Normal file
View File

@@ -0,0 +1,25 @@
console.log("If modules not found, run `npm install` in example/admin folder!");
var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || 8888;
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var Gun = require('gun');
var gun = Gun({
peers: 'http://localhost:' + port + '/gun'
,s3: require('../../test/shotgun') // replace this with your own keys!
});
app.use(express.static(__dirname))
.use(bodyParser.json())
.use(gun.server);
app.listen(port);
console.log('Express started on port ' + port + ' with /gun');
gun.load('blob/data', function(){ // ugly little idempotent initializer, in case no data is set
gun.set({_:{'#': "yVbyf7BqlXVQQUOE5cw9rf8h",'>':{hello: 1407328713707,from: 1407328713707}}, // this is an actual gun object, this won't overwrite any new changes
hello: "world",
from: "Mark Nadal"
}).key('blob/data');
});

View File

@@ -1,11 +0,0 @@
{
"_":{
"#":"yVbyf7BqlXVQQUOE5cw9rf8h",
">":{
"hello":1407328713707,
"from":1407328713707
}
},
"hello":"world",
"from":"Mark Nadal"
}

View File

@@ -3,9 +3,6 @@
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.js"></script>
<!--
<script src="https://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
-->
<script src="../../gun.js"></script>
</head>
<body ng-controller="editor">
@@ -37,9 +34,6 @@
<div ng-if="key != '_'">
<b>{{key}}</b>:
<span contenteditable="true" gun>{{val}}</span>
<!--
<br>{{key}}: {{val}}
-->
</div>
</li>
<li>
@@ -53,31 +47,32 @@
</li>
</ul>
<script>
gun = Gun('http://localhost:8888/gun');
angular.module('admin', [
]).controller('editor', function($scope){
$scope.data = {};
$scope.$data = gun.load('blob/data', function(data){
console.log("got it", data);
$scope.data = data;
$scope.$apply();
});
$scope.add = function(a,b,c){
$scope.$data.path($scope.field).set(
$scope.data[$scope.field] = 'value'
);
$scope.field = '';
};
window.$data = $scope.$data;
}).directive('gun', function(){
return function(scope, elem){
elem.on('keyup', function(){
scope.data[scope.key] = elem.text();
scope.$apply();
gun = Gun(['http://localhost:8888/gun', 'http://gunjs.herokuapp.com/gun']);
angular.module('admin', [
]).controller('editor', function($scope){
$scope.data = {};
$scope.$data = gun.load('blob/data', function(data){
$scope.data = data;
$scope.$apply();
});
};
});
$scope.add = function(a,b,c){
$scope.$data.path($scope.field).set(
$scope.data[$scope.field] = 'value'
);
$scope.field = '';
};
window.$data = $scope.$data;
}).directive('gun', function(){
return function(scope, elem){
elem.on('keyup', function(){
scope.$data.path(scope.key).set(
scope.data[scope.key] = elem.text()
);
scope.$apply();
});
};
});
</script>
</body>
</html>

View File

@@ -0,0 +1,9 @@
{
"name": "admin",
"main": "app.js",
"dependencies": {
"express": "~>4.9.0",
"body-parser": "~>1.8.1",
"gun": "~>0.0.2b"
}
}

1
examples/node_modules/gun/index.js generated vendored Normal file
View File

@@ -0,0 +1 @@
module.exports = require('../../shots');

View File

@@ -1,7 +1,11 @@
var fs = require('fs');
var http = require('http');
var qs = require('querystring');
var gun = require('../../test/shotgun');
var Gun = require('gun');
var gun = Gun({
peers: 'http://localhost:8888/gun'
,s3: require('../../test/shotgun') // replace this with your own keys!
});
http.route = function(url){
console.log(url);

View File

@@ -1,8 +1,12 @@
var sign = {};
var gun = require('../../test/shotgun');
var Gun = require('gun');
var gun = Gun({
peers: 'http://localhost:8888/gun'
,s3: require('../../test/shotgun') // replace this with your own keys!
});
sign.user = {}
sign.user.create = function(form, cb, shell){ // TODO: REDO THIS TO MATCH GUN
sign.user.create = function(form, cb, shell){
sign.crypto(form, function(err, user){
if(err || !user){ return cb(err) }
user = {key: user.key, salt: user.salt};
@@ -11,28 +15,9 @@ sign.user.create = function(form, cb, shell){ // TODO: REDO THIS TO MATCH GUN
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");
});
*/
sign.server = function(req, res){
console.log("sign.server", req.headers, req.body);
/*res.emit('data', {ok: 1});
res.emit('data', {ok: 2});
res.emit('data', {ok: 3});
res.emit('data', {ok: 4});
setTimeout(function(){
res.emit('end', {ok: 5});
}, 5000);
return;*/
if(!req.body || !req.body.email){ return res.emit('end', {err: "That email does not exist."}) }
var user = gun.load('email/' + req.body.email, function(data){ // this callback is called the magazine, since it holds the clip
console.log("data from key", data);

View File

@@ -33,7 +33,9 @@ b.forEach(function (user, i) {
user.friends = chance.shuffle(users).slice(chance.integer({ min: 20, max: (num < 120)? num : 120 }));
});
var gun = require('../test/shotgun');
var gun = require('gun')({
s3: require('../test/shotgun') // replace this with your own keys!
});
gun.set(b[0]);

View File

@@ -67,7 +67,7 @@
s.batch = s.batch || {};
if(s.batch[id]){ return s }
s.batch[id] = (s.batch[id] || 0) + 1;
console.log("no batch!", id);
console.log("no batch!");
s.S3().getObject(m, function(e,r){
var d, t, m, r = r || (this && this.httpResponse);
if(e || !r){ return s.own.on(id).emit(e) }

64
gate/s3pricing.html Normal file
View File

@@ -0,0 +1,64 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<style>
.table li {
float: left;
min-width: 200px;
max-width: 400px;
}
ul, li {
list-style: none;
}
.clear {
clear: both;
}
.none {
display: none;
}
</style>
<ul>
<li><ul class="table none">
<li>Seconds in month:</li>
<li><input type="number" value="2629743.83" id="sim"></li>
</ul></li>
<li class="clear"></li>
<li><ul class="table">
<li>Persist every seconds:</li>
<li><input type="number" value="15" id="se"></li>
</ul></li>
<li class="clear"></li>
<li><ul class="table">
<li>Over how many objects:</li>
<li><input type="number" value="100" id="o"></li>
</ul></li>
<li class="clear"></li>
<li><ul class="table">
<li>Cost $:</li>
<li><input type="number" value="" readonly id="r"></li>
</ul></li>
</ul>
<br>
<p>
This page is for throughput calculation, it assumes continuous load non-stop.
</p>
<script>
$(function(){
var sim = $('#sim')
, se = $('#se')
, o = $('#o')
, r = $('#r')
, n = function(n){ return parseFloat(n) }
$(document).on('keyup', function(){
r.val(
(( n(sim.val()) / n(se.val()) ) * n(o.val()) / 1000 * 0.005 ).toFixed(2)
);
})
})
</script>
</body>
</html>

162
gun.js
View File

@@ -9,53 +9,64 @@
Gun.is = function(gun){ return (gun instanceof Gun)? true : false }
Gun._ = {};
Gun.chain = Gun.prototype;
Gun.chain._ = {};
Gun.chain._.opt = {};
Gun.chain._.nodes = {};
Gun.chain._.chain = {};
Gun.chain._.trace = [];
Gun.chain._.keys = {};
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;
gun._ = gun._ || {};
gun.__ = gun.__ || {};
if(!opt){ return gun }
gun.__.opt = gun.__.opt || {};
gun.__.keys = gun.__.keys || {};
gun.__.nodes = gun.__.nodes || {};
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] }
if(Gun.list.is(opt.peers)){ opt.peers = Gun.obj.map(opt.peers, function(n,f,m){ m(n,{}) }) }
gun._.opt.peers = opt.peers || gun._.opt.peers || {};
gun._.opt.uuid = opt.uuid || gun._.opt.uuid || {};
gun._.opt.hook = gun._.opt.hook || {};
gun.__.opt.peers = opt.peers || gun.__.opt.peers || {};
gun.__.opt.uuid = opt.uuid || gun.__.opt.uuid || {};
gun.__.opt.hook = gun.__.opt.hook || {};
Gun.obj.map(opt.hook, function(h, f){
if(!Gun.fns.is(h)){ return }
gun._.opt.hook[f] = h;
gun.__.opt.hook[f] = h;
});
if(!stun){ Gun.on('init').emit(gun, opt) }
return gun;
}
Gun.chain.chain = function(from){
var gun = Gun();
from = from || this;
gun.__ = from.__;
gun._ = {};
Gun.obj.map(from._, function(val, field){
gun._[field] = val;
});
gun._.events = Gun.on.split(); // we want events per chain
gun._.events.trace = gun._.events.trace || 0;
gun._.events.at = gun._.events.at || 0;
return gun;
}
Gun.chain.load = function(key, cb, opt){
var gun = this;
var gun = this.chain();
cb = cb || function(){};
if(cb.node = gun._.keys[key]){ // set this to the current node, too!
if(cb.node = gun.__.keys[key]){ // set this to the current node, too!
Gun.log("from gun"); // remember to do all the same stack stuff here also!
return cb(Gun.obj.copy(gun._.node = cb.node)), gun; // TODO: BUG: This needs to be frozen/copied, and react the same as below!
}
cb.fn = function(){}
gun._.key = key;
// missing: hear shots!
if(Gun.fns.is(gun._.opt.hook.load)){
gun._.opt.hook.load(key, function(err, data){
if(Gun.fns.is(gun.__.opt.hook.load)){
gun.__.opt.hook.load(key, function(err, data){
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 = {}, 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);
node = gun._.keys[key] = gun._.nodes[data._[own.sym.id]];
cb(Gun.obj.copy(gun._.node = node));
gun._.events.on(gun._.events.at += 1).emit(node);
gun._.events.at = 0; // ???? reset it back once everything is done?
if(err){ return (gun._.dud||cb.fn)(err) }
if(!data){ return (gun._.blank||cb.fn)() }
var context = {nodes: {}};
context.nodes[data._[own.sym.id]] = data;
context = Gun.chain.set.now.union.call(gun, context.nodes); // data safely transformed
if(context.err){ return (gun._.dud||cb.fn)(context.err) }
gun._.node = gun.__.keys[key] = gun.__.nodes[data._[own.sym.id]];
cb(Gun.obj.copy(gun._.node));
gun._.events.on(gun._.events.at += 1).emit(gun._.node);
gun._.events.at = 0; // ???? reset it back once everything is done? the returns above don't allow for this.
}, opt);
} else {
Gun.log("Warning! You have no persistence layer to load from!");
@@ -65,9 +76,9 @@
Gun.chain.key = function(key, cb){ // TODO: Need to setImmediate if not loaded yet?
Gun.log("make key", key);
cb = cb || function(){};
this._.keys[key] = this._.node;
if(Gun.fns.is(this._.opt.hook.key)){
this._.opt.hook.key(key, this._.node, function(err, data){
this.__.keys[key] = this._.node;
if(Gun.fns.is(this.__.opt.hook.key)){
this.__.opt.hook.key(key, this._.node, function(err, data){
Gun.log("key made", key);
if(err){ return cb(err) }
return cb(null);
@@ -78,9 +89,9 @@
return this;
}
Gun.chain.path = function(path){ // The focal point follows the path
var gun = this;
var gun = this.chain();
path = path.split('.');
Gun.log("PATH stack trace", gun._.events.trace + 1);
Gun.log("PATH stack trace", gun._.events.trace + 1, 'was it before loaded?', this._);
gun._.events.on(gun._.events.trace += 1).event(function trace(node){
Gun.log("stack at", gun._.events.at);
if(!path.length){ // if the path resolves to another node, we finish here
@@ -104,9 +115,9 @@
}
}
});
if(gun._.loaded){
if(this._.loaded){ // this was the previous chain, gun is the new one
console.log("Send off!", gun._.events.at + 1);
gun._.events.on(gun._.events.at += 1).emit(gun._.node);
gun._.events.on(gun._.events.at += 1).emit(this._.node);
}
return gun;
}
@@ -130,7 +141,8 @@
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){ // TODO: set failed miserably to catch depth references in social tests
Gun.chain.set = function(val, cb, opt){ // TODO: set failed miserably to catch depth references in social tests
opt = opt || {};
var gun = this, set;
if(gun._.field){ // a field cannot be 0!
set = {}; // in case we are doing a set on a field, not on a node
@@ -144,10 +156,10 @@
if(set.err){ return cb(set.err), gun }
set = gun.set.now(set.nodes, Gun.time.is()); // set time state on nodes?
if(set.err){ return cb(set.err), gun }
Gun.union(gun._.nodes, set.nodes); // while this maybe should return a list of the nodes that were changed, we want to send the actual delta
gun._.node = gun._.nodes[cb.root._[own.sym.id]] || cb.root; // TODO? Maybe BUG! if val is a new node on a field, _.node should now be that! Or will that happen automatically?
if(Gun.fns.is(gun._.opt.hook.set)){
gun._.opt.hook.set(set.nodes, function(err, data){ // now iterate through those nodes to S3 and get a callback once all are saved
Gun.union(gun.__.nodes, set.nodes); // while this maybe should return a list of the nodes that were changed, we want to send the actual delta
gun._.node = gun.__.nodes[cb.root._[own.sym.id]] || cb.root; // TODO? Maybe BUG! if val is a new node on a field, _.node should now be that! Or will that happen automatically?
if(Gun.fns.is(gun.__.opt.hook.set)){
gun.__.opt.hook.set(set.nodes, function(err, data){ // now iterate through those nodes to S3 and get a callback once all are saved
Gun.log("gun set hook callback called");
if(err){ return cb(err) }
return cb(null);
@@ -174,15 +186,34 @@
});
return context;
}
Gun.chain.set.now.union = function(prime){
var gun = Gun.is(this)? this : null
, context = {nodes: {}};
if(!gun){
context.err = {err: "No gun instance!", corrupt: true};
return context;
}
Gun.obj.map(prime, function(node){
var set = Gun.ify.call(gun, node);
if(set.err){ return context.err = set.err }
Gun.obj.map(set.nodes, function(node, id){
context.nodes[id] = node;
console.log("Gun set.now.union ----->", node);
});
});
if(context.err){ return context }
Gun.union(gun.__.nodes, context.nodes); // need to move good primes onto context.nodes;
return context;
}
Gun.chain.match = function(){ // same as path, except using objects
return this;
}
Gun.chain.blank = function(blank){
this._.chain.blank = Gun.fns.is(blank)? blank : function(){};
this._.blank = Gun.fns.is(blank)? blank : function(){};
return this;
}
Gun.chain.dud = function(dud){
this._.chain.dud = Gun.fns.is(dud)? dud : function(){};
this._.dud = Gun.fns.is(dud)? dud : function(){};
return this;
}
Gun.fns = {};
@@ -311,11 +342,11 @@
}());
Gun.roulette = function(l, c){
var gun = Gun.is(this)? this : {};
if(gun._ && gun._.opt && gun._.opt.uuid){
if(Gun.fns.is(gun._.opt.uuid)){
return gun._.opt.uuid(l, c);
if(gun._ && gun.__.opt && gun.__.opt.uuid){
if(Gun.fns.is(gun.__.opt.uuid)){
return gun.__.opt.uuid(l, c);
}
l = l || gun._.opt.uuid.length;
l = l || gun.__.opt.uuid.length;
}
return Gun.text.random(l, c);
}
@@ -379,6 +410,7 @@
var serverState = Gun.time.is();
// add more checks?
var state = HAM(serverState, deltaStates[field], states[field], deltaValue, current[field]);
console.log("HAM:", field, deltaValue, deltaStates[field], current[field], 'the', state, (deltaStates[field] - serverState));
if(state.err){
Gun.log(".!HYPOTHETICAL AMNESIA MACHINE ERR!.", state.err);
return;
@@ -428,7 +460,7 @@
}
}({}));
;(function(Serializer){
Gun.ify = function(data, gun){ // TODO: BUG: Modify lists to include HAM state
Gun.ify = function(data){ // TODO: BUG: Modify lists to include HAM state
var gun = Gun.is(this)? this : {}
, context = {
nodes: {}
@@ -586,7 +618,7 @@
Page.load = function(key, cb, opt){
cb = cb || function(){};
opt = opt || {};
Gun.obj.map(gun._.opt.peers, function(peer, url){
Gun.obj.map(gun.__.opt.peers, function(peer, url){
Page.ajax(url + '/' + key, null, function(data){
Gun.log('via', url, key, data);
// alert(data + data.hello + data.from + data._);
@@ -594,8 +626,18 @@
});
});
}
Page.set = function(nodes, cb){
cb = cb || function(){};
// TODO: batch and throttle later.
console.log('ajax set', nodes);
Gun.obj.map(gun.__.opt.peers, function(peer, url){
Page.ajax(url, nodes, function(reply){
console.log("set confirmed?", reply);
});
});
}
Page.ajax =
this.ajax =
window.ajax =
function(url, data, cb, opt){
/*
via Sockjs@1.0.0
@@ -611,6 +653,8 @@
data = u;
} else {
try{data = JSON.stringify(data);
opt.headers = opt.headers || {};
opt.headers["Content-Type"] = "application/json;charset=utf-8";
}catch(e){}
}
opt.method = (data? 'POST' : 'GET');
@@ -686,11 +730,6 @@
if(opt.cookies || opt.credentials || opt.withCredentials){
opt.xhr.withCredentials = true;
}
try{opt.xhr.open(opt.method, url, true);
} catch(e) {
opt.error();
return;
}
opt.xhr.onreadystatechange = function(){
if(!opt.xhr){ return }
var reply, status;
@@ -708,12 +747,29 @@
opt.done(false);
}
}
try{opt.xhr.open(opt.method, url, true);
} catch(e) {
opt.error();
return;
}
if(opt.headers){
try{for(var i in opt.headers){
if(opt.headers.hasOwnProperty(i)){
opt.xhr.setRequestHeader(i, opt.headers[i]);
}
}
} catch(e) {
opt.error();
return;
}
}
try{opt.xhr.send(data);
}catch(e){
opt.error();
}
return opt;
}
gun._.opt.hook.load = gun._.opt.hook.load || Page.load;
gun.__.opt.hook.load = gun.__.opt.hook.load || Page.load;
gun.__.opt.hook.set = gun.__.opt.hook.set || Page.set;
});
}({}));

View File

@@ -1,5 +1,5 @@
{ "name": "gun"
, "version": "0.0.2a"
, "version": "0.0.2b"
, "author": "Mark Nadal"
, "description": "Graph engine."
, "engines": {
@@ -9,6 +9,8 @@
"mime": "~>1.2.11",
"aws-sdk": "~>2.0.0",
"request": "~>2.39.0"
,"express": "~>4.9.0","body-parser": "~>1.8.1"
}
, "devDependencies": {
"chance": "~>2.39.0"

View File

@@ -4,52 +4,83 @@
, url = require('url')
, meta = {};
Gun.on('init').event(function(gun, opt){
gun.server = gun.server || function(req, res){ // where is the data? is it JSON? declare contentType=JSON from client?
console.log("gun server has requests!", req.headers, req.body, req.url, req.method);
gun.server = gun.server || function(req, res, next){ // where is the data? is it JSON? declare contentType=JSON from client?
/*meta.CORS(req, res);
res.emit('data', {way: 'cool'});
res.emit('data', {shish: 'kabob'});
res.emit('data', {I: 'love'});
res.end();
return;*/
if(!req || !res){ return }
if(!req.url){ return }
if(!req.method){ return }
next = next || function(){};
if(!req || !res){ return next() }
if(!req.url){ return next() }
if(!req.method){ return next() }
var tmp = {};
tmp.url = url.parse(req.url, true);
if(!gun.server.regex.test(tmp.url.pathname)){ return }
tmp.key = tmp.url.pathname.replace(gun.server.regex,'').replace(/^\//i,''); // strip the base
if(!tmp.key){
return meta.JSON(res, {gun: true});
if(!gun.server.regex.test(tmp.url.pathname)){ return next() }
tmp.key = tmp.url.pathname.replace(gun.server.regex,'') || '';
if(tmp.key.toLowerCase() === '.js'){
res.writeHead(200, {'Content-Type': 'text/javascript'});
res.end(gun.server.js = gun.server.js || require('fs').readFileSync(__dirname + '/gun.js'));
return;
}
if('get' === req.method.toLowerCase()){ // get is used as subscribe
// raw test for now:
s3.load(tmp.key, function(err, data){
console.log("\ngun server has requests!", req.method, req.url, req.headers, req.body);
tmp.key = tmp.key.replace(/^\//i,'') || ''; // strip the base
tmp.method = (req.method||'').toLowerCase();
if('get' === tmp.method){ // get is used as subscribe
if(!tmp.key){
return meta.JSON(res, {gun: true});
}
// raw test for now, no auth:
gun.load(tmp.key, function(err, data){
console.log("gun subscribed!", err, data);
meta.CORS(req, res);
return meta.JSON(res, data || err);
})
} else
if('post' === req.method.toLowerCase()){ // post is used as patch, sad that patch has such poor support
if('post' === tmp.method || 'patch' === tmp.method){ // post is used as patch, sad that patch has such poor support
if(!req.body){
console.log("Warn: No body on POST?");
}
// raw test for now, no auth:
// should probably load all the nodes first?
var context = Gun.chain.set.now.union.call(gun, req.body); // data safely transformed
if(context.err){
return meta.JSON(res, context.err); // need to standardize errors more
}
console.log("-------- union ---------");Gun.obj.map(gun.__.nodes, function(node){ console.log(node); });console.log("------------------------");
/*
WARNING! TODO: BUG! Do not send OK confirmation if amnesiaQuaratine is activated! Not until after it has actually been processed!!!
*/
if(Gun.fns.is(gun.__.opt.hook.set)){
gun.__.opt.hook.set(context.nodes, function(err, data){ // now iterate through those nodes to S3 and get a callback once all are saved
if(err){
return meta.JSON(res, {err: err}); // server should handle the error for the client first! Not force client to re-attempt.
}
meta.JSON(res, {ok: 1}); // need to standardize OKs, OK:1 not good.
});
} else {
context.err = "Warning! You have no persistence layer to save to!";
Gun.log(context.err);
}
}
}
gun.server.regex = /^\/gun/i;
var s3 = gun._.opt.s3 = gun._.opt.s3 || S3(opt && opt.s3);
s3.path = s3.path || opt.s3.path || '';
s3.keyed = s3.keyed || opt.s3.keyed || '';
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.keepMaxSockets){ require('https').globalAgent.maxSockets = require('http').globalAgent.maxSockets = Infinity } // WARNING: Document this!
var s3 = gun.__.opt.s3 = gun.__.opt.s3 || S3(opt && opt.s3);
s3.prefix = s3.prefix || opt.s3.prefix || '';
s3.prekey = s3.prekey || opt.s3.prekey || '';
s3.prenode = s3.prenode || opt.s3.prenode || '_/nodes/';
gun.__.opt.batch = opt.batch || gun.__.opt.batch || 10;
gun.__.opt.throttle = opt.throttle || gun.__.opt.throttle || 2;
if(!gun.__.opt.keepMaxSockets){ require('https').globalAgent.maxSockets = require('http').globalAgent.maxSockets = Infinity } // WARNING: Document this!
s3.load = s3.load || function(key, cb, opt){
cb = cb || function(){};
opt = opt || {};
if(opt.id){
key = s3.path + s3.nodes + key;
key = s3.prefix + s3.prenode + key;
} else {
key = s3.path + s3.keyed + key;
key = s3.prefix + s3.prekey + key;
}
s3.get(key, function(err, data, text, meta){
console.log('via s3', key);
@@ -83,13 +114,13 @@
}
});
});
if(gun._.opt.batch < s3.batching){
if(gun.__.opt.batch < s3.batching){
return s3.set.now();
}
if(!gun._.opt.throttle){
if(!gun.__.opt.throttle){
return s3.set.now();
}
s3.wait = s3.wait || setTimeout(s3.set.now, gun._.opt.throttle * 1000); // in seconds
s3.wait = s3.wait || setTimeout(s3.set.now, gun.__.opt.throttle * 1000); // in seconds
}
s3.set.now = s3.set.now || function(){
clearTimeout(s3.wait);
@@ -99,8 +130,8 @@
, batch = s3.batch[s3.next];
s3.next = Gun.time.is();
Gun.obj.map(batch, function put(exists, id){
var node = gun._.nodes[id]; // the batch does not actually have the nodes, but what happens when we do cold data? Could this be gone?
s3.put(s3.path + s3.nodes + id, node, function(err, reply){
var node = gun.__.nodes[id]; // the batch does not actually have the nodes, but what happens when we do cold data? Could this be gone?
s3.put(s3.prefix + s3.prenode + id, node, function(err, reply){
console.log("s3 put reply", id, err, reply);
if(err || !reply){
put(exists, id); // naive implementation of retry TODO: BUG: need backoff and anti-infinite-loop!
@@ -123,7 +154,7 @@
if(!id){
return cb({err: "No ID!"});
}
s3.put(s3.path + s3.keyed + key, '', function(err, reply){ // key is 2 bytes??? Should be smaller
s3.put(s3.prefix + s3.prekey + key, '', function(err, reply){ // key is 2 bytes??? Should be smaller
console.log("s3 put reply", id, err, reply);
if(err || !reply){
s3.key(key, node, cb); // naive implementation of retry TODO: BUG: need backoff and anti-infinite-loop!

View File

@@ -62,7 +62,9 @@ describe('Gun', function(){
it('path', function(done){
this.timeout(9000);
var gun = require('./shotgun');
var gun = require('gun')({
s3: require('./shotgun') // replace this with your own keys!
});
gun.load('d1ed426098eae2bba8c60605e1e4552f66281770', null, {id: true}) // get Rodney Morris
.path('parent.parent.first') // Rodney's parent is Juan Colon, whose parent is Francis Peters
.get(function(val){

View File

@@ -1,7 +1,6 @@
var keys;
if(process.env.LIVE || (process.env.NODE_ENV === 'production')){
// Keys are provided by environment configs on the server
//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 = __dirname + '/../../../linux/.ssh/keys-gun.js')){
@@ -9,10 +8,13 @@ if(process.env.LIVE || (process.env.NODE_ENV === 'production')){
}
}
module.exports = keys || {};
/*
var Gun = require('../shots');
var gun = Gun({
peers: 'http://localhost:8888/gun'
,s3: keys
});
module.exports = gun;
module.exports = gun;
*/