sync form
This commit is contained in:
parent
8aaeaa7e0f
commit
584e017cd7
4 changed files with 61 additions and 7 deletions
|
@ -1,4 +1,5 @@
|
||||||
import * as Y from "yjs";
|
import * as Y from "yjs";
|
||||||
|
import * as AwarenessProtocol from "y-protocols/dist/awareness.cjs";
|
||||||
import { MissionMap } from "../storage/missionMap";
|
import { MissionMap } from "../storage/missionMap";
|
||||||
|
|
||||||
export default abstract class MissionDocHelper {
|
export default abstract class MissionDocHelper {
|
||||||
|
@ -19,7 +20,10 @@ export default abstract class MissionDocHelper {
|
||||||
// const ytext = ydoc.getText('meinText');
|
// const ytext = ydoc.getText('meinText');
|
||||||
// ytext.insert(0, 'Hier ist ein initialer Text');
|
// ytext.insert(0, 'Hier ist ein initialer Text');
|
||||||
|
|
||||||
MissionMap.write(missionId, { missionId, doc, timestamp: 0 }, true);
|
const awareness = new AwarenessProtocol.Awareness(doc);
|
||||||
|
awareness.setLocalState(null);
|
||||||
|
|
||||||
|
MissionMap.write(missionId, { missionId, doc, awareness, timestamp: 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async saveDoc(missionId: string) {
|
public static async saveDoc(missionId: string) {
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import * as Y from "yjs";
|
import * as Y from "yjs";
|
||||||
|
import * as AwarenessProtocol from "y-protocols/dist/awareness.cjs";
|
||||||
|
|
||||||
export interface missionStoreModel {
|
export interface missionStoreModel {
|
||||||
missionId: string;
|
missionId: string;
|
||||||
doc: Y.Doc;
|
doc: Y.Doc;
|
||||||
|
awareness: AwarenessProtocol.Awareness;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +24,12 @@ export abstract class MissionMap {
|
||||||
this.write(identifier, mission, true);
|
this.write(identifier, mission, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static updateAwareness(identifier: string, data: Uint8Array, socketId: string): void {
|
||||||
|
let mission = this.read(identifier);
|
||||||
|
AwarenessProtocol.applyAwarenessUpdate(mission.awareness, data, socketId);
|
||||||
|
this.write(identifier, mission, true);
|
||||||
|
}
|
||||||
|
|
||||||
public static updateTimestamp(identifier: string, data: number): void {
|
public static updateTimestamp(identifier: string, data: number): void {
|
||||||
let mission = this.read(identifier);
|
let mission = this.read(identifier);
|
||||||
mission.timestamp = data;
|
mission.timestamp = data;
|
||||||
|
|
3
src/types/y-protocols.d.ts
vendored
Normal file
3
src/types/y-protocols.d.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
declare module "y-protocols/dist/awareness.cjs" {
|
||||||
|
export * from "y-protocols/awareness";
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import { Server, Socket } from "socket.io";
|
||||||
import { handleEvent } from "../handleEvent";
|
import { handleEvent } from "../handleEvent";
|
||||||
import { MissionMap, missionStoreModel } from "../../storage/missionMap";
|
import { MissionMap, missionStoreModel } from "../../storage/missionMap";
|
||||||
import * as Y from "yjs";
|
import * as Y from "yjs";
|
||||||
|
import * as AwarenessProtocol from "y-protocols/dist/awareness.cjs";
|
||||||
import MissionDocHelper from "../../helpers/missionDocHelper";
|
import MissionDocHelper from "../../helpers/missionDocHelper";
|
||||||
|
|
||||||
export default (io: Server, socket: Socket) => {
|
export default (io: Server, socket: Socket) => {
|
||||||
|
@ -19,20 +20,20 @@ export default (io: Server, socket: Socket) => {
|
||||||
try {
|
try {
|
||||||
socket.join(missionId);
|
socket.join(missionId);
|
||||||
|
|
||||||
await MissionDocHelper.populateDoc(missionId);
|
if (!MissionMap.exists(missionId)) {
|
||||||
|
await MissionDocHelper.populateDoc(missionId);
|
||||||
|
}
|
||||||
|
|
||||||
const mission = MissionMap.read(missionId);
|
const mission = MissionMap.read(missionId);
|
||||||
|
|
||||||
if (clientLastUpdate && clientLastUpdate.timestamp) {
|
if (clientLastUpdate && clientLastUpdate.timestamp) {
|
||||||
// Prüfe, ob der Client aktuell ist oder nicht
|
|
||||||
if (mission.timestamp > clientLastUpdate.timestamp) {
|
if (mission.timestamp > clientLastUpdate.timestamp) {
|
||||||
// Server hat neuere Daten, sende vollständigen State
|
|
||||||
socket.emit("package-sync", {
|
socket.emit("package-sync", {
|
||||||
update: Y.encodeStateAsUpdate(mission.doc),
|
update: Y.encodeStateAsUpdate(mission.doc),
|
||||||
timestamp: mission.timestamp,
|
timestamp: mission.timestamp,
|
||||||
source: "server",
|
source: "server",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Client hat aktuellere oder gleich aktuelle Daten
|
|
||||||
socket.emit("sync-get-missing-updates", {
|
socket.emit("sync-get-missing-updates", {
|
||||||
stateVector: Y.encodeStateVector(mission.doc),
|
stateVector: Y.encodeStateVector(mission.doc),
|
||||||
timestamp: mission.timestamp,
|
timestamp: mission.timestamp,
|
||||||
|
@ -40,7 +41,6 @@ export default (io: Server, socket: Socket) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Client hat keine Zeitstempel-Info, sende vollständigen State
|
|
||||||
socket.emit("package-sync", {
|
socket.emit("package-sync", {
|
||||||
update: Y.encodeStateAsUpdate(mission.doc),
|
update: Y.encodeStateAsUpdate(mission.doc),
|
||||||
timestamp: mission.timestamp,
|
timestamp: mission.timestamp,
|
||||||
|
@ -48,6 +48,14 @@ export default (io: Server, socket: Socket) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
socket.emit("package-sync-awareness", {
|
||||||
|
update: AwarenessProtocol.encodeAwarenessUpdate(
|
||||||
|
mission.awareness,
|
||||||
|
Array.from(mission.awareness.getStates().keys())
|
||||||
|
),
|
||||||
|
source: "server",
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "status-mission:join",
|
type: "status-mission:join",
|
||||||
answer: { status: "success" },
|
answer: { status: "success" },
|
||||||
|
@ -74,7 +82,7 @@ export default (io: Server, socket: Socket) => {
|
||||||
answer: {
|
answer: {
|
||||||
update: data.update,
|
update: data.update,
|
||||||
timestamp: data.timestamp,
|
timestamp: data.timestamp,
|
||||||
source: "client",
|
source: socket.id,
|
||||||
},
|
},
|
||||||
room: socketRooms[0],
|
room: socketRooms[0],
|
||||||
};
|
};
|
||||||
|
@ -119,6 +127,37 @@ export default (io: Server, socket: Socket) => {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
socket.on(
|
||||||
|
"mission:sync-client-awareness",
|
||||||
|
handleEvent(
|
||||||
|
{ type: "create", section: "operation", module: "mission" },
|
||||||
|
async (data: { update: Array<number>; timestamp: number }) => {
|
||||||
|
const socketRooms = Array.from(socket.rooms).filter((room) => room !== socket.id && room !== "home");
|
||||||
|
try {
|
||||||
|
MissionMap.updateAwareness(socketRooms[0], new Uint8Array(data.update), socket.id);
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "package-sync-awareness",
|
||||||
|
answer: {
|
||||||
|
update: data.update,
|
||||||
|
source: socket.id,
|
||||||
|
},
|
||||||
|
room: socketRooms[0],
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
const mission = MissionMap.read(socketRooms[0]);
|
||||||
|
socket.emit("package-sync-awareness", {
|
||||||
|
update: Y.encodeStateAsUpdate(mission.doc),
|
||||||
|
source: "server",
|
||||||
|
error: true,
|
||||||
|
});
|
||||||
|
return { type: "status-mission:sync-client-updates", answer: { status: "failed", msg: error.message } };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
socket
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
socket.on(
|
socket.on(
|
||||||
"mission:leave",
|
"mission:leave",
|
||||||
handleEvent(
|
handleEvent(
|
||||||
|
|
Loading…
Add table
Reference in a new issue