@x5e/gink
Version:
an eventually consistent database
116 lines (103 loc) • 3.65 kB
text/typescript
import { Addressable } from "./Addressable";
import { Database } from "./Database";
import {
AsOf,
EdgeData,
Muid,
Value,
Timestamp,
Bundler,
Meta,
} from "./typedefs";
import { Vertex } from "./Vertex";
import { EdgeType } from "./EdgeType";
import { entryToEdgeData } from "./utils";
import { movementHelper } from "./store_utils";
import { Behavior } from "./builders";
export class Edge extends Addressable {
private source: Muid;
private target: Muid;
private action: Muid;
private value?: Value;
private constructor(
readonly database: Database,
address: Muid,
) {
super(address);
}
static get(database: Database, muid: Muid, data: EdgeData) {
const edge = new Edge(database, muid);
edge.setFromEdgeData(data);
return edge;
}
private setFromEdgeData(data: EdgeData) {
this.source = data.source;
this.target = data.target;
this.action = data.etype ?? {
timestamp: -1,
medallion: -1,
offset: Behavior.EDGE_TYPE,
};
this.value = data.value;
}
static async load(database: Database, address: Muid): Promise<Edge> {
const entry = await database.store.getEntryById(
address,
address.timestamp + 1,
);
if (!entry) {
throw new Error("edge not found");
}
const edge = new Edge(database, address);
edge.setFromEdgeData(entryToEdgeData(entry));
return edge;
}
getSourceVertex(): Vertex {
return Vertex.get(this.database, this.source);
}
getTargetVertex(): Vertex {
return Vertex.get(this.database, this.target);
}
getEdgeType(): EdgeType {
return EdgeType.get(this.database, this.action);
}
getValue(): Value | undefined {
return this.value;
}
/**
* NOTE: If this edge has been removed, or if its edgeType has been reset, this method will ALWAYS return false.
* If its edgeType has been reset, it has been replaced with a new edge that has the exact same source, target, value,
* and properties. Check getEdgesTo and getEdgesFrom on the source and target vertices to find replaced edges.
*/
async isAlive(asOf?: AsOf): Promise<boolean> {
return 0 !== (await this.getEffective(asOf));
}
async getEffective(asOf?: AsOf): Promise<Timestamp> {
const entry = await this.database.store.getEntryById(
this.address,
asOf,
);
if (!entry) {
return 0;
} else {
return <number>entry.storageKey;
}
}
/**
* If dest is not provided (or 0), the edge will be removed. This exact edge
* with the same Muid will never exist again. The only way to "revive" it is to reset
* the database or its edgeType. In that case, a new edge will be created with the same
* source, target, value, and properties.
* @param dest a timestamp to move the edge to. If 0 or not specified, the edge will be removed.
* @param purge completely remove the edge's entry from the datastore?
* @param meta optional metadata (may contain: comment, identity, or bundler)
*/
async remove(dest?: number, purge?: boolean, meta?: Meta) {
if (!(await this.isAlive())) throw new Error("this edge is not alive.");
const bundler: Bundler = await this.database.startBundle(meta);
await movementHelper(bundler, this.address, this.action, dest, purge);
if (!meta?.bundler) {
await bundler.commit();
}
}
}