Massive cleanup and plugbox cleanup

This commit is contained in:
Zef Hemel
2022-03-23 15:41:12 +01:00
parent a916088215
commit 09d07d587f
34 changed files with 695 additions and 525 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
import { test, expect, beforeAll, afterAll, describe } from "@jest/globals";
import { afterAll, beforeAll, describe, expect, test } from "@jest/globals";
import { createServer } from "http";
import { io as Client } from "socket.io-client";
@@ -7,7 +7,7 @@ import { SocketServer } from "./api_server";
import * as path from "path";
import * as fs from "fs";
import { SilverBulletHooks } from "../common/manifest";
import { System } from "../plugbox/runtime";
import { System } from "../plugbox/system";
describe("Server test", () => {
let io: Server,
@@ -43,7 +43,7 @@ describe("Server test", () => {
socketServer = new SocketServer(
tmpDir,
io,
new System<SilverBulletHooks>()
new System<SilverBulletHooks>("server")
);
clientSocket.on("connect", done);
await socketServer.init();
+14 -5
View File
@@ -3,17 +3,20 @@ import { Page } from "./types";
import * as path from "path";
import { IndexApi } from "./index_api";
import { PageApi } from "./page_api";
import { System } from "../plugbox/runtime";
import { SilverBulletHooks } from "../common/manifest";
import pageIndexSyscalls from "./syscalls/page_index";
import { safeRun } from "./util";
import { System } from "../plugbox/system";
export class ClientConnection {
openPages = new Set<string>();
constructor(readonly sock: Socket) {}
}
export interface ApiProvider {
init(): Promise<void>;
api(): Object;
}
@@ -62,13 +65,19 @@ export class SocketServer {
socket.on("disconnect", () => {
console.log("Disconnected", socket.id);
clientConn.openPages.forEach(disconnectPageSocket);
clientConn.openPages.forEach((pageName) => {
safeRun(async () => {
await disconnectPageSocket(pageName);
});
});
this.connectedSockets.delete(socket);
});
socket.on("page.closePage", (pageName: string) => {
console.log("Client closed page", pageName);
disconnectPageSocket(pageName);
safeRun(async () => {
await disconnectPageSocket(pageName);
});
clientConn.openPages.delete(pageName);
});
@@ -87,12 +96,12 @@ export class SocketServer {
});
};
const disconnectPageSocket = (pageName: string) => {
const disconnectPageSocket = async (pageName: string) => {
let page = this.openPages.get(pageName);
if (page) {
for (let client of page.clientStates) {
if (client.socket === socket) {
(this.apis.get("page")! as PageApi).disconnectClient(
await (this.apis.get("page")! as PageApi).disconnectClient(
client,
page
);
+7 -3
View File
@@ -1,4 +1,4 @@
import { readdir, readFile, stat, unlink, writeFile } from "fs/promises";
import { mkdir, readdir, readFile, stat, unlink, writeFile } from "fs/promises";
import * as path from "path";
import { PageMeta } from "./types";
@@ -48,7 +48,7 @@ export class DiskStorage {
},
};
} catch (e) {
// console.error("Error while writing page", pageName, e);
// console.error("Error while reading page", pageName, e);
throw Error(`Could not read page ${pageName}`);
}
}
@@ -56,9 +56,13 @@ export class DiskStorage {
async writePage(pageName: string, text: string): Promise<PageMeta> {
let localPath = path.join(this.rootPath, pageName + ".md");
try {
// Ensure parent folder exists
await mkdir(path.dirname(localPath), { recursive: true });
// Actually write the file
await writeFile(localPath, text);
// console.log(`Wrote to ${localPath}`);
// Fetch new metadata
const s = await stat(localPath);
return {
name: pageName,
+3 -3
View File
@@ -1,8 +1,8 @@
import { Express } from "express";
import { System } from "../plugbox/runtime";
import { SilverBulletHooks } from "../common/manifest";
import { exposeSystem } from "../plugbox/endpoints";
import { EndpointFeature } from "../plugbox/feature/endpoint";
import { readFile } from "fs/promises";
import { System } from "../plugbox/system";
export class ExpressServer {
app: Express;
@@ -19,7 +19,7 @@ export class ExpressServer {
this.rootPath = rootPath;
this.system = system;
app.use(exposeSystem(this.system));
system.addFeature(new EndpointFeature(app));
// Fallback, serve index.html
let cachedIndex: string | undefined = undefined;
+30 -25
View File
@@ -9,8 +9,8 @@ import fs from "fs";
import path from "path";
import { stat } from "fs/promises";
import { Cursor, cursorEffect } from "../webapp/cursorEffect";
import { System } from "../plugbox/runtime";
import { SilverBulletHooks } from "../common/manifest";
import { System } from "../plugbox/system";
export class PageApi implements ApiProvider {
openPages: Map<string, Page>;
@@ -34,17 +34,18 @@ export class PageApi implements ApiProvider {
async init(): Promise<void> {
this.fileWatcher();
// TODO: Move this elsewhere, this doesn't belong here
this.system.on({
plugUpdated: (plugName, plugDef) => {
plugLoaded: (plugName, plugDef) => {
console.log("Plug updated on disk, broadcasting to all clients");
this.connectedSockets.forEach((socket) => {
socket.emit("plugUpdated", plugName, plugDef);
socket.emit("plugLoaded", plugName, plugDef.manifest);
});
},
plugRemoved: (plugName) => {
plugUnloaded: (plugName) => {
console.log("Plug removed on disk, broadcasting to all clients");
this.connectedSockets.forEach((socket) => {
socket.emit("plugRemoved", plugName);
socket.emit("plugUnloaded", plugName);
});
},
});
@@ -53,27 +54,25 @@ export class PageApi implements ApiProvider {
broadcastCursors(page: Page) {
page.clientStates.forEach((client) => {
client.socket.emit(
"cursorSnapshot",
page.name,
Object.fromEntries(page.cursors.entries())
"cursorSnapshot",
page.name,
Object.fromEntries(page.cursors.entries())
);
});
}
flushPageToDisk(name: string, page: Page) {
safeRun(async () => {
let meta = await this.pageStore.writePage(name, page.text.sliceString(0));
console.log(`Wrote page ${name} to disk`);
page.meta = meta;
});
async flushPageToDisk(name: string, page: Page) {
let meta = await this.pageStore.writePage(name, page.text.sliceString(0));
console.log(`Wrote page ${name} to disk`);
page.meta = meta;
}
disconnectClient(client: ClientPageState, page: Page) {
async disconnectClient(client: ClientPageState, page: Page) {
console.log("Disconnecting client");
page.clientStates.delete(client);
if (page.clientStates.size === 0) {
console.log("No more clients for", page.name, "flushing");
this.flushPageToDisk(page.name, page);
await this.flushPageToDisk(page.name, page);
this.openPages.delete(page.name);
} else {
page.cursors.delete(client.socket.id);
@@ -214,16 +213,22 @@ export class PageApi implements ApiProvider {
// Throttle
if (!page.saveTimer) {
page.saveTimer = setTimeout(() => {
if (page) {
console.log("Indexing", pageName);
safeRun(async () => {
if (page) {
console.log(
"Persisting",
pageName,
" to disk and indexing."
);
await this.flushPageToDisk(pageName, page);
this.system.dispatchEvent("page:index", {
name: pageName,
text: page.text.sliceString(0),
});
this.flushPageToDisk(pageName, page);
page.saveTimer = undefined;
}
await this.system.dispatchEvent("page:index", {
name: pageName,
text: page.text.sliceString(0),
});
page.saveTimer = undefined;
}
});
}, 1000);
}
}
+6 -2
View File
@@ -4,10 +4,12 @@ import { Server } from "socket.io";
import { SocketServer } from "./api_server";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { System } from "../plugbox/runtime";
import { SilverBulletHooks } from "../common/manifest";
import { ExpressServer } from "./express_server";
import { DiskPlugLoader } from "../plugbox/plug_loader";
import { NodeCronFeature } from "../plugbox/feature/node_cron";
import shellSyscalls from "./syscalls/shell";
import { System } from "../plugbox/system";
let args = yargs(hideBin(process.argv))
.option("debug", {
@@ -23,7 +25,7 @@ const pagesPath = args._[0] as string;
const app = express();
const server = http.createServer(app);
const system = new System<SilverBulletHooks>();
const system = new System<SilverBulletHooks>("server");
const io = new Server(server, {
cors: {
@@ -52,6 +54,8 @@ expressServer
);
await plugLoader.loadPlugs();
plugLoader.watcher();
system.registerSyscalls(shellSyscalls(pagesPath));
system.addFeature(new NodeCronFeature());
server.listen(port, () => {
console.log(`Server listening on port ${port}`);
});