Compare commits

..

3 Commits

Author SHA1 Message Date
Derrick Hammer 630dce7b05
*Update relay-types 2022-12-19 15:34:44 -05:00
Derrick Hammer 7b26856720
*Update rpc methods that require cache to only be enabled if on
*Make get_direct_peers, get_connected_peers, and get_bootstrap_info debug methods
2022-12-19 15:34:32 -05:00
Derrick Hammer af4e6155bc
*Make dht cache optional, but enabled by default 2022-12-19 15:28:22 -05:00
4 changed files with 124 additions and 91 deletions

View File

@ -29,6 +29,7 @@ config.inject({
logLevel: "info", logLevel: "info",
pluginDir: path.resolve(configDir, "..", "plugins"), pluginDir: path.resolve(configDir, "..", "plugins"),
plugins: ["core"], plugins: ["core"],
cache: true,
}); });
config.load(); config.load();

View File

@ -48,39 +48,91 @@ async function broadcastRequest(
const plugin: Plugin = { const plugin: Plugin = {
name: "rpc", name: "rpc",
async plugin(api: PluginAPI): Promise<void> { async plugin(api: PluginAPI): Promise<void> {
api.registerMethod("get_cached_item", { if (api.config.bool("cache")) {
cacheable: false, api.registerMethod("get_cached_item", {
async handler(req: string): Promise<RPCResponse> { cacheable: false,
if (typeof req !== "string") { async handler(req: string): Promise<RPCResponse> {
throw new Error("item must be a string"); if (typeof req !== "string") {
} throw new Error("item must be a string");
}
const cache = getRpcServer().cache.data; const cache = api.rpcServer.cache?.data;
if (!Object.keys(cache).includes(req)) { if (!cache?.has(req)) {
throw new Error("item does not exist"); throw new Error("item does not exist");
} }
return { return {
data: true, data: true,
...cache.get<RPCCacheItem>(req)?.value, ...cache.get<RPCCacheItem>(req)?.value,
signature: cache.get<RPCCacheItem>(req)?.signature, signature: cache.get<RPCCacheItem>(req)?.signature,
}; };
}, },
}); });
api.registerMethod("clear_cached_item", { api.registerMethod("clear_cached_item", {
cacheable: false, cacheable: false,
async handler(req: string): Promise<void> { async handler(req: string): Promise<void> {
if (typeof req !== "string") { if (typeof req !== "string") {
throw new Error("item must be a string"); throw new Error("item must be a string");
} }
try { try {
api.getRpcServer().cache.deleteItem(req); api.rpcServer.cache.deleteItem(req);
} catch (e: any) { } catch (e: any) {
throw e; throw e;
} }
}, },
}); });
api.registerMethod("get_peers", {
cacheable: false,
async handler(): Promise<string[]> {
const pubkey = b4a.from(api.identity.publicKeyRaw).toString("hex");
const online = api.rpcServer.cache?.dhtCache.online || new Set();
if (online.has(pubkey)) {
online.delete(pubkey);
}
return [...online];
},
});
if (api.logger.level === "debug") {
api.registerMethod("get_direct_peers", {
cacheable: false,
async handler(): Promise<string[]> {
const online = api.rpcServer.cache.dhtCache.online;
const pubkey = b4a
.from(api.swarm.keyPair.publicKeyRaw())
.toString("hex");
if (online.has(pubkey)) {
online.delete(pubkey);
}
const topic = LUMEWEB_TOPIC_HASH.toString("hex");
return [...api.swarm.peers.values()]
.filter((item: any) =>
[...item._seenTopics.keys()].includes(topic)
)
.map((item: any) => item.publicKey.toString("hex"))
.filter((item: any) => online.has(item));
},
});
api.registerMethod("get_bootstrap_info", {
cacheable: false,
async handler(): Promise<string[]> {
// @ts-ignore
return api.rpcServer.cache.dhtCache._getBootstrapInfo();
},
});
api.registerMethod("get_connected_peers", {
cacheable: false,
async handler(): Promise<string[]> {
// @ts-ignore
return [...api.rpcServer.cache.dhtCache.connectedTo];
},
});
}
}
api.registerMethod("broadcast_request", { api.registerMethod("broadcast_request", {
cacheable: false, cacheable: false,
async handler(req: RPCBroadcastRequest): Promise<RPCBroadcastResponse> { async handler(req: RPCBroadcastRequest): Promise<RPCBroadcastResponse> {
@ -128,55 +180,6 @@ const plugin: Plugin = {
return result; return result;
}, },
}); });
api.registerMethod("get_peers", {
cacheable: false,
async handler(): Promise<string[]> {
const pubkey = b4a
.from(getRpcServer().cache.swarm.keyPair.publicKey)
.toString("hex");
const online = getRpcServer().cache.dhtCache.online;
if (online.has(pubkey)) {
online.delete(pubkey);
}
return [...online];
},
});
api.registerMethod("get_direct_peers", {
cacheable: false,
async handler(): Promise<string[]> {
const online = getRpcServer().cache.dhtCache.online;
const pubkey = b4a
.from(getRpcServer().cache.swarm.keyPair.publicKey)
.toString("hex");
if (online.has(pubkey)) {
online.delete(pubkey);
}
const topic = LUMEWEB_TOPIC_HASH.toString("hex");
return [...getRpcServer().cache.swarm.peers.values()]
.filter((item: any) => [...item._seenTopics.keys()].includes(topic))
.map((item: any) => item.publicKey.toString("hex"))
.filter((item: any) => online.has(item));
},
});
api.registerMethod("get_bootstrap_info", {
cacheable: false,
async handler(): Promise<string[]> {
// @ts-ignore
return getRpcServer().cache.dhtCache._getBootstrapInfo();
},
});
api.registerMethod("get_connected_peers", {
cacheable: false,
async handler(): Promise<string[]> {
// @ts-ignore
return [...getRpcServer().cache.dhtCache.connectedTo];
},
});
}, },
}; };

View File

@ -18,6 +18,7 @@ import { Mutex } from "async-mutex";
import { RPCCache } from "./cache"; import { RPCCache } from "./cache";
// @ts-ignore // @ts-ignore
import jsonStringify from "json-stringify-deterministic"; import jsonStringify from "json-stringify-deterministic";
import config from "../../config";
const sodium = require("sodium-universal"); const sodium = require("sodium-universal");
let server: RPCServer; let server: RPCServer;
@ -54,9 +55,16 @@ export class RPCServer extends EventEmitter {
>(); >();
private pendingRequests: Map<string, Mutex> = new Map<string, Mutex>(); private pendingRequests: Map<string, Mutex> = new Map<string, Mutex>();
private _cache: RPCCache = new RPCCache(this); private _cache?: RPCCache;
get cache(): RPCCache { constructor() {
super();
if (config.bool("cache")) {
this._cache = new RPCCache(this);
}
}
get cache(): RPCCache | undefined {
return this._cache; return this._cache;
} }
@ -137,7 +145,7 @@ export class RPCServer extends EventEmitter {
} }
return crypto return crypto
.sign(Buffer.from(raw), this._cache.swarm.keyPair.secretKey) .sign(Buffer.from(raw), this._cache?.swarm.keyPair.secretKey)
.toString("hex"); .toString("hex");
} }
@ -201,8 +209,8 @@ export class RPCServer extends EventEmitter {
} }
method = method as RPCMethod; method = method as RPCMethod;
if (method.cacheable) { if (config.bool("cache") && method.cacheable) {
this.cache.addItem(request, rpcResult); this.cache?.addItem(request, rpcResult);
} }
this.getRequestLock(request)?.release(); this.getRequestLock(request)?.release();
@ -211,9 +219,14 @@ export class RPCServer extends EventEmitter {
} }
private getCachedRequest(request: RPCRequest): RPCCacheItem | boolean { private getCachedRequest(request: RPCRequest): RPCCacheItem | boolean {
if (!config.bool("cache")) {
return false;
}
const req = RPCServer.hashQuery(request); const req = RPCServer.hashQuery(request);
if (this._cache.data.has(req)) {
return this._cache.data.get<RPCCacheItem>(req) as RPCCacheItem; if (this._cache?.data.has(req)) {
return this._cache?.data.get<RPCCacheItem>(req) as RPCCacheItem;
} }
return false; return false;
@ -256,8 +269,8 @@ export class RPCServer extends EventEmitter {
if (lock.isLocked()) { if (lock.isLocked()) {
await lock.waitForUnlock(); await lock.waitForUnlock();
if (this._cache.data.has(reqId)) { if (this._cache?.data.has(reqId)) {
return this._cache.data.get<RPCCacheItem>(reqId) as RPCCacheItem; return this._cache?.data.get<RPCCacheItem>(reqId) as RPCCacheItem;
} }
} }

View File

@ -662,8 +662,15 @@ __metadata:
"@lumeweb/relay-types@https://git.lumeweb.com/LumeWeb/relay-types.git": "@lumeweb/relay-types@https://git.lumeweb.com/LumeWeb/relay-types.git":
version: 0.1.0 version: 0.1.0
resolution: "@lumeweb/relay-types@https://git.lumeweb.com/LumeWeb/relay-types.git#commit=2d7bed64d580293aaa810f1f6d6fe9ff0e5c359e" resolution: "@lumeweb/relay-types@https://git.lumeweb.com/LumeWeb/relay-types.git#commit=f1da2249ac8d21e76e729d019c75cf15f01bb6a0"
checksum: 7265158184d01196fceb39d18e639bc0fc3ab4977f1ddc00e6af46d66687aed619ce2040f9ec77a1e57484f509b28e7a2f3116a060e7336895f925bfe6306b8e dependencies:
"@lumeweb/dht-cache": "https://git.lumeweb.com/LumeWeb/dht-cache.git"
"@types/eventemitter2": "npm:^4.1.0"
arg: "npm:^5.0.2"
eventemitter2: "npm:^6.4.9"
micro-ed25519-hdkey: "npm:^0.1.2"
pino: "npm:^8.8.0"
checksum: 8d46b69d80b24a8b0c9709f6a8270d4861c3f58eb11a60d92af8432e70f82731f9ade0b84bdf2361232c90dd94ce3631b9da09b47846185941f911279d674a4c
languageName: node languageName: node
linkType: hard linkType: hard
@ -922,6 +929,15 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@types/eventemitter2@npm:^4.1.0":
version: 4.1.0
resolution: "@types/eventemitter2@npm:4.1.0"
dependencies:
eventemitter2: "npm:*"
checksum: 64e08ed52804bb9c5cdde8aff52e1dc33ed596f2ffa37364e6f0b02655b898746c7bf6722b36e9456af1eb0d0e42a436e2d2b2e0f523ca922ebde4768a242540
languageName: node
linkType: hard
"@types/minimatch@npm:^3.0.5": "@types/minimatch@npm:^3.0.5":
version: 3.0.5 version: 3.0.5
resolution: "@types/minimatch@npm:3.0.5" resolution: "@types/minimatch@npm:3.0.5"
@ -1793,7 +1809,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"eventemitter2@npm:^6.4.9": "eventemitter2@npm:*, eventemitter2@npm:^6.4.9":
version: 6.4.9 version: 6.4.9
resolution: "eventemitter2@npm:6.4.9" resolution: "eventemitter2@npm:6.4.9"
checksum: c180cc0012389f2cd564cdfba949807175dd309b1d7f0900cfdfc5a97436a867a30964b94f86613ab237d960d52f7e4c85098c9c8ef6dc8ed29bbf4e79465d8b checksum: c180cc0012389f2cd564cdfba949807175dd309b1d7f0900cfdfc5a97436a867a30964b94f86613ab237d960d52f7e4c85098c9c8ef6dc8ed29bbf4e79465d8b