syndicate-js/packages/core/src/runtime/dataspace.ts

74 lines
2.5 KiB
TypeScript

/// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { IdentityMap } from '@preserves/core';
import { Index } from './skeleton.js';
import { Assertion, Entity, Facet, Handle, LocalAction, Ref, Turn } from './actor.js';
import { fromObserve, Observe, toObserve } from '../gen/dataspace.js';
import * as P from '../gen/dataspacePatterns.js';
export class Dataspace implements Partial<Entity> {
readonly index = new Index();
readonly handleMap = new IdentityMap<Handle, [Assertion, Observe | undefined]>();
assert(turn: Turn, v: Assertion, handle: Handle): void {
this.index.addAssertion(turn, v);
const o = toObserve(v);
if (o !== void 0) {
this.index.addObserver(turn, o.pattern, o.observer);
}
this.handleMap.set(handle, [v, o]);
}
retract(turn: Turn, handle: Handle): void {
const entry = this.handleMap.get(handle);
if (entry === void 0) return;
const [v, o] = entry;
if (o !== void 0) {
this.index.removeObserver(turn, o.pattern, o.observer);
}
this.index.removeAssertion(turn, v);
}
message(turn: Turn, v: Assertion): void {
this.index.deliverMessage(turn, v);
}
}
export function assertionObserver(f: (t: Turn, a: Assertion) => LocalAction | undefined): Partial<Entity> {
const assertionMap = new IdentityMap<Handle, LocalAction>();
return {
assert(t: Turn, a: Assertion, h: Handle): void {
const g = f(t, a) ?? null;
if (g !== null) {
assertionMap.set(h, g);
}
},
retract(t: Turn, h: Handle): void {
assertionMap.get(h)?.(t);
assertionMap.delete(h);
},
};
}
export function assertionFacetObserver(f: (t: Turn, a: Assertion) => void, inertOk: boolean = true): Partial<Entity> {
const facetMap = new IdentityMap<Handle, Facet>();
return {
assert(t: Turn, a: Assertion, h: Handle): void {
facetMap.set(h, t.facet(t => {
if (inertOk) t.activeFacet.preventInertCheck();
f(t, a);
}));
},
retract(t: Turn, h: Handle): void {
const facet = facetMap.get(h);
if (facet) t.stop(facet);
facetMap.delete(h);
},
};
}
export function assertObserve(t: Turn, ds: Ref, pattern: P.Pattern, e: Partial<Entity>): Handle {
return t.assert(ds, fromObserve(Observe({ pattern, observer: t.ref(e) })));
}