Create deltas class, mature multiwrite for retries

master
Bel LaPointe 2021-02-26 23:02:05 -06:00
parent fc438a55f8
commit da08be0285
1 changed files with 116 additions and 11 deletions

View File

@ -1106,7 +1106,7 @@
</head> </head>
<body> <body>
<div class=logo> <div class=logo>
<a href=https://nullboard.io>Nullboard</a> <a href=https://nullboard.io>Nullboard <span id="pending"></span></a>
<div class=bulk> <div class=bulk>
<a href=# class=view-about>About</a> <a href=# class=view-about>About</a>
<a href=# class=view-license>License</a> <a href=# class=view-license>License</a>
@ -1237,6 +1237,38 @@
} }
} }
class Deltas {
constructor(database)
{
this.database = new NamespacedDatabase("deltas", database);
}
length()
{
var n = 0;
this.database.forEach((k) => { n += 1; });
return n;
}
push(key)
{
this.database.set(key, 1);
}
pop(key)
{
this.database.del(key);
}
popEach(foo)
{
this.database.forEach((key) => {
foo(key);
this.database.del(key);
});
}
}
class MultiDatabase extends Database { class MultiDatabase extends Database {
constructor() constructor()
{ {
@ -1250,24 +1282,97 @@
{ {
this.databases.push(arguments[i]); this.databases.push(arguments[i]);
} }
this.deltas = new Deltas(this.primary());
this.scheduleSync();
}
primary()
{
return this.databases[0];
}
replicas()
{
return this.databases.slice(1);
}
scheduleSync()
{
setInterval(() => { this.sync(); }, 15 * 1000);
}
sync()
{
console.log("syncing to replicas: " + this.pendingSyncCount());
this.deltas.popEach((k) => {
console.log("syncing to replicas: " + k);
this.replicate(k);
});
console.log("synced to replicas: " + this.pendingSyncCount());
this.writePendingSyncCount();
}
pendingSyncCount()
{
return this.deltas.length();
}
writePendingSyncCount()
{
var n = this.pendingSyncCount();
var s = "(" + n + ")";
if (! n)
s = ""
document.getElementById("pending").innerHTML = s;
}
replicate(k)
{
var v = this.primary().get(k);
this.replicas().forEach((database) => {
if (v)
database.set(k, v);
else
database.del(k, v);
});
} }
get(key) { get(key) {
return this.databases[0].get(key); return this.primary().get(key);
} }
set(key, value) set(key, value)
{ {
this.databases.forEach((database) => { this.primary().set(key, value);
this.deltas.push(key);
try
{
this.replicas().forEach((database) => {
database.set(key, value); database.set(key, value);
}); });
this.deltas.pop(key);
}
catch (e)
{
console.log("failed to replicate set: " + e);
}
} }
del(key) del(key)
{ {
this.databases.forEach((database) => { this.primary().del(key);
database.del(key, value); this.deltas.push(key);
try
{
this.replicas().forEach((database) => {
database.del(key);
}); });
this.deltas.pop(key);
}
catch (e)
{
console.log("failed to replicate del: " + e);
}
} }
forEach(foo) forEach(foo)
@ -1290,7 +1395,7 @@
{ {
if (key.startsWith(this.namespace + ".")) if (key.startsWith(this.namespace + "."))
return key.slice(this.namespace.length + 1); return key.slice(this.namespace.length + 1);
return key; return null;
} }
prefix(key) prefix(key)
@ -1319,6 +1424,7 @@
{ {
this.database.forEach((key) => { this.database.forEach((key) => {
var k = this.deprefix(key); var k = this.deprefix(key);
if (k)
foo(k); foo(k);
}); });
} }
@ -1367,7 +1473,6 @@
new NamespacedDatabase("A", new Local()), new NamespacedDatabase("A", new Local()),
new NamespacedDatabase("B", new Local()), new NamespacedDatabase("B", new Local()),
); );
globalStorage = new NamespacedDatabase("B", new Local());
/* /*
* poor man's error handling -- $fixme * poor man's error handling -- $fixme