Skip to content

Commit aaf2cef

Browse files
author
adithya.sathu
committed
consistency across and more more validations
1 parent 3c8b361 commit aaf2cef

15 files changed

+421
-130
lines changed

README.md

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
### save-state (WIP)
1+
### save-state
22

33
Abstraction for data store with In-Memory cache, MongoDB, Redis and Elastic without worrying about the internal implementations
44

@@ -31,7 +31,9 @@ client.connect();
3131

3232
**createClient** takes optional data store config, with no config passed returns In-Memory Store Client
3333

34-
Example below shows Mongo Client creation with mongo store config
34+
Examples below
35+
36+
- **Mongo Client**
3537

3638

3739
```js
@@ -46,6 +48,36 @@ const client = Store.createClient(
4648
```
4749

4850

51+
- **Redis Client**
52+
53+
54+
```js
55+
const client = Store.createClient(
56+
{
57+
redis: {
58+
url: "redis://localhost:6379/0",
59+
},
60+
});
61+
```
62+
63+
64+
65+
- **Elasticsearch Client**
66+
67+
68+
```js
69+
const client = Store.createClient(
70+
{
71+
redis : {
72+
url: "localhost:9200",
73+
index: "example-index",
74+
type: "example-type",
75+
},
76+
});
77+
```
78+
79+
80+
4981
##### set API
5082

5183
**set** takes JSON document whose key is string and value is a document. Can pass more than one document to be saved at once.
@@ -88,7 +120,7 @@ client.set({ yoo: "not a document"}) // throws error
88120
// retrieve document
89121
client.get(["key-1"]);
90122

91-
// save retrieve documents
123+
// retrieve multiple documents
92124
client.get(["key-1", "key-2"]);
93125

94126
```

config/default.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ mongo:
1616
secsAbortAfter: 300
1717
elastic:
1818
url: localhost:9200
19-
apiVersion: "7.4"
19+
apiVersion: "7.6"
2020
index: store
2121
type: doc-store
2222
retry:

config/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ mongo:
1717
elastic:
1818
url: localhost:9200
1919
index: store
20-
apiVersion: "7.4"
20+
apiVersion: "7.6"
2121
type: doc-store
2222
retry:
2323
secsWaitBetween: 3

docs/local-setup.md

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Run `docker -v` to confirm docker is running
1111

1212
##### Docker images defined in compose file
1313

14-
- **mongodb** - local Mongo DB instance Running on mongodb://localhost:27017
14+
- **mongodb** - Mongo DB instance Running on mongodb://localhost:27017
1515

1616
- **mongo-express** - Web based MongoDB admin interface running on http://localhost:9005/
1717

@@ -20,19 +20,46 @@ user id: admin
2020
password: password
2121
```
2222

23-
- **redis** - local RedisDB instance Running on redis://localhost:6379/0
23+
- **redis** - RedisDB instance Running on redis://localhost:6379/0
2424

2525
- **redis-commander** - Web based Redis admin interface running on http://localhost:8081/
2626

27+
- **elastic** - Elasticsearch instance running on http://localhost:9200
2728

2829

29-
30-
`docker ps -a` should show something like below
30+
`docker ps -a` list of docker containers and status
3131
```
3232
adithya.sathu$ docker ps -a
33-
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
34-
d5c090888ef0 mongo-express "tini -- /docker-ent…" 29 hours ago Up 29 hours 0.0.0.0:9005->8081/tcp save-state_mongodb-ui_1
35-
85683df259ba mongo:4 "docker-entrypoint.s…" 29 hours ago Up 29 hours 0.0.0.0:27017->27017/tcp mongodb
33+
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
34+
ad4795e13f68 elasticsearch:7.6.2 "/usr/local/bin/dock…" About an hour ago Up About an hour 0.0.0.0:9200->9200/tcp, 9300/tcp save-state_elastic_1
35+
65494191b3dd rediscommander/redis-commander:latest "/usr/bin/dumb-init …" 5 days ago Up 2 hours (healthy) 0.0.0.0:8081->8081/tcp redis-commander
36+
428c7853d67d redis:4 "docker-entrypoint.s…" 5 days ago Up 2 hours 0.0.0.0:6379->6379/tcp save-state_redis_1
37+
d5c090888ef0 mongo-express "tini -- /docker-ent…" 8 days ago Up 2 hours 0.0.0.0:9005->8081/tcp save-state_mongodb-ui_1
38+
85683df259ba mongo:4 "docker-entrypoint.s…" 8 days ago Up 2 hours 0.0.0.0:27017->27017/tcp mongodb
3639
```
3740

38-
`docker logs <CONTAINER ID>` would show docker logs of that container
41+
`docker logs <CONTAINER ID>` docker logs of the container
42+
43+
`docker start <CONTAINER ID>` start container
44+
45+
`docker restart <CONTAINER ID>` restart container
46+
47+
`docker stop <CONTAINER ID>` stop container
48+
49+
`docker rm <CONTAINER ID>` remove container, obviously you have to stop it first
50+
51+
`docker images` list of images installed
52+
53+
```
54+
adithya.sathu$ docker images
55+
REPOSITORY TAG IMAGE ID CREATED SIZE
56+
redis 4 f54239c50400 9 days ago 89.2MB
57+
mongo 4 c5e5843d9f5f 13 days ago 387MB
58+
elasticsearch 7.6.2 f29a1ee41030 2 weeks ago 791MB
59+
mongo-express latest a36d72e09c39 2 weeks ago 127MB
60+
rediscommander/redis-commander latest abbafbd36f62 3 weeks ago 107MB
61+
```
62+
63+
`docker rmi <IMAGE ID>` remove image, again you have to stop and remove the container first
64+
65+
**Dont forget ` docker -help` would show all the options available**

src/elastic-store.ts

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { IStore, HealthEvents, IElasticStoreConfig } from "./interfaces";
2-
import { Client } from "elasticsearch";
3-
import { logger as log } from "./logger";
41
import { inspect } from "util";
52
import { EventEmitter } from "events";
3+
import { Client } from "elasticsearch";
4+
import { logger as log } from "./logger";
5+
import { IStore, HealthEvents, IElasticStoreConfig } from "./interfaces";
6+
import {validate} from "./validator";
67

78
export class ElasticStore extends EventEmitter implements IStore {
89
public client: Client;
@@ -29,7 +30,9 @@ export class ElasticStore extends EventEmitter implements IStore {
2930
}
3031

3132
public async disconnect() {
32-
if (!this.client) { return; }
33+
if (!this.client) {
34+
throw new Error("Client is not initialized");
35+
}
3336
this.emit(HealthEvents.Ready, false);
3437
return this.client.close();
3538
}
@@ -38,8 +41,8 @@ export class ElasticStore extends EventEmitter implements IStore {
3841
if (!this.client) {
3942
throw new Error("Client is not initialized");
4043
}
41-
if (!keys || keys.length === 0) {
42-
return "nothing to query";
44+
if (!keys || keys.length === 0 || keys.includes("")) {
45+
throw new Error("invalid keys");
4346
}
4447
return this.client.mget({
4548
index: this.options.index,
@@ -64,8 +67,9 @@ export class ElasticStore extends EventEmitter implements IStore {
6467
public async remove(key: string) {
6568
if (!this.client) {
6669
throw new Error("Client is not initialized");
70+
} else if (!key) {
71+
throw new Error("not a valid key");
6772
}
68-
6973
await this.client.delete({
7074
index: this.options.index,
7175
type : this.options.type,
@@ -78,15 +82,10 @@ export class ElasticStore extends EventEmitter implements IStore {
7882
if (!this.client) {
7983
throw new Error("Client is not initialized");
8084
}
81-
82-
await this.client.deleteByQuery({
85+
// delete the index
86+
await this.client.indices.delete({
8387
index: this.options.index,
8488
ignoreUnavailable: true,
85-
body: {
86-
query: {
87-
match_all: {},
88-
},
89-
},
9089
});
9190

9291
}
@@ -95,11 +94,10 @@ export class ElasticStore extends EventEmitter implements IStore {
9594
if (!this.client) {
9695
throw new Error("Client is not initialized");
9796
}
98-
99-
const keys = Object.keys(mappings);
100-
if (keys.length === 0) {
101-
return;
97+
if (!validate(mappings)) {
98+
throw new Error("not a valid object to save");
10299
}
100+
const keys = Object.keys(mappings);
103101
let body = "";
104102
const indexName = this.options.index;
105103
const typeName = this.options.type;

src/memory-store.ts

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { validate } from "./validator";
12
import { EventEmitter } from "events";
23
import { IStore, HealthEvents } from "./interfaces";
34

@@ -7,41 +8,51 @@ export class MemoryStore extends EventEmitter implements IStore {
78

89
constructor() { super(); }
910

10-
public connect() {
11+
public async connect() {
1112
this.emit(HealthEvents.Ready, true);
1213
return Promise.resolve();
1314
}
1415

15-
public disconnect() {
16+
public async disconnect() {
17+
this.cache = {};
18+
this.emit(HealthEvents.Ready, false);
1619
return Promise.resolve();
1720
}
1821

19-
public isReady(): Promise<void> {
22+
public async isReady(): Promise<void> {
2023
this.emit(HealthEvents.Ready, true);
2124
return Promise.resolve();
2225
}
2326

24-
public get(keys: string[]) {
27+
public async get(keys: string[]) {
28+
if (!keys || keys.length === 0 || keys.includes("")) {
29+
throw new Error("invalid keys");
30+
}
2531
const foundItems: any = {};
2632
keys.forEach((k) => {
27-
foundItems[k] = this.cache[k];
33+
foundItems[k] = this.cache[k] || null;
2834
});
2935
return foundItems;
3036
}
3137

32-
public set(map: any) {
33-
const keys = Object.keys(map);
38+
public async set(mappings: any) {
39+
if (!validate(mappings)) {
40+
throw new Error("not a valid object to save");
41+
}
42+
const keys = Object.keys(mappings);
3443
keys.forEach((k) => {
35-
this.cache[k] = map[k];
44+
this.cache[k] = mappings[k];
3645
});
3746
}
3847

39-
public remove(key: string) {
40-
if (!this.cache.hasOwnProperty(key)) { throw new Error(`${key} not found`); }
41-
delete this.cache[key];
48+
public async remove(key: string) {
49+
if (!key) {
50+
throw new Error("not a valid key");
51+
}
52+
delete this.cache[key];
4253
}
4354

44-
public removeAll() {
55+
public async removeAll() {
4556
this.cache = {};
4657
}
4758
}

src/mongo-store.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { EventEmitter } from "events";
2+
import { validate } from "./validator";
23
import { logger as log } from "./logger";
34
import { MongoClient, Db } from "mongodb";
45
import { promisify, inspect } from "util";
@@ -39,6 +40,9 @@ export class MongoStore extends EventEmitter implements IStore {
3940
}
4041

4142
public isReady(): Promise<void> {
43+
if (!this.db) {
44+
throw new Error("Client is not initialized");
45+
}
4246
return this.db.stats().then(() => {
4347
this.emit(HealthEvents.Ready, true);
4448
}).catch((err) => {
@@ -48,9 +52,11 @@ export class MongoStore extends EventEmitter implements IStore {
4852
}
4953

5054
public async disconnect() {
51-
if (this.client) {
52-
return this.client.close();
55+
if (!this.client) {
56+
throw new Error("Client is not initialized");
5357
}
58+
return this.client.close();
59+
5460
}
5561

5662
public async removeAll() {
@@ -63,6 +69,8 @@ export class MongoStore extends EventEmitter implements IStore {
6369
public async remove(key: string) {
6470
if (!this.client) {
6571
throw new Error("Client is not initialized");
72+
} else if (!key) {
73+
throw new Error("not a valid key");
6674
}
6775
return this.collection.deleteOne({_id: key});
6876
}
@@ -71,6 +79,9 @@ export class MongoStore extends EventEmitter implements IStore {
7179
if (!this.client) {
7280
throw new Error("Client is not initialized");
7381
}
82+
if (!keys || keys.length === 0 || keys.includes("")) {
83+
throw new Error("invalid keys");
84+
}
7485
const docs = await this.collection.find({_id : { $in : keys }}).toArray();
7586
const mapping: any = {};
7687
keys.forEach((k) => mapping[k] = null);
@@ -85,10 +96,10 @@ export class MongoStore extends EventEmitter implements IStore {
8596
if (!this.client) {
8697
throw new Error("Client is not initialized");
8798
}
88-
const keys = Object.keys(mappings);
89-
if (keys.length === 0) {
90-
return;
99+
if (!validate(mappings)) {
100+
throw new Error("not a valid object to save");
91101
}
102+
const keys = Object.keys(mappings);
92103
const operations: any [] = [];
93104
keys.forEach((key) => {
94105
const value = mappings[key];

0 commit comments

Comments
 (0)