Skip to content

Commit fed9d75

Browse files
author
Felix Robles
committed
add small redis client
1 parent b7c8d06 commit fed9d75

File tree

3 files changed

+127
-8
lines changed

3 files changed

+127
-8
lines changed

package-lock.json

Lines changed: 36 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"@types/mysql": "^2.15.5",
6363
"@types/node": "^10.11.3",
6464
"@types/pg": "^7.4.11",
65+
"@types/redis": "^2.8.11",
6566
"@types/uuid": "^3.4.4",
6667
"@types/validator": "^9.4.2",
6768
"axios": "^0.18.0",
@@ -72,6 +73,7 @@
7273
"lodash": "^4.17.11",
7374
"mysql": "^2.16.0",
7475
"pg": "^7.5.0",
76+
"redis": "^2.8.0",
7577
"uuid": "^3.3.2",
7678
"validator": "^10.8.0"
7779
},
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { Container } from "inversify"
2+
import { Logger } from "../../../logging"
3+
import { ClientOpts, RedisClient, createClient } from "redis"
4+
import { Process } from "../../../runtime"
5+
import { promisify } from "util"
6+
7+
export class RedisStore implements Process {
8+
private client?: RedisClient
9+
private logger?: Logger
10+
private healthyState: boolean = false
11+
12+
constructor(private connectionOptions?: ClientOpts) {}
13+
14+
public isHealthy(): boolean {
15+
return this.healthyState
16+
}
17+
18+
public getClient(): RedisClient {
19+
if (this.client === undefined) {
20+
throw new Error(
21+
"The RedisStore is not currently open and cannot be used. Check that the store has had .startup() called and that the Promise has successfully returned."
22+
)
23+
}
24+
25+
return this.client
26+
}
27+
28+
public async startup(container: Container): Promise<void> {
29+
if (this.client === undefined) {
30+
this.client = createClient(this.connectionOptions)
31+
32+
// Handle errors and mark the connection as unhealthy
33+
this.client.on("error", (err) => {
34+
if (container.isBound(Logger)) {
35+
this.logger = container.get(Logger)
36+
this.logger.error("RedisStore encountered an error", err)
37+
}
38+
39+
this.healthyState = false
40+
})
41+
42+
this.client.on("end", (err) => {
43+
if (container.isBound(Logger)) {
44+
this.logger = container.get(Logger)
45+
this.logger.error("RedisStore encountered an error", err)
46+
}
47+
48+
this.healthyState = false
49+
})
50+
51+
// listen for the connection to mark it as healthy
52+
this.client.on("connect", () => {
53+
this.healthyState = true
54+
})
55+
56+
container.bind(RedisStore).toConstantValue(this)
57+
} else {
58+
throw new Error(
59+
"A RedisClient already exists and cannot be reinstated without first being closed. This usually happens from calling startup on an existing Runtime."
60+
)
61+
}
62+
}
63+
64+
public async shutdown(container: Container): Promise<void> {
65+
if (this.client) {
66+
container.unbind(RedisStore)
67+
68+
await promisify(this.client.quit.bind(this.client))()
69+
70+
// Dereference the pool
71+
this.client = undefined
72+
this.healthyState = false
73+
}
74+
}
75+
76+
public async sendCommand<A, B>(command: string, args?: A): Promise<B> {
77+
if (this.client === undefined) {
78+
throw new Error(
79+
"RedisStore cannot send a command on a closed connection. This usually happens from forgetting to call startup."
80+
)
81+
}
82+
83+
let result: B = await promisify(
84+
this.client.sendCommand.bind(this.client)
85+
)(command, args)
86+
87+
return result
88+
}
89+
}

0 commit comments

Comments
 (0)