@technicity/data-service-generator 0.11.0-next.0 → 0.11.0-next.2

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.
@@ -249,7 +249,7 @@ async function getSDKSource(input, specialCaseUuidColumn, supplementClientOpts)
249
249
  param1: ${findOnes
250
250
  .map((findOne) => `{ ${findOne.name}: ${findOne.type}${findOne.nullable ? " | null" : ""} }`)
251
251
  .join(" | ")},
252
- param2?: { fields?: ${x.typeFieldsName}, correlationId?: string, context?: TContext }
252
+ param2?: { fields?: ${x.typeFieldsName}, correlationId?: string, skipCache?: boolean, context?: TContext }
253
253
  ): Promise<${x.typeReturnBaseName}> {
254
254
  return this.runtime.resolve(
255
255
  {
@@ -258,7 +258,8 @@ async function getSDKSource(input, specialCaseUuidColumn, supplementClientOpts)
258
258
  args: { $where: param1 },
259
259
  fields: param2?.fields,
260
260
  artifacts,
261
- context: param2?.context
261
+ context: param2?.context,
262
+ skipCache: param2?.skipCache
262
263
  }
263
264
  );
264
265
  }`;
@@ -266,7 +267,7 @@ async function getSDKSource(input, specialCaseUuidColumn, supplementClientOpts)
266
267
  if (x.kind === "getList") {
267
268
  return `async ${x.methodName}(
268
269
  param1: { $where?: ${x.typeWhereName}, $orderBy?: ${x.typeOrderByName}, $limit?: number },
269
- param2?: { fields?: ${x.typeFieldsName}, correlationId?: string, context?: TContext }
270
+ param2?: { fields?: ${x.typeFieldsName}, correlationId?: string, skipCache?: boolean, context?: TContext }
270
271
  ): Promise<Array<${x.typeReturnBaseName}>> {
271
272
  return this.runtime.resolve(
272
273
  {
@@ -275,7 +276,8 @@ async function getSDKSource(input, specialCaseUuidColumn, supplementClientOpts)
275
276
  args: param1,
276
277
  fields: param2?.fields,
277
278
  artifacts,
278
- context: param2?.context
279
+ context: param2?.context,
280
+ skipCache: param2?.skipCache
279
281
  }
280
282
  );
281
283
  }`;
@@ -283,7 +285,7 @@ async function getSDKSource(input, specialCaseUuidColumn, supplementClientOpts)
283
285
  if (x.kind === "getListPaginated") {
284
286
  return `async ${x.methodName}(
285
287
  param1: { $where?: ${x.typeWhereName}, $orderBy?: ${x.typeOrderByName}, $paginate: Paginate },
286
- param2?: { fields?: ${x.typeFieldsName}, correlationId?: string, context?: TContext }
288
+ param2?: { fields?: ${x.typeFieldsName}, correlationId?: string, skipCache?: boolean, context?: TContext }
287
289
  ): Promise<ListPaginated<${x.typeReturnBaseName}>> {
288
290
  return this.runtime.resolve(
289
291
  {
@@ -292,7 +294,8 @@ async function getSDKSource(input, specialCaseUuidColumn, supplementClientOpts)
292
294
  args: param1,
293
295
  fields: param2?.fields,
294
296
  artifacts,
295
- context: param2?.context
297
+ context: param2?.context,
298
+ skipCache: param2?.skipCache
296
299
  }
297
300
  );
298
301
  }`;
@@ -1,10 +1,12 @@
1
1
  import { RedisClientType } from 'redis';
2
2
  import { TResolveParams } from './IRuntime';
3
+ import Stats from './Stats';
3
4
  declare class Cache {
4
- protected logs?: boolean | undefined;
5
5
  client: RedisClientType;
6
6
  waiting?: Set<() => void> | undefined;
7
- constructor(url: string, logs?: boolean | undefined);
7
+ logs?: boolean;
8
+ stats?: Stats;
9
+ constructor(url: string, debug?: string[]);
8
10
  log(message: string): void;
9
11
  pending(): Promise<void>;
10
12
  from(input: TResolveParams): Promise<{
@@ -3,21 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const crypto_1 = require("crypto");
4
4
  const redis_1 = require("redis");
5
5
  const utility_1 = require("./lib/utility");
6
+ const Stats_1 = require("./Stats");
6
7
  class Cache {
7
- constructor(url, logs) {
8
- this.logs = logs;
8
+ constructor(url, debug) {
9
9
  this.waiting = new Set();
10
- this.client = (0, redis_1.createClient)({ url: `redis://${url}` });
11
- this.client.connect();
12
- this.client.on("connect", () => {
10
+ if (debug?.includes("Cache"))
11
+ this.logs = true;
12
+ const client = this.client =
13
+ (0, redis_1.createClient)({ url: `redis://${url}` });
14
+ client.connect();
15
+ client.on("connect", () => {
13
16
  if (this.waiting)
14
17
  this.waiting.forEach(x => x());
15
18
  this.waiting = undefined;
16
19
  });
20
+ if (debug?.includes("Stats"))
21
+ this.stats = new Stats_1.default(client);
17
22
  }
18
23
  log(message) {
19
24
  if (this.logs)
20
- console.log(message);
25
+ console.log(`\n-- CACHE: ${message}\n`);
21
26
  }
22
27
  async pending() {
23
28
  if (this.waiting)
@@ -50,7 +55,7 @@ class Cache {
50
55
  }
51
56
  if (!pending.length)
52
57
  return;
53
- this.log(`Cache insert: ${key.substring(0, 6)}`);
58
+ this.log(`insert: ${key.substring(0, 6)}`);
54
59
  await Promise.all([
55
60
  redis.set(`cache:${key}`, json),
56
61
  ...pending
@@ -61,11 +66,11 @@ class Cache {
61
66
  const data = await this.client.get(`cache:${key}`);
62
67
  const shorthand = key.substring(0, 6);
63
68
  if (data) {
64
- this.log(`Cache hit: ${shorthand}`);
69
+ this.log(`hit: ${shorthand}`);
65
70
  return JSON.parse(data);
66
71
  }
67
72
  else {
68
- this.log(`Cache miss: ${shorthand}`);
73
+ this.log(`miss: ${shorthand}`);
69
74
  return undefined;
70
75
  }
71
76
  }
@@ -14,6 +14,7 @@ export declare type TResolveParams = {
14
14
  artifacts: IArtifacts;
15
15
  fields?: IField[] | undefined;
16
16
  context?: TContext | undefined;
17
+ skipCache?: boolean;
17
18
  };
18
19
  export declare type TContext = {
19
20
  [k: string]: any;
@@ -24,9 +24,8 @@ class RuntimeMySQL {
24
24
  _RuntimeMySQL_clientCache.set(this, void 0);
25
25
  _RuntimeMySQL_middlewareHandler.set(this, void 0);
26
26
  __classPrivateFieldSet(this, _RuntimeMySQL_middlewareHandler, new shared_1.MiddlewareHandler(), "f");
27
- const debugCache = clientOpts?.debug?.includes("Cache");
28
27
  if (otherOpts.redisHost)
29
- __classPrivateFieldSet(this, _RuntimeMySQL_clientCache, new Cache_1.default(otherOpts.redisHost, debugCache), "f");
28
+ __classPrivateFieldSet(this, _RuntimeMySQL_clientCache, new Cache_1.default(otherOpts.redisHost, clientOpts?.debug), "f");
30
29
  if (otherOpts.supplementClientOpts) {
31
30
  clientOpts = {
32
31
  supportBigNumbers: true,
@@ -0,0 +1,12 @@
1
+ import { RedisClientType } from '@redis/client';
2
+ declare class Stats {
3
+ client: RedisClientType<any>;
4
+ constructor(client: RedisClientType<any>);
5
+ updateStats: (ms: number, category: string) => Promise<void>;
6
+ }
7
+ declare namespace timer {
8
+ type Callback = (time: number, ...params: any[]) => void;
9
+ type Params<T> = T extends (ms: number, ...params: infer U) => any ? U : never;
10
+ }
11
+ export declare function timer(): <T extends timer.Callback>(callback: T, ...args: timer.Params<T>) => void;
12
+ export default Stats;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.timer = void 0;
4
+ const perf_hooks_1 = require("perf_hooks");
5
+ class Stats {
6
+ constructor(client) {
7
+ this.client = client;
8
+ this.updateStats = async (ms, category) => {
9
+ const redis = this.client;
10
+ const requests = Number(await redis.get(`stats:${category}_requests`)) || 0;
11
+ const average = Number(await redis.get(`stats:${category}_avg`)) || 0;
12
+ const max = Number(await redis.get(`stats:${category}_max`)) || 0;
13
+ const min = Number(await redis.get(`stats:${category}_min`)) || Infinity;
14
+ const newTotalRequests = requests + 1;
15
+ const newAverage = (average * requests + ms) / newTotalRequests;
16
+ await redis.set(`stats:${category}_requests`, newTotalRequests);
17
+ await redis.set(`stats:${category}_avg`, newAverage);
18
+ if (ms > max)
19
+ await redis.set(`stats:${category}_max`, ms);
20
+ if (ms < min)
21
+ await redis.set(`stats:${category}_min`, ms);
22
+ };
23
+ }
24
+ }
25
+ function timer() {
26
+ const start = perf_hooks_1.performance.now();
27
+ return (callback, ...args) => {
28
+ callback(perf_hooks_1.performance.now() - start, ...args);
29
+ };
30
+ }
31
+ exports.timer = timer;
32
+ exports.default = Stats;
@@ -22,6 +22,7 @@ const SDKNotFoundError_1 = require("./SDKNotFoundError");
22
22
  const SDKBadWhereError_1 = require("./SDKBadWhereError");
23
23
  const stringifyWhere_1 = require("./stringifyWhere");
24
24
  const getOrderBy_1 = require("./getOrderBy");
25
+ const Stats_1 = require("../Stats");
25
26
  async function resolve(input, dbCall, formatQuery, beginTransaction, dialect, middlewareHandler, context, cache) {
26
27
  // https://github.com/prisma/prisma/blob/822198e5ba21535364d20c86901b8c3778ebf6a3/packages/client/src/runtime/getPrismaClient.ts#L1087
27
28
  let index = -1;
@@ -46,7 +47,7 @@ function _resolve(input, dbCall, formatQuery, beginTransaction, dialect, context
46
47
  case "findUnique":
47
48
  case "findMany":
48
49
  case "findManyPaginated":
49
- return cache ?
50
+ return cache && !input.skipCache ?
50
51
  getCached(input, dbCall, formatQuery, dialect, cache) :
51
52
  getData(input, dbCall, formatQuery, dialect);
52
53
  case "create":
@@ -266,12 +267,24 @@ async function getData(input, dbCall, formatQuery, dialect) {
266
267
  return data;
267
268
  }
268
269
  async function getCached(input, dbCall, formatQuery, dialect, cache) {
270
+ const done = (0, Stats_1.timer)();
271
+ const { stats } = cache;
269
272
  const { request, cached } = await cache.from(input);
270
- if (cached)
271
- return cached;
272
- ensureUuidSelect(input);
273
- const results = await getData(input, dbCall, formatQuery, dialect);
274
- cache.insert(request, results);
273
+ let results;
274
+ if (cached) {
275
+ if (stats)
276
+ done(stats.updateStats, "get_redis");
277
+ results = cache;
278
+ }
279
+ else {
280
+ ensureUuidSelect(input);
281
+ results = await getData(input, dbCall, formatQuery, dialect);
282
+ cache.insert(request, results);
283
+ if (stats)
284
+ done(stats.updateStats, "get_mysql");
285
+ }
286
+ if (stats)
287
+ done(stats.updateStats, "get");
275
288
  return results;
276
289
  }
277
290
  function ensureUuidSelect(input) {
@@ -281,7 +294,7 @@ function ensureUuidSelect(input) {
281
294
  const { scalarFields, relationFields } = artifacts[type];
282
295
  if (!scalarFields.includes("uuid"))
283
296
  return;
284
- const fields = input.fields || [];
297
+ const fields = input.fields;
285
298
  if (!fields.includes("uuid"))
286
299
  fields.unshift("uuid");
287
300
  for (const field of fields)
package/package.json CHANGED
@@ -1,15 +1,14 @@
1
1
  {
2
2
  "name": "@technicity/data-service-generator",
3
- "version": "0.11.0-next.0",
3
+ "version": "0.11.0-next.2",
4
4
  "main": "./dist/index.js",
5
5
  "files": [
6
6
  "dist"
7
7
  ],
8
8
  "scripts": {
9
9
  "compile": "rm -rf dist && tsc",
10
- "publish:next": "npm version preminor --preid next",
10
+ "publish:next": "npm version prerelease --preid next",
11
11
  "preversion": "npm run compile",
12
- "postversion": "npm publish",
13
12
  "generate": "npm run compile && concurrently \"node ./test/mysql/generate.js\" \"node ./test/mysql8/generate.js\"",
14
13
  "test": "npm run generate && mocha ./test/addNullFallbacks.test.js && mocha ./test/stringifyWhere.test.js && npm run test:sdk",
15
14
  "test:prepare": "docker-compose down --volumes && docker-compose up -d --build",