@x5e/gink
Version:
an eventually consistent database
116 lines (103 loc) • 3.6 kB
text/typescript
import { Database } from "./Database";
import { Container } from "./Container";
import { Muid, AsOf, Meta, Bundler } from "./typedefs";
import { Behavior } from "./builders";
import { entryToEdgeData, muidTupleToMuid } from "./utils";
import { Edge } from "./Edge";
export class Vertex extends Container {
private constructor(database: Database, address: Muid) {
super(database, address, Behavior.VERTEX);
}
static get(database?: Database, muid?: Muid): Vertex {
database = database || Database.recent;
if (!muid) {
muid = { timestamp: -1, medallion: -1, offset: Behavior.VERTEX };
}
return new Vertex(database, muid);
}
static async create(database?: Database, meta?: Meta): Promise<Vertex> {
database = database || Database.recent;
const muid = await Container.addContainer({
behavior: Behavior.VERTEX,
database,
meta,
});
return new Vertex(database, muid);
}
toJson(
indent: number | boolean,
asOf?: AsOf,
seen?: Set<string>,
): Promise<string> {
throw new Error("toJson not implemented for Vertex");
}
/**
* Returns a promise that resolves to true showing if this placeholder is/was visible at the
* specified time (default now), or false if it was softly deleted.
* @returns undefined, a basic value, or a container
*/
async isAlive(asOf?: AsOf): Promise<boolean> {
const entry = await this.database.store.getEntryByKey(
this.address,
undefined,
asOf,
);
return entry === undefined || !entry.deletion;
}
public async size(asOf?: AsOf): Promise<number> {
return (await this.isAlive(asOf)) ? 1 : 0;
}
/**
* Performs a soft delete of this graph node.
*/
async remove(meta?: Meta): Promise<Muid> {
return this.addEntry(undefined, Container.DELETION, meta);
}
async revive(meta?: Meta): Promise<Muid> {
return this.addEntry(undefined, Container.INCLUSION, meta);
}
async reset(toTime?: AsOf, recurse?, meta?: Meta): Promise<void> {
const bundler: Bundler = await this.database.startBundle(meta);
if (!toTime) {
await this.remove(meta);
} else {
const aliveThen = await this.isAlive(toTime);
const aliveNow = await this.isAlive();
if (aliveThen !== aliveNow) {
if (aliveThen) {
await this.revive({ bundler });
} else {
await this.remove({ bundler });
}
}
}
if (!meta?.bundler) {
await bundler.commit();
}
}
async getEdgesFrom(asOf?: AsOf) {
return this.getEdges(true, asOf);
}
async getEdgesTo(asOf?: AsOf) {
return this.getEdges(false, asOf);
}
async getEdges(source: boolean, asOf?: AsOf): Promise<Edge[]> {
const entries = await this.database.store.getEntriesBySourceOrTarget(
this.address,
source,
asOf,
);
const edges: Edge[] = [];
for (let i = 0; i < entries.length; i++) {
const entry = entries[i];
if (entry.behavior !== Behavior.EDGE_TYPE) continue;
const edge = Edge.get(
this.database,
muidTupleToMuid(entry.entryId),
entryToEdgeData(entry),
);
edges.push(edge);
}
return edges;
}
}