feat: save/restore database snapshots (#78)

This commit is contained in:
Richard Ramos 2020-03-20 12:56:57 -04:00 committed by GitHub
parent e9c71c1d71
commit ada876dec7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 8 deletions

View File

@ -41,9 +41,8 @@ class Database {
} }
databaseInitialize(cb) { databaseInitialize(cb) {
// TODO: save in the db results by using a combination of concatMap and scan, to save results in batches
fromEvent(this.events, "updateDB").subscribe(({eventKey, eventData}) => { fromEvent(this.events, "updateDB").subscribe(({eventKey, eventData}) => {
if (eventData.removed) { if (eventData.removed) {
this.deleteEvent(eventKey, eventData.id); this.deleteEvent(eventKey, eventData.id);
return; return;
} }
@ -56,6 +55,25 @@ class Database {
}); });
} }
serialize() {
return this.db.serialize();
}
restore(serializedDb, forced) {
return new Promise((resolve, reject) => {
const collections = this.db.listCollections();
if (!collections?.length || forced) {
this.db.loadJSON(serializedDb);
this.db.saveDatabase(err => {
if(err) {
reject(err);
}
resolve();
});
}
});
}
getLastKnownEvent(eventKey) { getLastKnownEvent(eventKey) {
const collection = this.db.getCollection(eventKey); const collection = this.db.getCollection(eventKey);
if (collection?.count()) { if (collection?.count()) {
@ -99,9 +117,10 @@ class Database {
deleteEvent(eventKey, eventId) { deleteEvent(eventKey, eventId) {
const collection = this.db.getCollection(eventKey); const collection = this.db.getCollection(eventKey);
if (collection) if (collection)
collection.chain() collection
.find({id: eventId}) .chain()
.remove(); .find({id: eventId})
.remove();
} }
deleteNewestBlocks(eventKey, gteBlockNum) { deleteNewestBlocks(eventKey, gteBlockNum) {
@ -109,9 +128,10 @@ class Database {
const collection = this.db.getCollection(eventKey); const collection = this.db.getCollection(eventKey);
if (collection) if (collection)
collection.chain() collection
.find({blockNumber: {$gte: gteBlockNum}}) .chain()
.remove(); .find({blockNumber: {$gte: gteBlockNum}})
.remove();
} }
} }

View File

@ -33,6 +33,7 @@ export default class Subspace {
this.options.callInterval = options.callInterval; this.options.callInterval = options.callInterval;
this.options.dbFilename = options.dbFilename ?? "subspace.db"; this.options.dbFilename = options.dbFilename ?? "subspace.db";
this.options.disableDatabase = options.disableDatabase; this.options.disableDatabase = options.disableDatabase;
this.options.snapshot = options.snapshot;
this.networkId = undefined; this.networkId = undefined;
this.isWebsocketProvider = options.disableSubscriptions ? false : !!web3?.currentProvider?.on; this.isWebsocketProvider = options.disableSubscriptions ? false : !!web3?.currentProvider?.on;
@ -44,6 +45,11 @@ export default class Subspace {
} else { } else {
this._db = new Database(this.options.dbFilename, this.events); this._db = new Database(this.options.dbFilename, this.events);
} }
if(this.options.snapshot) {
await this._db.restore(this.options.snapshot);
}
this.eventSyncer = new EventSyncer(this.web3.eth, this.events, this._db, this.isWebsocketProvider); this.eventSyncer = new EventSyncer(this.web3.eth, this.events, this._db, this.isWebsocketProvider);
this.logSyncer = new LogSyncer(this.web3.eth, this.events, this._db); this.logSyncer = new LogSyncer(this.web3.eth, this.events, this._db);
@ -308,4 +314,12 @@ export default class Subspace {
close() { close() {
this.eventSyncer.close(); this.eventSyncer.close();
} }
snapshot() {
return this._db.serialize();
}
async loadSnapshot(serializedDb) {
return this._db.restore(serializedDb, true);
}
} }

View File

@ -19,6 +19,8 @@ export default class Subspace {
trackGasPrice(): Observable<string>; trackGasPrice(): Observable<string>;
trackAverageBlocktime(): Observable<number>; trackAverageBlocktime(): Observable<number>;
close(): void; close(): void;
snapshot(): string;
async loadSnapshot(serializedDb: string): void;
} }
export interface ContractLike { export interface ContractLike {