From 5cb3835ec77360335064b809b09541be92f5bde1 Mon Sep 17 00:00:00 2001 From: Evan Patterson Date: Fri, 3 Aug 2018 15:56:26 -0700 Subject: [PATCH] REST API: Put Redis cache in front of CouchDB. Use master version of Node Redis client for now, because TLS support is not yet officially released: https://github.com/NodeRedis/node_redis/issues/1268 https://github.com/NodeRedis/node_redis/pull/1282 --- api/package.json | 4 ++++ api/src/config.ts | 3 +++ api/src/main.ts | 24 ++++++++++++++++----- api/yarn.lock | 55 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 80 insertions(+), 6 deletions(-) diff --git a/api/package.json b/api/package.json index 8074c29..cee725e 100644 --- a/api/package.json +++ b/api/package.json @@ -13,13 +13,17 @@ }, "dependencies": { "express": "^4.16.3", + "express-redis-cache": "^1.1.3", "lodash": "^4.17.10", + "redis": "https://github.com/NodeRedis/node_redis", "request": "^2.87.0", "request-promise-native": "^1.0.5" }, "devDependencies": { "@types/express": "^4.16.0", + "@types/express-redis-cache": "^1.1.0", "@types/lodash": "^4.14.115", + "@types/redis": "^2.8.6", "@types/request": "^2.47.1", "@types/request-promise-native": "^1.0.15", "typescript": "^3.0.1" diff --git a/api/src/config.ts b/api/src/config.ts index 5b9ed25..6c0c6e8 100644 --- a/api/src/config.ts +++ b/api/src/config.ts @@ -9,3 +9,6 @@ export const dbUrl = `${couchUrl}/${dbName}`; export const appDbName = 'data-science-ontology-webapp'; export const appDbUrl = `${couchUrl}/${appDbName}`; + +// Redis +export const redisUrl = process.env.REDIS_URL || "redis://localhost:6379"; \ No newline at end of file diff --git a/api/src/main.ts b/api/src/main.ts index dd2829b..bf3c6d7 100644 --- a/api/src/main.ts +++ b/api/src/main.ts @@ -1,18 +1,20 @@ -import express from "express"; +import Express from "express"; +import ExpressRedisCache from "express-redis-cache"; +import Redis from "redis"; import * as Config from "./config"; import * as Methods from "./methods"; // Helper functions. -const sendJSON = (res: express.Response, data: object | string) => { +const sendJSON = (res: Express.Response, data: object | string) => { if (typeof data === 'object') data = JSON.stringify(data); res.set('Content-Type', 'application/json'); res.send(data); } -const handleGetError = (res: express.Response, next: express.NextFunction, error: any) => { +const handleGetError = (res: Express.Response, next: Express.NextFunction, error: any) => { if (error.statusCode == 404) { res.status(404); sendJSON(res, { error: 'not_found' }); @@ -21,9 +23,21 @@ const handleGetError = (res: express.Response, next: express.NextFunction, error } } -// Create and set up Express.js app. +// Create Express.js app. -const app = express(); +const app = Express(); + +// Set up Redis caching on all routes. + +const redis = Redis.createClient(Config.redisUrl); +const cache = ExpressRedisCache({ + client: redis, + prefix: 'dso', + expire: 60*60*24, // Cache entries expire after one day. +}) +app.use(cache.route()); + +// Define routes for REST API. app.get('/', (req, res) => res.send('Data Science Ontology API')); diff --git a/api/yarn.lock b/api/yarn.lock index c106b05..7391d28 100644 --- a/api/yarn.lock +++ b/api/yarn.lock @@ -23,6 +23,14 @@ version "1.2.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" +"@types/express-redis-cache@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/express-redis-cache/-/express-redis-cache-1.1.0.tgz#b0b0742c56c1de2672ad6873e8074a6c930afe0d" + dependencies: + "@types/events" "*" + "@types/express" "*" + "@types/redis" "*" + "@types/express-serve-static-core@*": version "4.16.0" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz#fdfe777594ddc1fe8eb8eccce52e261b496e43e7" @@ -31,7 +39,7 @@ "@types/node" "*" "@types/range-parser" "*" -"@types/express@^4.16.0": +"@types/express@*", "@types/express@^4.16.0": version "4.16.0" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.16.0.tgz#6d8bc42ccaa6f35cf29a2b7c3333cb47b5a32a19" dependencies: @@ -61,6 +69,13 @@ version "1.2.2" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.2.tgz#fa8e1ad1d474688a757140c91de6dace6f4abc8d" +"@types/redis@*", "@types/redis@^2.8.6": + version "2.8.6" + resolved "https://registry.yarnpkg.com/@types/redis/-/redis-2.8.6.tgz#3674d07a13ad76bccda4c37dc3909e4e95757e7e" + dependencies: + "@types/events" "*" + "@types/node" "*" + "@types/request-promise-native@^1.0.15": version "1.0.15" resolved "https://registry.yarnpkg.com/@types/request-promise-native/-/request-promise-native-1.0.15.tgz#5b3369fc6aaf9e7fef7b6b688aef4c5759623e16" @@ -117,6 +132,12 @@ assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" +async@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" + dependencies: + lodash "^4.17.10" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -162,6 +183,10 @@ co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" +colors@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.1.tgz#4accdb89cf2cabc7f982771925e9468784f32f3d" + combined-stream@1.0.6, combined-stream@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" @@ -204,6 +229,10 @@ delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" +denque@^1.2.3: + version "1.3.0" + resolved "https://registry.yarnpkg.com/denque/-/denque-1.3.0.tgz#681092ef44a630246d3f6edb2a199230eae8e76b" + depd@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" @@ -239,6 +268,14 @@ etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" +express-redis-cache@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/express-redis-cache/-/express-redis-cache-1.1.3.tgz#93eb6b09df1ff74a14a7f6caccb5d0d975010c62" + dependencies: + async "^2.6.1" + colors "^1.3.0" + redis "^2.4.2" + express@^4.16.3: version "4.16.3" resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53" @@ -510,6 +547,22 @@ raw-body@2.3.2: iconv-lite "0.4.19" unpipe "1.0.0" +redis-commands@^1.2.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.3.5.tgz#4495889414f1e886261180b1442e7295602d83a2" + +redis-parser@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-2.6.0.tgz#52ed09dacac108f1a631c07e9b69941e7a19504b" + +redis@^2.4.2, "redis@https://github.com/NodeRedis/node_redis": + version "2.8.0" + resolved "https://github.com/NodeRedis/node_redis#27bb93ac19157bdc7b7958bef012e4b266d156ae" + dependencies: + denque "^1.2.3" + redis-commands "^1.2.0" + redis-parser "^2.6.0" + request-promise-core@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6"