diff --git a/packages/rpc-cache-server/package.json b/packages/rpc-cache-server/package.json index 02379bf..24ced80 100644 --- a/packages/rpc-cache-server/package.json +++ b/packages/rpc-cache-server/package.json @@ -2,7 +2,7 @@ "name": "rpc-cache-server", "version": "0.0.1", "description": "A server to cache results of (expensive) RPC requests made to the Solana JSON RPC API", - "main": "src/index.js", + "main": "src/reader.js", "author": "Thomas Lisankie (Monadical)", "license": "MIT", "private": false, diff --git a/packages/rpc-cache-server/src/index.js b/packages/rpc-cache-server/src/index.js deleted file mode 100644 index 41a4ab3..0000000 --- a/packages/rpc-cache-server/src/index.js +++ /dev/null @@ -1,47 +0,0 @@ -const { JSONRPCServer } = require("json-rpc-2.0"); -const express = require("express"); -const bodyParser = require("body-parser"); -const redis = require("redis"); -const crypto = require("crypto"); - -const server = new JSONRPCServer(); -const redisClient = redis.createClient(); -const getProgramAccounts = function({ wormholeID }) -{ - return new Promise((resolve, reject) => { - redisClient.get(wormholeID, function(err, reply) { - if (err) { - reject(err); - } else { - if (reply === null) { - let uuid = crypto.randomUUID(); - redisClient.set(wormholeID, uuid, redis.print); - resolve(uuid); - return; - } - resolve(reply); - } - }); - }); -}; -server.addMethod("getProgramAccounts", getProgramAccounts); - -const app = express(); -app.use(bodyParser.json()); - -app.post("/json-rpc", (req, res) => { - const jsonRPCRequest = req.body; - // server.receive takes a JSON-RPC request and returns a Promise of a JSON-RPC response. - console.log("received request"); - console.log(jsonRPCRequest); - server.receive(jsonRPCRequest).then((jsonRPCResponse) => { - if (jsonRPCResponse) { - res.json(jsonRPCResponse); - } else { - console.log("no response"); - res.sendStatus(204); - } - }); -}); - -app.listen(80); diff --git a/packages/rpc-cache-server/src/reader.js b/packages/rpc-cache-server/src/reader.js new file mode 100644 index 0000000..7f28bec --- /dev/null +++ b/packages/rpc-cache-server/src/reader.js @@ -0,0 +1,78 @@ +const { JSONRPCServer } = require("json-rpc-2.0"); +const express = require("express"); +const bodyParser = require("body-parser"); +const redis = require("redis"); +const crypto = require("crypto"); +const axios = require("axios"); + +const server = new JSONRPCServer(); +const redisClient = redis.createClient(); +const getProgramAccounts = function({ wormholeID }) +{ + return new Promise((resolve, reject) => { + redisClient.get(wormholeID, function(err, reply) { + if (err) { + reject(err); + } else { + if (reply === null) { // if cache miss + let uuid = crypto.randomUUID(); + redisClient.set(wormholeID, uuid, redis.print); + // What it needs to do: + // 1. Notify the writer + axios({ + method : "post", + url : "http://localhost:3001/", + data : {identifier : wormholeID} + }); + + // 2. Send an RPC request to the full node on behalf of the client + const client = new JSONRPCClient((jsonRPCRequest) => + axios({ + method: "post", + url: "http://127.0.0.1:8899", // localnet url + headers: { + "content-type": "application/json", + }, + data: jsonRPCRequest, + }).then((response) => { + if (response.status === 200) { + // Use client.receive when you received a JSON-RPC response. + return client.receive(response.data); + } else if (jsonRPCRequest.id !== undefined) { + return Promise.reject(new Error(response.statusText)); + } + }) + ); + var val = null; + client + .request("getProgramAccounts", { wormholeID: wormholeID }) + .then((result) => val = result); + resolve(val); + return; + } + resolve(reply); + } + }); + }); +}; +server.addMethod("getProgramAccounts", getProgramAccounts); + +const app = express(); +app.use(bodyParser.json()); + +app.post("/json-rpc", (req, res) => { + const jsonRPCRequest = req.body; + // server.receive takes a JSON-RPC request and returns a Promise of a JSON-RPC response. + console.log("received request"); + console.log(jsonRPCRequest); + server.receive(jsonRPCRequest).then((jsonRPCResponse) => { + if (jsonRPCResponse) { + res.json(jsonRPCResponse); + } else { + console.log("no response"); + res.sendStatus(204); + } + }); +}); + +app.listen(3000); diff --git a/packages/rpc-cache-server/src/writer.js b/packages/rpc-cache-server/src/writer.js new file mode 100644 index 0000000..702c536 --- /dev/null +++ b/packages/rpc-cache-server/src/writer.js @@ -0,0 +1,36 @@ +const { JSONRPCClient } = require("json-rpc-2.0"); +const express = require("express"); +const bodyParser = require("body-parser"); +const redis = require("redis"); + +redisClient = redis.createClient(); +const app = express(); +app.use(bodyParser.json()); + +app.post("/", (req, res) => { + // when this is called, it means a cache miss happened and the cache needs to be written to. + // to do this, make an RPC call to the full node and write the value to cache. + const client = new JSONRPCClient((jsonRPCRequest) => + axios({ + method: "post", + url: "http://127.0.0.1:8899", // localnet url + headers: { + "content-type": "application/json", + }, + data: jsonRPCRequest, + }).then((response) => { + if (response.status === 200) { + // Use client.receive when you received a JSON-RPC response. + return client.receive(response.data); + } else if (jsonRPCRequest.id !== undefined) { + return Promise.reject(new Error(response.statusText)); + } + }) + ); + + client.request("getProgramAccounts", {wormholdID: req.body.wormholeID}) + .then((result) => redis.set(req.body.wormholeID, result)); + // also going to want some cache eviction logic +}); + +app.listen(3001);