Tighten and simplify
This commit is contained in:
parent
5d49794d88
commit
6a5cac5328
84
main.ts
84
main.ts
|
@ -15,71 +15,55 @@ import { Bag, ChangeDescription } from './bag';
|
|||
const Observe = Record.makeConstructor<Ref<Entity>>('Observe', ['label', 'observer']);
|
||||
|
||||
function makeDataspace(): Entity {
|
||||
const handleMap: IdentityMap<Handle, Assertion> = new IdentityMap();
|
||||
const handleMap: IdentityMap<Handle, Record<Ref<Entity>>> = new IdentityMap();
|
||||
const assertions = new Bag<Ref<Entity>>();
|
||||
const subscriptions: Dictionary<Map<Ref<Entity>, Dictionary<Handle>>> = new Dictionary();
|
||||
|
||||
function forEachSubscription(assertion: Assertion, f: (handleMap: Dictionary<Handle>, peer: Ref<Entity>) => void): void {
|
||||
if (!Record.isRecord(assertion)) return;
|
||||
function forEachSubscription(assertion: Record<Ref<Entity>>, f: (seen: Dictionary<Handle>, peer: Ref<Entity>) => void): void {
|
||||
subscriptions.get(assertion.label)?.forEach(f);
|
||||
}
|
||||
|
||||
return {
|
||||
[assert](turn: Turn, assertion: Assertion, handle: Handle): void {
|
||||
// console.log(`DS: assert ${assertion.asPreservesText()} :: ${handle}`);
|
||||
handleMap.set(handle, assertion);
|
||||
if (assertions.change(assertion, +1) === ChangeDescription.ABSENT_TO_PRESENT) {
|
||||
if (Observe.isClassOf(assertion)) {
|
||||
const observedLabel = Observe._.label(assertion)!;
|
||||
const observer = Observe._.observer(assertion) as Ref<Entity>;
|
||||
let peerMap = subscriptions.get(observedLabel);
|
||||
if (peerMap === void 0) {
|
||||
peerMap = new Map();
|
||||
subscriptions.set(observedLabel, peerMap);
|
||||
}
|
||||
const handleMap: Dictionary<Handle> = new Dictionary();
|
||||
peerMap.set(observer, handleMap);
|
||||
assertions.forEach((_count, assertion) => {
|
||||
if (Record.isRecord(assertion)) {
|
||||
if (is(assertion.label, observedLabel)) {
|
||||
handleMap.set(assertion, turn.assert(observer, assertion));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
forEachSubscription(assertion, (handleMap, peer) => {
|
||||
if (!handleMap.has(assertion)) {
|
||||
handleMap.set(assertion, turn.assert(peer, assertion));
|
||||
}
|
||||
});
|
||||
[assert](turn: Turn, rec: Assertion, handle: Handle): void {
|
||||
if (!Record.isRecord<Ref<Entity>>(rec)) return;
|
||||
handleMap.set(handle, rec);
|
||||
if (assertions.change(rec, +1) !== ChangeDescription.ABSENT_TO_PRESENT) return;
|
||||
if (Observe.isClassOf(rec)) {
|
||||
const label = Observe._.label(rec)!;
|
||||
const observer = Observe._.observer(rec) as Ref<Entity>;
|
||||
const seen = new Dictionary<Handle>();
|
||||
if (!subscriptions.has(label)) subscriptions.set(label, new Map());
|
||||
subscriptions.get(label)!.set(observer, seen);
|
||||
assertions.forEach((_count, prev) =>
|
||||
is((prev as Record<Ref<Entity>>).label, label)
|
||||
&& seen.set(prev, turn.assert(observer, prev)));
|
||||
}
|
||||
forEachSubscription(rec, (seen, peer) =>
|
||||
seen.has(rec) || seen.set(rec, turn.assert(peer, rec)));
|
||||
},
|
||||
|
||||
[retract](turn: Turn, upstreamHandle: Handle): void {
|
||||
const assertion = handleMap.get(upstreamHandle);
|
||||
// console.log(`DS: retract ${(assertion ?? Symbol.for('missing')).asPreservesText()} :: ${upstreamHandle}`);
|
||||
if (assertion !== void 0) {
|
||||
handleMap.delete(upstreamHandle);
|
||||
if (assertions.change(assertion, -1) === ChangeDescription.PRESENT_TO_ABSENT) {
|
||||
forEachSubscription(assertion, (handleMap, _peer) => {
|
||||
const downstreamHandle = handleMap.get(assertion);
|
||||
if (downstreamHandle !== void 0) {
|
||||
turn.retract(downstreamHandle);
|
||||
handleMap.delete(assertion);
|
||||
}
|
||||
});
|
||||
if (Observe.isClassOf(assertion)) {
|
||||
let peerMap = subscriptions.get(Observe._.label(assertion)!)!;
|
||||
peerMap.delete(Observe._.observer(assertion)! as Ref<Entity>);
|
||||
if (peerMap.size === 0) subscriptions.delete(Observe._.label(assertion)!);
|
||||
}
|
||||
const rec = handleMap.get(upstreamHandle);
|
||||
if (rec === void 0) return;
|
||||
handleMap.delete(upstreamHandle);
|
||||
if (assertions.change(rec, -1) !== ChangeDescription.PRESENT_TO_ABSENT) return;
|
||||
forEachSubscription(rec, (seen, _peer) => {
|
||||
const downstreamHandle = seen.get(rec);
|
||||
if (downstreamHandle !== void 0) {
|
||||
turn.retract(downstreamHandle);
|
||||
seen.delete(rec);
|
||||
}
|
||||
});
|
||||
if (Observe.isClassOf(rec)) {
|
||||
let peerMap = subscriptions.get(Observe._.label(rec)!)!;
|
||||
peerMap.delete(Observe._.observer(rec) as Ref<Entity>);
|
||||
if (peerMap.size === 0) subscriptions.delete(Observe._.label(rec)!);
|
||||
}
|
||||
},
|
||||
|
||||
[message](turn: Turn, message: Assertion): void {
|
||||
// console.log(`DS: message ${message.asPreservesText()}`);
|
||||
forEachSubscription(message, (_handleMap, peer) => turn.message(peer, message));
|
||||
[message](turn: Turn, rec: Assertion): void {
|
||||
if (!Record.isRecord<Ref<Entity>>(rec)) return;
|
||||
forEachSubscription(rec, (_seen, peer) => turn.message(peer, rec));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue