rhizome/src/deltas.ts

103 lines
2.5 KiB
TypeScript
Raw Normal View History

2024-12-21 21:16:18 -06:00
import EventEmitter from 'node:events';
import {REQUEST_BIND_HOST, REQUEST_BIND_PORT} from './config';
import {publishSock, subscribeSock} from './pub-sub';
import {Decision, Delta, PeerAddress} from './types';
import {myRequestAddr} from './peers';
2024-12-22 14:38:01 -06:00
import objectHash from 'object-hash';
2024-12-21 21:16:18 -06:00
export const deltaStream = new EventEmitter();
export const deltasProposed: Delta[] = [];
export const deltasAccepted: Delta[] = [];
export const deltasRejected: Delta[] = [];
export const deltasDeferred: Delta[] = [];
2024-12-22 14:38:01 -06:00
export const hashesReceived = new Set<string>();
2024-12-21 21:16:18 -06:00
export function applyPolicy(delta: Delta): Decision {
2024-12-22 09:13:44 -06:00
return !!delta && Decision.Accept;
2024-12-21 21:16:18 -06:00
}
export function receiveDelta(delta: Delta) {
2024-12-22 14:38:01 -06:00
// Deduplication: if we already received this delta, disregard it
const hash = objectHash(delta);
if (!hashesReceived.has(hash)) {
hashesReceived.add(hash);
deltasProposed.push(delta);
}
2024-12-21 21:16:18 -06:00
}
export function ingestDelta(delta: Delta) {
2024-12-22 09:13:44 -06:00
const decision = applyPolicy(delta);
switch (decision) {
case Decision.Accept:
deltasAccepted.push(delta);
deltaStream.emit('delta', {delta});
2024-12-22 09:13:44 -06:00
break;
case Decision.Reject:
deltasRejected.push(delta);
break;
case Decision.Defer:
deltasDeferred.push(delta);
break;
}
2024-12-21 21:16:18 -06:00
}
export function ingestNext(): boolean {
const delta = deltasProposed.shift();
if (!delta) {
return false;
}
ingestDelta(delta);
return true;
}
export function ingestAll() {
while (ingestNext());
}
export function ingestNextDeferred(): boolean {
const delta = deltasDeferred.shift();
if (!delta) {
return false;
}
ingestDelta(delta);
return true;
}
export function ingestAllDeferred() {
while (ingestNextDeferred());
}
export function subscribeDeltas(fn: (delta: Delta) => void) {
deltaStream.on('delta', ({delta}) => {
fn(delta);
});
}
export async function publishDelta(delta: Delta) {
console.log(`Publishing delta: ${JSON.stringify(delta)}`);
await publishSock.send(["deltas", myRequestAddr.toAddrString(), serializeDelta(delta)]);
2024-12-21 21:16:18 -06:00
}
function serializeDelta(delta: Delta) {
return JSON.stringify(delta);
}
function deserializeDelta(input: string) {
return JSON.parse(input);
}
export async function runDeltas() {
for await (const [topic, sender, msg] of subscribeSock) {
2024-12-21 21:16:18 -06:00
if (topic.toString() !== "deltas") {
continue;
}
const delta = deserializeDelta(msg.toString());
delta.receivedFrom = PeerAddress.fromString(sender.toString());
2024-12-21 21:16:18 -06:00
console.log(`Received delta: ${JSON.stringify(delta)}`);
ingestDelta(delta);
}
}