RAD indexedDB!

This commit is contained in:
Mark Nadal 2018-08-24 03:06:12 -07:00
parent 7ab41c02d0
commit aee20ebbc3
3 changed files with 139 additions and 101 deletions

35
gun.js
View File

@ -883,7 +883,7 @@
Gun.log.once("welcome", "Hello wonderful person! :) Thanks for using GUN, feel free to ask for help on https://gitter.im/amark/gun and ask StackOverflow questions tagged with 'gun'!");
;"Please do not remove these messages unless you are paying for a monthly sponsorship, thanks!";
if(typeof window !== "undefined"){ window.Gun = Gun }
if(typeof window !== "undefined"){ (window.Gun = Gun).window = window }
try{ if(typeof common !== "undefined"){ common.exports = Gun } }catch(e){}
module.exports = Gun;
@ -1787,24 +1787,21 @@
// 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)) || {};
//if(false === opt.localStorage){ return ev.next(root) } // we want offline resynce queue regardless!
opt.prefix = opt.file || 'gun/';
var gap = Gun.obj.ify(store.getItem('gap/'+opt.prefix)) || {};
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]);
});
var disk = Gun.obj.ify(store.getItem(opt.prefix)) || {}, 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.$});
},10);
});
setTimeout(function(){
root.on('out', {put: send, '#': root.ask(ack), I: root.$});
},10);
}
root.on('out', function(msg){
@ -1842,7 +1839,7 @@
var flush = function(){
clearTimeout(to);
to = false;
try{store.setItem('gap/'+opt.file, JSON.stringify(gap));
try{store.setItem('gap/'+opt.prefix, JSON.stringify(gap));
}catch(e){ Gun.log(err = e || "localStorage failure") }
}
});
@ -1852,9 +1849,9 @@
var opt = root.opt;
if(root.once){ return }
if(false === opt.localStorage){ return }
opt.file = opt.file || opt.prefix || 'gun/'; // support old option name.
opt.prefix = opt.file || 'gun/';
var graph = root.graph, acks = {}, count = 0, to;
var disk = Gun.obj.ify(store.getItem(opt.file)) || {};
var disk = Gun.obj.ify(store.getItem(opt.prefix)) || {};
var lS = function(){}, u;
root.on('localStorage', disk); // NON-STANDARD EVENT!
@ -1902,10 +1899,10 @@
var ack = acks;
acks = {};
if(data){ disk = data }
try{store.setItem(opt.file, JSON.stringify(disk));
try{store.setItem(opt.prefix, JSON.stringify(disk));
}catch(e){
Gun.log(err = e || "localStorage failure");
root.on('localStorage:error', {err: err, file: opt.file, flush: disk, retry: flush});
root.on('localStorage:error', {err: err, file: opt.prefix, flush: disk, retry: flush});
}
if(!err && !Gun.obj.empty(opt.peers)){ return } // only ack if there are no peers.
Gun.obj.map(ack, function(yes, id){

View File

@ -1,87 +1,103 @@
function Store(opt){
opt = opt || {};
opt.file = String(opt.file || 'radata');
var db = null;
;(function(){
var Gun = (typeof window !== "undefined")? window.Gun : require('../gun');
// Initialize indexedDB. Version 1.
const request = window.indexedDB.open(opt.file, 1)
Gun.on('create', function(root){
this.to.next(root);
root.opt.store = root.opt.store || Store(root.opt);
});
// Create schema. onupgradeneeded is called only when DB is first created or when the DB version increases.
request.onupgradeneeded = function(event){
const db = event.target.result;
db.createObjectStore(opt.file);
function Store(opt){
opt = opt || {};
opt.file = String(opt.file || 'radata');
var db = null;
opt.indexedDB = opt.indexedDB || window.indexedDB;
// Initialize indexedDB. Version 1.
var request = opt.indexedDB.open(opt.file, 1)
// Create schema. onupgradeneeded is called only when DB is first created or when the DB version increases.
request.onupgradeneeded = function(event){
var db = event.target.result;
db.createObjectStore(opt.file);
}
// onsuccess is called when the DB is ready.
request.onsuccess = function(){
db = request.result;
}
request.onerror = function(event){
console.log('ERROR: RAD IndexedDB generic error:', event);
};
var store = function Store(){}, u;
store.put = function(file, data, cb){
cb = cb || function(){};
if(!db){
var es = 'ERROR: RAD IndexedDB not yet ready.'
console.log(es);
cb(es, undefined);
} else {
// Start a transaction. The transaction will be automaticallt closed when the last success/error handler took no new action.
var transaction = db.transaction([opt.file], 'readwrite');
// Add or update data.
var radStore = transaction.objectStore(opt.file);
var putRequest = radStore.put(data, file);
putRequest.onsuccess = radStore.onsuccess = transaction.onsuccess = function(){
//console.log('RAD IndexedDB put transaction was succesful.');
cb(null, 1);
};
putRequest.onabort = radStore.onabort = transaction.onabort = function(){
var es = 'ERROR: RAD IndexedDB put transaction was aborted.';
console.log(es);
cb(es, undefined);
};
putRequest.onerror = radStore.onerror = transaction.onerror = function(event){
var es = 'ERROR: RAD IndexedDB put transaction was in error: ' + JSON.stringify(event)
console.log(es);
cb(es, undefined);
};
}
};
store.get = function(file, cb){
cb = cb || function(){};
if(!db){
var es = 'ERROR: RAD IndexedDB not yet ready.';
console.log(es);
cb(es, undefined);
} else {
// Start a transaction. The transaction will be automaticallt closed when the last success/error handler took no new action.
var transaction = db.transaction([opt.file], 'readwrite');
// Read data.
var radStore = transaction.objectStore(opt.file);
var getRequest = radStore.get(file);
getRequest.onsuccess = function(){
//console.log('RAD IndexedDB get transaction was succesful.');
cb(null, getRequest.result);
};
getRequest.onabort = function(){
var es = 'ERROR: RAD IndexedDB get transaction was aborted.';
console.log(es);
cb(es, undefined);
};
getRequest.onerror = function(event){
var es = 'ERROR: RAD IndexedDB get transaction was in error: ' + JSON.stringify(event)
console.log(es);
cb(es, undefined);
};
}
};
return store;
}
// onsuccess is called when the DB is ready.
request.onsuccess = function(){
db = request.result;
if(Gun.window){
Gun.window.RindexedDB = Store;
} else {
module.exports = Store;
}
request.onerror = function(event){
console.log('ERROR: RAD IndexedDB generic error:', event);
};
var store = function Store(){}, u;
store.put = function(file, data, cb){
cb = cb || function(){};
if(!db){
const es = 'ERROR: RAD IndexedDB not yet ready.'
console.log(es);
cb(es, undefined);
} else {
// Start a transaction. The transaction will be automaticallt closed when the last success/error handler took no new action.
const transaction = db.transaction([opt.file], 'readwrite');
// Add or update data.
const radStore = transaction.objectStore(opt.file);
const putRequest = radStore.put(data, file);
putRequest.onsuccess = radStore.onsuccess = transaction.onsuccess = function(){
console.log('RAD IndexedDB put transaction was succesful.');
cb(null, 1);
};
putRequest.onabort = radStore.onabort = transaction.onabort = function(){
const es = 'ERROR: RAD IndexedDB put transaction was aborted.';
console.log(es);
cb(es, undefined);
};
putRequest.onerror = radStore.onerror = transaction.onerror = function(event){
const es = 'ERROR: RAD IndexedDB put transaction was in error: ' + JSON.stringify(event)
console.log(es);
cb(es, undefined);
};
}
};
store.get = function(file, cb){
cb = cb || function(){};
if(!db){
const es = 'ERROR: RAD IndexedDB not yet ready.';
console.log(es);
cb(es, undefined);
} else {
// Start a transaction. The transaction will be automaticallt closed when the last success/error handler took no new action.
const transaction = db.transaction([opt.file], 'readwrite');
// Read data.
const radStore = transaction.objectStore(opt.file);
const getRequest = radStore.get(file);
getRequest.onsuccess = function(){
console.log('RAD IndexedDB get transaction was succesful.');
cb(null, getRequest.result);
};
getRequest.onabort = function(){
const es = 'ERROR: RAD IndexedDB get transaction was aborted.';
console.log(es);
cb(es, undefined);
};
getRequest.onerror = function(event){
const es = 'ERROR: RAD IndexedDB get transaction was in error: ' + JSON.stringify(event)
console.log(es);
cb(es, undefined);
};
}
};
return store;
}
}());

25
test/tmp/indexedDB.html Normal file
View File

@ -0,0 +1,25 @@
<h1>RindexedDB</h1>
<script src="../../examples/jquery.js"></script>
<script src="../../gun.js"></script>
<script src="../../lib/radix.js"></script>
<script src="../../lib/radisk.js"></script>
<script src="../../lib/store.js"></script>
<script src="../../lib/rindexed.js"></script>
<button onclick="var i = 0; window.TO = setInterval(function(){ gun.get(Gun.text.random(3)).put({a: ++i}) }, 0);">start</button>
<button onclick="clearTimeout(window.TO);">end</button>
<br/><br/>
<button onclick="gun.get('a').put({b: Gun.text.random(900)});setTimeout(function(){gun.get('x').put({y: Gun.text.random(900)});},1000);">write</button>
<button id='read' onclick="console.debug.i=1;gun.get('a').once(d => console.log(1, d));gun.get('x').once(d => console.log(2, d));">read</button>
<script>
localStorage.clear();
var opt = {localStorage: false, chunk: 1024, batch: 100};
opt.store = RindexedDB(opt);
var gun = Gun(opt);
//setTimeout(function(){ $('#read').trigger('click') });
</script>