slonik-interceptor-query-cache 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,11 +14,17 @@ Query cache interceptor is initialised using a custom storage service. The [Exam
14
14
 
15
15
  Which queries are cached is controlled using cache attributes. Cache attributes are comments starting with `-- @cache-` prefix. Only queries with cache attributes are cached (see [Cache attributes](#cache-attributes))
16
16
 
17
+ ## Behavior
18
+
19
+ * Does not cache queries inside of a transaction.
20
+ * Does not take into account the query parameters.
21
+
17
22
  ## Cache attributes
18
23
 
19
24
  |Cache attribute|Description|Required?|Default|
20
25
  |---|---|---|---|
21
26
  |`@cache-ttl`|Number (in seconds) to cache the query for.|Yes|N/A|
27
+ |`@cache-key`|Key (`/^[A-Za-z0-9\-_:]+$/`) that uniquely identifies the query.|Yes|N/A|
22
28
 
23
29
  ### Example usage
24
30
 
@@ -39,19 +45,16 @@ const nodeCache = new NodeCache({
39
45
  useClones: false,
40
46
  });
41
47
 
42
- const hashQuery = (query: QueryType): string => {
43
- return JSON.stringify(query);
44
- };
45
-
46
48
  const pool = await createPool('postgres://', {
47
49
  interceptors: [
48
50
  createQueryCacheInterceptor({
49
51
  storage: {
50
- get: (query) => {
51
- return cache.get(hashQuery(query)) || null;
52
+ get: (query, cacheAttributes) => {
53
+ // Returning null results in the query being executed.
54
+ return cache.get(cacheAttributes.key) || null;
52
55
  },
53
56
  set: (query, cacheAttributes, queryResult) => {
54
- cache.set(hashQuery(query), queryResult, cacheAttributes.ttl);
57
+ cache.set(cacheAttributes.key, queryResult, cacheAttributes.ttl);
55
58
  },
56
59
  },
57
60
  }),
@@ -60,6 +63,7 @@ const pool = await createPool('postgres://', {
60
63
 
61
64
  await connection.any(sql`
62
65
  -- @cache-ttl 60
66
+ -- @cache-key foo
63
67
  SELECT
64
68
  id,
65
69
  code_alpha_2
@@ -67,4 +71,4 @@ await connection.any(sql`
67
71
  WHERE
68
72
  code_alpha_2 = ${countryCode}
69
73
  `);
70
- ```
74
+ ```
@@ -1,5 +1,6 @@
1
1
  import type { Interceptor, Query, QueryResultRow, QueryResult } from 'slonik';
2
2
  declare type CacheAttributes = {
3
+ key: string;
3
4
  ttl: number;
4
5
  };
5
6
  declare type Storage = {
@@ -13,6 +13,9 @@ const createQueryCacheInterceptor = (configurationInput) => {
13
13
  return {
14
14
  beforeQueryExecution: async (context, query) => {
15
15
  var _a;
16
+ if (context.transactionId) {
17
+ return null;
18
+ }
16
19
  const cacheAttributes = (_a = context.sandbox.cache) === null || _a === void 0 ? void 0 : _a.cacheAttributes;
17
20
  if (!cacheAttributes) {
18
21
  return null;
@@ -28,6 +31,9 @@ const createQueryCacheInterceptor = (configurationInput) => {
28
31
  },
29
32
  beforeQueryResult: async (context, query, result) => {
30
33
  var _a;
34
+ if (context.transactionId) {
35
+ return null;
36
+ }
31
37
  const cacheAttributes = (_a = context.sandbox.cache) === null || _a === void 0 ? void 0 : _a.cacheAttributes;
32
38
  if (cacheAttributes) {
33
39
  await configuration.storage.set(query, cacheAttributes, result);
@@ -35,6 +41,9 @@ const createQueryCacheInterceptor = (configurationInput) => {
35
41
  return null;
36
42
  },
37
43
  beforeTransformQuery: async (context, query) => {
44
+ if (context.transactionId) {
45
+ return null;
46
+ }
38
47
  const cacheAttributes = (0, utilities_1.extractCacheAttributes)(query.sql);
39
48
  if (!cacheAttributes) {
40
49
  return null;
@@ -1,3 +1,4 @@
1
1
  export declare const extractCacheAttributes: (subject: string) => {
2
+ key: string;
2
3
  ttl: number;
3
4
  } | null;
@@ -2,10 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.extractCacheAttributes = void 0;
4
4
  const extractCacheAttributes = (subject) => {
5
- const matches = /-- @cache-ttl (\d+)/u.exec(subject);
6
- if (matches) {
5
+ var _a, _b;
6
+ const ttl = (_a = /-- @cache-ttl (\d+)/u.exec(subject)) === null || _a === void 0 ? void 0 : _a[1];
7
+ if (ttl) {
8
+ const key = (_b = /-- @cache-key ([a-zA-Z0-9\-_:/]+)/ui.exec(subject)) === null || _b === void 0 ? void 0 : _b[1];
9
+ if (!key) {
10
+ throw new Error('@cache-key must be specified when @cache-ttl is specified.');
11
+ }
7
12
  return {
8
- ttl: Number(matches[1]),
13
+ key,
14
+ ttl: Number(ttl),
9
15
  };
10
16
  }
11
17
  return null;
package/package.json CHANGED
@@ -57,7 +57,7 @@
57
57
  "test": "NODE_ENV=test nyc ava --verbose --serial"
58
58
  },
59
59
  "typings": "./dist/src/index.d.ts",
60
- "version": "2.1.0",
60
+ "version": "2.2.0",
61
61
  "peerDependencies": {
62
62
  "slonik": ">=27.0.0"
63
63
  },
@@ -22,6 +22,7 @@ type Sandbox = {
22
22
  };
23
23
 
24
24
  type CacheAttributes = {
25
+ key: string,
25
26
  ttl: number,
26
27
  };
27
28
 
@@ -45,6 +46,10 @@ export const createQueryCacheInterceptor = (configurationInput: ConfigurationInp
45
46
 
46
47
  return {
47
48
  beforeQueryExecution: async (context, query) => {
49
+ if (context.transactionId) {
50
+ return null;
51
+ }
52
+
48
53
  const cacheAttributes = (context.sandbox as Sandbox).cache?.cacheAttributes;
49
54
 
50
55
  if (!cacheAttributes) {
@@ -64,6 +69,10 @@ export const createQueryCacheInterceptor = (configurationInput: ConfigurationInp
64
69
  return null;
65
70
  },
66
71
  beforeQueryResult: async (context, query, result) => {
72
+ if (context.transactionId) {
73
+ return null;
74
+ }
75
+
67
76
  const cacheAttributes = (context.sandbox as Sandbox).cache?.cacheAttributes;
68
77
 
69
78
  if (cacheAttributes) {
@@ -73,6 +82,10 @@ export const createQueryCacheInterceptor = (configurationInput: ConfigurationInp
73
82
  return null;
74
83
  },
75
84
  beforeTransformQuery: async (context, query) => {
85
+ if (context.transactionId) {
86
+ return null;
87
+ }
88
+
76
89
  const cacheAttributes = extractCacheAttributes(query.sql);
77
90
 
78
91
  if (!cacheAttributes) {
@@ -1,9 +1,16 @@
1
1
  export const extractCacheAttributes = (subject: string) => {
2
- const matches = /-- @cache-ttl (\d+)/u.exec(subject);
2
+ const ttl = /-- @cache-ttl (\d+)/u.exec(subject)?.[1];
3
+
4
+ if (ttl) {
5
+ const key = /-- @cache-key ([a-zA-Z0-9\-_:/]+)/ui.exec(subject)?.[1];
6
+
7
+ if (!key) {
8
+ throw new Error('@cache-key must be specified when @cache-ttl is specified.');
9
+ }
3
10
 
4
- if (matches) {
5
11
  return {
6
- ttl: Number(matches[1]),
12
+ key,
13
+ ttl: Number(ttl),
7
14
  };
8
15
  }
9
16