Skip to content

Commit

Permalink
initial restructuring for protobufs structure
Browse files Browse the repository at this point in the history
  • Loading branch information
d-roak committed Sep 9, 2024
1 parent 8409b17 commit 17b039d
Show file tree
Hide file tree
Showing 17 changed files with 876 additions and 412 deletions.
9 changes: 5 additions & 4 deletions buf.gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ version: v2
plugins:
- local: ./node_modules/ts-proto/protoc-gen-ts_proto
strategy: directory
# out: ./packages/network/src
out: ./packages/object/src
out: ./packages
opt:
- esModuleInterop=true
- fileSuffix=_pb
inputs:
#- directory: ./packages/network/src
- directory: ./packages/object/src
- directory: ./packages
exclude_paths:
- packages/network/node_modules
- packages/object/node_modules
25 changes: 7 additions & 18 deletions examples/canvas/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { Canvas } from "./objects/canvas";
import { Pixel } from "./objects/pixel";

const node = new TopologyNode();
let topologyObject: TopologyObject<Canvas>;
let canvasCRO: Canvas;
let topologyObject: TopologyObject;
let peers: string[] = [];
let discoveryPeers: string[] = [];
let objectPeers: string[] = [];
Expand Down Expand Up @@ -62,17 +62,6 @@ async function paint_pixel(pixel: HTMLDivElement) {
canvasCRO.paint(node.networkNode.peerId, [x, y], painting);
const [r, g, b] = canvasCRO.pixel(x, y).color();
pixel.style.backgroundColor = `rgb(${r}, ${g}, ${b})`;

node.updateObject(topologyObject.id, [
{
fn: "paint",
args: [
node.networkNode.peerId,
`${x},${y}`,
`${painting[0]},${painting[1]},${painting[2]}`,
],
},
]);
}

async function init() {
Expand All @@ -86,8 +75,8 @@ async function init() {

const create_button = <HTMLButtonElement>document.getElementById("create");
create_button.addEventListener("click", async () => {
canvasCRO = new Canvas(5, 10);
topologyObject = await node.createObject();
topologyObject = await node.createObject(new Canvas(5, 10));
canvasCRO = topologyObject.cro as Canvas;

// message handler for the CRO
node.addCustomGroupMessageHandler(topologyObject.id, (e) => {
Expand All @@ -98,7 +87,7 @@ async function init() {
});

node.objectStore.subscribe(topologyObject.id, (_, obj) => {
handleObjectOps(canvasCRO, obj.operations);
handleObjectOps(canvasCRO, obj.vertices);
});

(<HTMLSpanElement>document.getElementById("canvasId")).innerText =
Expand All @@ -111,8 +100,8 @@ async function init() {
const croId = (<HTMLInputElement>document.getElementById("canvasIdInput"))
.value;
try {
canvasCRO = new Canvas(5, 10);
topologyObject = await node.createObject();
topologyObject = await node.createObject(new Canvas(5, 10), croId);
canvasCRO = topologyObject.cro as Canvas;

// message handler for the CRO
node.addCustomGroupMessageHandler(topologyObject.id, (e) => {
Expand All @@ -125,7 +114,7 @@ async function init() {
});

node.objectStore.subscribe(topologyObject.id, (_, obj) => {
handleObjectOps(canvasCRO, obj.operations);
handleObjectOps(canvasCRO, obj.vertices);
render();
});

Expand Down
24 changes: 21 additions & 3 deletions examples/canvas/src/objects/canvas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { Pixel } from "./pixel";
import {
ActionType,
type CRO,
type Operation,
} from "@topology-foundation/object";

export class Canvas implements CRO<Canvas> {
operations: string[] = ["splash", "paint"];

export class Canvas {
width: number;
height: number;
canvas: Pixel[][];
Expand All @@ -14,7 +21,7 @@ export class Canvas {
}

splash(
node_id: string,
nodeId: string,
offset: [number, number],
size: [number, number],
rgb: [number, number, number],
Expand All @@ -24,7 +31,7 @@ export class Canvas {

for (let x = offset[0]; x < this.width || x < offset[0] + size[0]; x++) {
for (let y = offset[1]; y < this.height || y < offset[1] + size[1]; y++) {
this.canvas[x][y].paint(node_id, rgb);
this.canvas[x][y].paint(nodeId, rgb);
}
}
}
Expand All @@ -49,4 +56,15 @@ export class Canvas {
row.forEach((pixel, y) => pixel.merge(peerCanvas.pixel(x, y))),
);
}

resolveConflicts(_): ActionType {
return ActionType.Nop;
}

mergeCallback(operations: Operation<Canvas>[]): void {
for (const op of operations) {
if (!op.value) continue;
this.merge(op.value);
}
}
}
8 changes: 4 additions & 4 deletions examples/chat/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Chat, addMessage, getMessages } from "./objects/chat";

const node = new TopologyNode();
// CRO = Conflict-free Replicated Object
let topologyObject: TopologyObject;
let topologyObject: TopologyObject<Chat>;
let chatCRO: Chat;
let peers: string[] = [];
let discoveryPeers: string[] = [];
Expand Down Expand Up @@ -91,8 +91,8 @@ async function main() {
document.getElementById("createRoom")
);
button_create.addEventListener("click", async () => {
chatCRO = new Chat();
topologyObject = await node.createObject();
topologyObject = await node.createObject(new Chat());
chatCRO = topologyObject.cro as Chat;

node.addCustomGroupMessageHandler(topologyObject.id, (e) => {
// on create/connect
Expand All @@ -103,7 +103,7 @@ async function main() {

node.objectStore.subscribe(topologyObject.id, (_, obj) => {
console.log("Received object operations: ", obj);
handleObjectOps(chatCRO, obj.operations);
handleObjectOps(chatCRO, obj.vertices);
});

(<HTMLButtonElement>document.getElementById("chatId")).innerText =
Expand Down
19 changes: 18 additions & 1 deletion examples/chat/src/objects/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,15 @@ import {
gset_create,
gset_merge,
} from "@topology-foundation/crdt";
import {
ActionType,
Vertex,
type CRO,
type Operation,
} from "@topology-foundation/object";

export class Chat {
export class Chat implements CRO<Chat> {
operations: string[] = ["addMessage"];
// store messages as strings in the format (timestamp, message, nodeId)
messages: GSet<string>;
constructor() {
Expand All @@ -24,6 +31,16 @@ export class Chat {
merge(other: Chat): void {
this.messages.merge(other.messages);
}

resolveConflicts(vertices: Vertex<Chat>[]): ActionType {
return ActionType.Nop;
}

mergeCallback(operations: Operation<Chat>[]): void {
for (const op of operations) {
console.log(op);
}
}
}

export function createChat(): Chat {
Expand Down
12 changes: 6 additions & 6 deletions packages/crdt/src/cros/AddWinsSet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
type Vertex,
} from "@topology-foundation/object";

export class AddWinsSet<T> implements CRO<T> {
export class AddWinsSet<T> implements CRO {
operations: string[] = ["add", "remove"];
state: Map<T, boolean>;

Expand Down Expand Up @@ -40,10 +40,10 @@ export class AddWinsSet<T> implements CRO<T> {
}

// in this case is an array of length 2 and there are only two possible operations
resolveConflicts(vertices: Vertex<T>[]): ActionType {
resolveConflicts(vertices: Vertex[]): ActionType {
if (
vertices[0].operation.type !== vertices[1].operation.type &&
vertices[0].operation.value === vertices[1].operation.value
vertices[0].operation.value === (vertices[1].operation.value as T)
) {
return vertices[0].operation.type === "add"
? ActionType.DropRight
Expand All @@ -53,15 +53,15 @@ export class AddWinsSet<T> implements CRO<T> {
}

// merged at HG level and called as a callback
mergeCallback(operations: Operation<T>[]): void {
mergeCallback(operations: Operation[]): void {
this.state = new Map<T, boolean>();
for (const op of operations) {
switch (op.type) {
case "add":
if (op.value !== null) this._add(op.value);
if (op.value !== null) this._add(op.value as T);
break;
case "remove":
if (op.value !== null) this._remove(op.value);
if (op.value !== null) this._remove(op.value as T);
break;
default:
break;
Expand Down
2 changes: 1 addition & 1 deletion packages/network/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from "./node.js";
export * from "./proto/messages_pb.js";
export * as NetworkPb from "./proto/messages_pb.js";
27 changes: 27 additions & 0 deletions packages/network/src/proto/messages.proto
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
syntax = "proto3";
package topology.network;

// Supposed to be the RIBLT stuff
message Vertex {
message Operation {
string type = 1;
string value = 2;
}
string hash = 1;
string nodeId = 2;
Operation operation = 3;
repeated string dependencies = 4;
};

message Message {
enum MessageType {
UPDATE = 0;
Expand All @@ -14,3 +26,18 @@ message Message {
MessageType type = 2;
bytes data = 3;
}

message Update {
}

message Sync {
repeated string vertex_hashes = 1;
}

message SyncAccept {
// not strings
repeated Vertex diff = 1;
repeated string missing = 2;
}

message SyncReject { }
Loading

0 comments on commit 17b039d

Please sign in to comment.