sqlcache 2.9.0 → 2.9.1
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/.env.example +31 -17
- package/{readme.md → README.md} +106 -28
- package/core/autoInvalidate.js +14 -4
- package/core/autoKey.js +44 -8
- package/dbConnector.js +418 -65
- package/docs/API.md +161 -61
- package/docs/CONFIGURATION.md +155 -47
- package/docs/CONTRIBUTING.md +39 -29
- package/docs/EXAMPLES.md +70 -29
- package/docs/MIGRATION.md +141 -42
- package/docs/README.tr.md +75 -27
- package/docs/USE-CASE-BULK.md +48 -17
- package/docs/USE-CASE-ECOMMERCE.md +8 -2
- package/docs/USE-CASE-REALTIME.md +18 -6
- package/docs/USE-CASE-SAAS.md +24 -15
- package/index.d.ts +163 -50
- package/index.js +50 -23
- package/package.json +11 -5
- package/redis.Connector.js +98 -5
package/index.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Type definitions for sqlcache
|
|
3
3
|
* Project: https://github.com/hayatialikeles/sqlcache
|
|
4
|
-
* Definitions by: Ali
|
|
4
|
+
* Definitions by: Hayati Ali Keleş
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/// <reference types="node" />
|
|
8
8
|
|
|
9
9
|
declare module 'sqlcache' {
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Result of a write statement: mysql2's ResultSetHeader (`affectedRows`, `insertId`, `info`,
|
|
12
|
+
* `serverStatus`, `warningStatus`, `changedRows`, `fieldCount`). `warningCount`, `message` and
|
|
13
|
+
* `protocol41` are kept for compatibility; mysql2 does not set them.
|
|
12
14
|
*/
|
|
13
15
|
export interface QueryResult {
|
|
14
16
|
affectedRows?: number;
|
|
@@ -19,6 +21,10 @@ declare module 'sqlcache' {
|
|
|
19
21
|
changedRows?: number;
|
|
20
22
|
fieldCount?: number;
|
|
21
23
|
serverStatus?: number;
|
|
24
|
+
/** Server message, e.g. "Rows matched: 1 Changed: 1 Warnings: 0" */
|
|
25
|
+
info?: string;
|
|
26
|
+
/** Number of warnings */
|
|
27
|
+
warningStatus?: number;
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
/**
|
|
@@ -40,14 +46,23 @@ declare module 'sqlcache' {
|
|
|
40
46
|
// ==================== DATABASE FUNCTIONS ====================
|
|
41
47
|
|
|
42
48
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
49
|
+
* Runs a SQL statement on MySQL. It never reads the cache. After the statement succeeds, every
|
|
50
|
+
* cached key starting with `resetCacheName` (a prefix, or an array of prefixes) is deleted; without
|
|
51
|
+
* it, automatic invalidation applies when CORE_AUTO_INVALIDATION=true or enableAutoInvalidation()
|
|
52
|
+
* is on. A `resetCacheName` replaces the automatic patterns for the call.
|
|
45
53
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
54
|
+
* Prefixes are Redis glob patterns: escape `* ? [ ] \` in user-supplied parts. An empty prefix
|
|
55
|
+
* without REDIS_VHOST deletes every key in that Redis database.
|
|
56
|
+
*
|
|
57
|
+
* On connection errors the statement is attempted up to 3 times, so a write can run twice: make
|
|
58
|
+
* writes idempotent. mysql2 errors carry `err.sql` with the parameter values filled in.
|
|
59
|
+
*
|
|
60
|
+
* @param sql - The SQL statement to execute
|
|
61
|
+
* @param parameters - The parameters to be passed to the SQL statement (optional)
|
|
62
|
+
* @param resetCacheName - Prefix or prefixes of the cache keys to delete after the statement (optional)
|
|
49
63
|
* @param database - The database name to switch to (optional)
|
|
50
|
-
* @returns
|
|
64
|
+
* @returns The mysql2 result: rows for a SELECT, a {@link QueryResult} for a write. Pass the type
|
|
65
|
+
* for reads, e.g. `QuaryCache<User[]>('SELECT ...', [id])`.
|
|
51
66
|
*
|
|
52
67
|
* @example
|
|
53
68
|
* ```typescript
|
|
@@ -57,14 +72,17 @@ declare module 'sqlcache' {
|
|
|
57
72
|
* "users-cache"
|
|
58
73
|
* );
|
|
59
74
|
* console.log(result.insertId);
|
|
75
|
+
*
|
|
76
|
+
* // Several prefixes
|
|
77
|
+
* await QuaryCache("DELETE FROM users WHERE id = ?", [1], ["users:", "profiles:"]);
|
|
60
78
|
* ```
|
|
61
79
|
*/
|
|
62
|
-
export function QuaryCache(
|
|
80
|
+
export function QuaryCache<T = QueryResult>(
|
|
63
81
|
sql: string,
|
|
64
|
-
parameters
|
|
65
|
-
resetCacheName?: string | null,
|
|
82
|
+
parameters?: any[],
|
|
83
|
+
resetCacheName?: string | string[] | null,
|
|
66
84
|
database?: string | null
|
|
67
|
-
): Promise<
|
|
85
|
+
): Promise<T>;
|
|
68
86
|
|
|
69
87
|
/**
|
|
70
88
|
* Retrieves data from cache or database based on the provided SQL query and parameters.
|
|
@@ -79,8 +97,19 @@ declare module 'sqlcache' {
|
|
|
79
97
|
* (`DB_COALESCE_QUERIES=false` turns this off). Auto-generated keys of calls that pass
|
|
80
98
|
* `database` end with `@<database>`, so databases (tenants) never share cache entries.
|
|
81
99
|
*
|
|
100
|
+
* **v2.9.1:** empty results are not written to the cache (they were never served from it), and a
|
|
101
|
+
* cached value that is not a non-empty array is treated as a miss. A read that started before an
|
|
102
|
+
* invalidation in the same process does not write its possibly stale result. A caller that has
|
|
103
|
+
* waited `DB_COALESCE_MAX_WAIT` ms (default 10000) for a shared query starts its own, but still
|
|
104
|
+
* takes the shared result if it arrives first; an `ER_QUERY_TIMEOUT` of the shared query goes to
|
|
105
|
+
* every caller waiting on it.
|
|
106
|
+
*
|
|
107
|
+
* Results are cached for 40000 s as JSON: on a cache hit a `Date` is an ISO string and a `Buffer`
|
|
108
|
+
* is `{ type, data }`, while a miss returns mysql2's types. Without `cacheName` and with automatic
|
|
109
|
+
* keys disabled, the call rejects with `cacheName is required...`.
|
|
110
|
+
*
|
|
82
111
|
* @param sql - The SQL query to be executed
|
|
83
|
-
* @param parameters - The parameters to be passed to the SQL query
|
|
112
|
+
* @param parameters - The parameters to be passed to the SQL query (optional)
|
|
84
113
|
* @param cacheName - The name of the cache to store the data (optional if auto key enabled)
|
|
85
114
|
* @param database - The database name to switch to (optional)
|
|
86
115
|
* @returns A promise that resolves to the retrieved data
|
|
@@ -110,7 +139,7 @@ declare module 'sqlcache' {
|
|
|
110
139
|
*/
|
|
111
140
|
export function getCacheQuery<T = any>(
|
|
112
141
|
sql: string,
|
|
113
|
-
parameters
|
|
142
|
+
parameters?: any[],
|
|
114
143
|
cacheName?: string | null,
|
|
115
144
|
database?: string | null
|
|
116
145
|
): Promise<T[]>;
|
|
@@ -126,13 +155,21 @@ declare module 'sqlcache' {
|
|
|
126
155
|
* optimizer hint also bounds the count. With `DB_PAGINATION_REUSE_TOTAL=true` the total of one
|
|
127
156
|
* page is reused for the other pages of the same query until `cacheName` is invalidated.
|
|
128
157
|
*
|
|
158
|
+
* Each page is cached as `<cacheName>:page<n>:size<m>`, so invalidating `cacheName` clears every
|
|
159
|
+
* page.
|
|
160
|
+
*
|
|
161
|
+
* **v2.9.1:** `LIMIT` is appended on a new line, so SQL ending in a `-- comment` paginates
|
|
162
|
+
* correctly, and a cached value is only used if it is a page object. Without a `cacheName`, an
|
|
163
|
+
* automatic key is used when automatic keys are enabled; otherwise the result is not cached and a
|
|
164
|
+
* one-time warning is logged (before 2.9.1 all such calls shared one cache key).
|
|
165
|
+
*
|
|
129
166
|
* @param sql - The SQL query to execute
|
|
130
|
-
* @param parameters - The parameters to be used in the SQL query
|
|
131
|
-
* @param cacheName - The name of the cache to store the data
|
|
167
|
+
* @param parameters - The parameters to be used in the SQL query (`[]` for none)
|
|
168
|
+
* @param cacheName - The name of the cache to store the data (`null`: see above)
|
|
132
169
|
* @param page - The page number of the data to retrieve (0-based)
|
|
133
170
|
* @param pageSize - The number of records per page (default: 30)
|
|
134
171
|
* @param database - The database name to switch to (optional)
|
|
135
|
-
* @returns A promise that resolves to
|
|
172
|
+
* @returns A promise that resolves to `{ totalCount, pageCount, detail }`
|
|
136
173
|
*
|
|
137
174
|
* @example
|
|
138
175
|
* ```typescript
|
|
@@ -145,7 +182,7 @@ declare module 'sqlcache' {
|
|
|
145
182
|
* const result = await getCacheQueryPagination<Product>(
|
|
146
183
|
* "SELECT * FROM products WHERE category = ?",
|
|
147
184
|
* [5],
|
|
148
|
-
* "products
|
|
185
|
+
* "products:cat:5",
|
|
149
186
|
* 0,
|
|
150
187
|
* 25
|
|
151
188
|
* );
|
|
@@ -158,7 +195,7 @@ declare module 'sqlcache' {
|
|
|
158
195
|
export function getCacheQueryPagination<T = any>(
|
|
159
196
|
sql: string,
|
|
160
197
|
parameters: any[],
|
|
161
|
-
cacheName: string,
|
|
198
|
+
cacheName: string | null | undefined,
|
|
162
199
|
page: number,
|
|
163
200
|
pageSize?: number,
|
|
164
201
|
database?: string | null
|
|
@@ -236,6 +273,9 @@ declare module 'sqlcache' {
|
|
|
236
273
|
* merged. Waits for Redis like delKeyItem, and invalidations that could not run because Redis
|
|
237
274
|
* was unreachable are replayed once it is ready again.
|
|
238
275
|
*
|
|
276
|
+
* Prefixes are Redis glob patterns (`*` is appended): escape `* ? [ ] \` in user-supplied parts.
|
|
277
|
+
* An empty prefix without REDIS_VHOST deletes every key in that Redis database.
|
|
278
|
+
*
|
|
239
279
|
* @param keys - Single prefix or array of prefixes
|
|
240
280
|
* @returns A promise that resolves when deletion is complete
|
|
241
281
|
*
|
|
@@ -253,7 +293,8 @@ declare module 'sqlcache' {
|
|
|
253
293
|
/**
|
|
254
294
|
* Check if Redis connection is healthy.
|
|
255
295
|
* Useful for health-check endpoints and monitoring.
|
|
256
|
-
*
|
|
296
|
+
* **v2.9.1:** with REDIS_ENABLED=false it returns false without opening a connection (2.9.0
|
|
297
|
+
* opened one on the first call).
|
|
257
298
|
*
|
|
258
299
|
* @returns true if Redis is connected and ready
|
|
259
300
|
*
|
|
@@ -289,11 +330,15 @@ declare module 'sqlcache' {
|
|
|
289
330
|
database?: string | null;
|
|
290
331
|
/** Number of records per chunk (default: 1000) */
|
|
291
332
|
chunkSize?: number;
|
|
292
|
-
/**
|
|
293
|
-
|
|
333
|
+
/**
|
|
334
|
+
* Cache name prefix (or prefixes) to reset after insert. Without it, automatic invalidation
|
|
335
|
+
* applies when enabled (v2.9.1).
|
|
336
|
+
*/
|
|
337
|
+
resetCacheName?: string | string[] | null;
|
|
294
338
|
/**
|
|
295
339
|
* v2.9.0: insert all chunks in one transaction (all or nothing, and faster for large
|
|
296
|
-
* inserts). Without it each chunk commits on its own, as before (default: false)
|
|
340
|
+
* inserts). Without it each chunk commits on its own, as before (default: false).
|
|
341
|
+
* v2.9.1: an error from COMMIT is not retried and carries `err.commitOutcomeUnknown = true`.
|
|
297
342
|
*/
|
|
298
343
|
transaction?: boolean;
|
|
299
344
|
}
|
|
@@ -341,6 +386,19 @@ declare module 'sqlcache' {
|
|
|
341
386
|
* Executes a bulk insert operation with automatic chunking for large datasets.
|
|
342
387
|
* Prevents memory issues by splitting large datasets into manageable chunks.
|
|
343
388
|
*
|
|
389
|
+
* The columns are the keys of the first record, and the table and column names are used in the
|
|
390
|
+
* SQL as-is. Never pass untrusted keys: map request or CSV input onto a fixed list of columns.
|
|
391
|
+
* **v2.9.1:** an invalid name is rejected before anything is sent, with a `TypeError`
|
|
392
|
+
* (`bulkInsert: invalid table name "<name>"` / `bulkInsert: invalid column name "<name>"`).
|
|
393
|
+
*
|
|
394
|
+
* After a connection error the insert is retried from the first unacknowledged chunk, so a chunk
|
|
395
|
+
* can be inserted twice. With `transaction: true` a retry starts over, and (v2.9.1) an error from
|
|
396
|
+
* COMMIT is not retried and carries `err.commitOutcomeUnknown = true`.
|
|
397
|
+
*
|
|
398
|
+
* **v2.9.1:** without `resetCacheName`, automatic invalidation (CORE_AUTO_INVALIDATION /
|
|
399
|
+
* enableAutoInvalidation) applies, and invalidation also runs when the insert fails after rows
|
|
400
|
+
* may have been written.
|
|
401
|
+
*
|
|
344
402
|
* @param table - The table name to insert into
|
|
345
403
|
* @param records - Array of objects with column-value pairs
|
|
346
404
|
* @param options - Optional settings for bulk insert
|
|
@@ -374,9 +432,17 @@ declare module 'sqlcache' {
|
|
|
374
432
|
* pool connection) no longer runs the query afterwards. A query that is already running
|
|
375
433
|
* keeps running and caches its result, unless `cancelOnTimeout: true` is set.
|
|
376
434
|
*
|
|
435
|
+
* **v2.9.1:** a timeout during the database switch also stops the query from being sent. With
|
|
436
|
+
* `cancelOnTimeout`, the connection whose query was killed is discarded instead of being
|
|
437
|
+
* returned to the pool, and at most 4 cancellations run at once. Without a `cacheName`, an
|
|
438
|
+
* automatic key is used when automatic keys are enabled; otherwise the result is not cached and
|
|
439
|
+
* a one-time warning is logged (before 2.9.1 all such calls shared one cache key).
|
|
440
|
+
*
|
|
441
|
+
* The call rejects with `Query timeout exceeded` when the timeout fires.
|
|
442
|
+
*
|
|
377
443
|
* @param sql - The SQL query to execute
|
|
378
|
-
* @param parameters - Query parameters
|
|
379
|
-
* @param cacheName - Cache key for storing results
|
|
444
|
+
* @param parameters - Query parameters (optional)
|
|
445
|
+
* @param cacheName - Cache key for storing results (see above when omitted)
|
|
380
446
|
* @param options - Optional timeout and database settings
|
|
381
447
|
* @returns Promise resolving to query results
|
|
382
448
|
*
|
|
@@ -392,19 +458,23 @@ declare module 'sqlcache' {
|
|
|
392
458
|
*/
|
|
393
459
|
export function getCacheQueryWithTimeout<T = any>(
|
|
394
460
|
sql: string,
|
|
395
|
-
parameters
|
|
396
|
-
cacheName
|
|
461
|
+
parameters?: any[],
|
|
462
|
+
cacheName?: string | null,
|
|
397
463
|
options?: QueryTimeoutOptions
|
|
398
464
|
): Promise<T[]>;
|
|
399
465
|
|
|
400
466
|
/**
|
|
401
|
-
* Gracefully closes
|
|
467
|
+
* Gracefully closes the MySQL connection pool; new queries are rejected afterwards.
|
|
402
468
|
* Should be called during application shutdown to prevent connection leaks.
|
|
403
469
|
*
|
|
470
|
+
* The Redis client is not closed: when Redis is enabled, also call `getRedisClient().quit()`,
|
|
471
|
+
* or the open Redis connection keeps the process alive.
|
|
472
|
+
*
|
|
404
473
|
* @example
|
|
405
474
|
* ```typescript
|
|
406
475
|
* process.on('SIGTERM', async () => {
|
|
407
476
|
* await closeConnections();
|
|
477
|
+
* if (process.env.REDIS_ENABLED !== 'false') getRedisClient().quit();
|
|
408
478
|
* process.exit(0);
|
|
409
479
|
* });
|
|
410
480
|
* ```
|
|
@@ -441,7 +511,10 @@ declare module 'sqlcache' {
|
|
|
441
511
|
export interface AutoInvalidationConfig {
|
|
442
512
|
/** Enable auto invalidation */
|
|
443
513
|
enabled?: boolean;
|
|
444
|
-
/**
|
|
514
|
+
/**
|
|
515
|
+
* Table-specific invalidation patterns. A rule replaces the default `<table>_*` and
|
|
516
|
+
* `<table>:*` patterns for its table; keep `<table>:*` when you use automatic keys.
|
|
517
|
+
*/
|
|
445
518
|
tables?: Record<string, string | string[]>;
|
|
446
519
|
}
|
|
447
520
|
|
|
@@ -455,11 +528,31 @@ declare module 'sqlcache' {
|
|
|
455
528
|
autoInvalidation?: AutoInvalidationConfig;
|
|
456
529
|
}
|
|
457
530
|
|
|
531
|
+
/**
|
|
532
|
+
* Options of configure(): like {@link CoreConfig}, and each feature also accepts a boolean.
|
|
533
|
+
*/
|
|
534
|
+
export interface ConfigureOptions {
|
|
535
|
+
/** Auto key generation config, or `true`/`false` */
|
|
536
|
+
autoKey?: AutoKeyConfig | boolean;
|
|
537
|
+
/** Auto invalidation config, or `true`/`false` */
|
|
538
|
+
autoInvalidation?: AutoInvalidationConfig | boolean;
|
|
539
|
+
}
|
|
540
|
+
|
|
458
541
|
/**
|
|
459
542
|
* Enables auto cache key generation feature.
|
|
460
|
-
* When enabled, cacheName parameter becomes optional in getCacheQuery()
|
|
543
|
+
* When enabled, the cacheName parameter becomes optional in getCacheQuery() and
|
|
544
|
+
* tx.getCacheQuery(), and (v2.9.1) may be omitted in getCacheQueryPagination() and
|
|
545
|
+
* getCacheQueryWithTimeout(). Same as CORE_AUTO_FEATURES=true.
|
|
546
|
+
*
|
|
547
|
+
* **v2.9.1:** `enableAutoKey(false)` disables the feature (before 2.9.1 it enabled it). Queries
|
|
548
|
+
* without a detectable table (`CALL`, `SELECT fn(?)`) get the key `query:<sqlhash>:<paramhash>`,
|
|
549
|
+
* and BigInt parameters no longer throw.
|
|
550
|
+
*
|
|
551
|
+
* Keys are built from the table, the WHERE column names and a 32-bit parameter hash; the select
|
|
552
|
+
* list, ORDER BY, LIMIT, literal values and joins are not part of them. Use explicit cache names
|
|
553
|
+
* for queries that differ only in those, and for anything user-specific or sensitive.
|
|
461
554
|
*
|
|
462
|
-
* @param config - Auto key configuration
|
|
555
|
+
* @param config - Auto key configuration, or `true`/`false`
|
|
463
556
|
*
|
|
464
557
|
* @example
|
|
465
558
|
* ```typescript
|
|
@@ -469,35 +562,41 @@ declare module 'sqlcache' {
|
|
|
469
562
|
* const users = await getCacheQuery('SELECT * FROM users WHERE id = ?', [123]);
|
|
470
563
|
* ```
|
|
471
564
|
*/
|
|
472
|
-
export function enableAutoKey(config?: AutoKeyConfig): void;
|
|
565
|
+
export function enableAutoKey(config?: AutoKeyConfig | boolean): void;
|
|
473
566
|
|
|
474
567
|
/**
|
|
475
568
|
* Enables auto cache invalidation feature.
|
|
476
|
-
* When enabled,
|
|
569
|
+
* When enabled, writes without a resetCacheName (QuaryCache, tx.query and, since v2.9.1,
|
|
570
|
+
* bulkInsert) clear the `<table>_*` and `<table>:*` keys of the table they write to. Same as
|
|
571
|
+
* CORE_AUTO_INVALIDATION=true; CORE_AUTO_FEATURES does not enable it.
|
|
477
572
|
*
|
|
478
|
-
*
|
|
573
|
+
* **v2.9.1:** `enableAutoInvalidation(false)` disables the feature (before 2.9.1 it enabled it).
|
|
574
|
+
*
|
|
575
|
+
* @param config - Auto invalidation configuration, or `true`/`false`
|
|
479
576
|
*
|
|
480
577
|
* @example
|
|
481
578
|
* ```typescript
|
|
482
579
|
* enableAutoInvalidation({
|
|
483
580
|
* enabled: true,
|
|
484
581
|
* tables: {
|
|
485
|
-
* users: ['users_*', 'profiles_*'],
|
|
486
|
-
* orders: ['orders_*']
|
|
582
|
+
* users: ['users:*', 'users_*', 'profiles_*'],
|
|
583
|
+
* orders: ['orders:*', 'orders_*']
|
|
487
584
|
* }
|
|
488
585
|
* });
|
|
489
586
|
*
|
|
490
587
|
* // Now resetCacheName is optional
|
|
491
588
|
* await QuaryCache('INSERT INTO users...', [data]);
|
|
492
|
-
* // Auto-clears: users_*, profiles_*
|
|
589
|
+
* // Auto-clears: users:*, users_*, profiles_*
|
|
493
590
|
* ```
|
|
494
591
|
*/
|
|
495
|
-
export function enableAutoInvalidation(config?: AutoInvalidationConfig): void;
|
|
592
|
+
export function enableAutoInvalidation(config?: AutoInvalidationConfig | boolean): void;
|
|
496
593
|
|
|
497
594
|
/**
|
|
498
595
|
* All-in-one configuration helper for v2.6.0 features.
|
|
596
|
+
* Each option is passed to enableAutoKey() / enableAutoInvalidation(); since v2.9.1 `false`
|
|
597
|
+
* disables the feature (e.g. `configure({ autoKey: false })`).
|
|
499
598
|
*
|
|
500
|
-
* @param config -
|
|
599
|
+
* @param config - Configuration object
|
|
501
600
|
*
|
|
502
601
|
* @example
|
|
503
602
|
* ```typescript
|
|
@@ -506,15 +605,15 @@ declare module 'sqlcache' {
|
|
|
506
605
|
* autoInvalidation: {
|
|
507
606
|
* enabled: true,
|
|
508
607
|
* tables: {
|
|
509
|
-
* users: ['users_*', 'profiles_*']
|
|
608
|
+
* users: ['users:*', 'users_*', 'profiles_*']
|
|
510
609
|
* }
|
|
511
610
|
* }
|
|
512
611
|
* });
|
|
513
612
|
* ```
|
|
514
613
|
*/
|
|
515
|
-
export function configure(config?:
|
|
614
|
+
export function configure(config?: ConfigureOptions): void;
|
|
516
615
|
|
|
517
|
-
// ==================== TRANSACTION SUPPORT (v2.
|
|
616
|
+
// ==================== TRANSACTION SUPPORT (v2.6.0+) ====================
|
|
518
617
|
|
|
519
618
|
/**
|
|
520
619
|
* Transaction context object provided to transaction callback.
|
|
@@ -526,7 +625,7 @@ declare module 'sqlcache' {
|
|
|
526
625
|
* Cache invalidation is buffered and applied only on successful commit.
|
|
527
626
|
*
|
|
528
627
|
* @param sql - SQL query to execute
|
|
529
|
-
* @param parameters - Query parameters
|
|
628
|
+
* @param parameters - Query parameters (optional)
|
|
530
629
|
* @param resetCacheName - Optional cache patterns to invalidate on commit
|
|
531
630
|
* @returns Promise resolving to query result
|
|
532
631
|
*
|
|
@@ -538,16 +637,20 @@ declare module 'sqlcache' {
|
|
|
538
637
|
*/
|
|
539
638
|
query<T = any>(
|
|
540
639
|
sql: string,
|
|
541
|
-
parameters
|
|
640
|
+
parameters?: any[],
|
|
542
641
|
resetCacheName?: string | string[] | null
|
|
543
642
|
): Promise<T>;
|
|
544
643
|
|
|
545
644
|
/**
|
|
546
645
|
* Executes a cached read query within the transaction.
|
|
547
|
-
* Note: Reads from cache
|
|
646
|
+
* Note: Reads from cache first, so a cache hit doesn't reflect the transaction's own changes;
|
|
647
|
+
* use query() for reads that decide a write (e.g. `SELECT ... FOR UPDATE`).
|
|
648
|
+
*
|
|
649
|
+
* **v2.9.1:** rows read on a cache miss are written to the cache only after the transaction
|
|
650
|
+
* commits; nothing is cached from a rolled-back transaction (2.9.0 cached them immediately).
|
|
548
651
|
*
|
|
549
652
|
* @param sql - SQL query to execute
|
|
550
|
-
* @param parameters - Query parameters
|
|
653
|
+
* @param parameters - Query parameters (optional)
|
|
551
654
|
* @param cacheName - Cache key (optional if auto-key enabled)
|
|
552
655
|
* @returns Promise resolving to query results
|
|
553
656
|
*
|
|
@@ -558,7 +661,7 @@ declare module 'sqlcache' {
|
|
|
558
661
|
*/
|
|
559
662
|
getCacheQuery<T = any>(
|
|
560
663
|
sql: string,
|
|
561
|
-
parameters
|
|
664
|
+
parameters?: any[],
|
|
562
665
|
cacheName?: string | null
|
|
563
666
|
): Promise<T[]>;
|
|
564
667
|
|
|
@@ -584,7 +687,7 @@ declare module 'sqlcache' {
|
|
|
584
687
|
* Automatically commits on success or rolls back on error.
|
|
585
688
|
* Cache invalidation is buffered and applied only on successful commit.
|
|
586
689
|
*
|
|
587
|
-
* @param callback -
|
|
690
|
+
* @param callback - Function (usually async) that receives transaction context
|
|
588
691
|
* @param options - Transaction options
|
|
589
692
|
* @returns Promise resolving to callback return value
|
|
590
693
|
* @throws Error if transaction fails or is rolled back
|
|
@@ -622,14 +725,20 @@ declare module 'sqlcache' {
|
|
|
622
725
|
* ```
|
|
623
726
|
*/
|
|
624
727
|
export function withTransaction<T = any>(
|
|
625
|
-
callback: (tx: TransactionContext) => Promise<T>,
|
|
728
|
+
callback: (tx: TransactionContext) => T | Promise<T>,
|
|
626
729
|
options?: TransactionOptions
|
|
627
730
|
): Promise<T>;
|
|
628
731
|
|
|
629
732
|
// ==================== BACKWARD COMPATIBILITY ====================
|
|
630
733
|
|
|
631
734
|
/**
|
|
632
|
-
* Default export for backward compatibility with v2.4.x
|
|
735
|
+
* Default export for backward compatibility with v2.4.x.
|
|
736
|
+
*
|
|
737
|
+
* Since v2.9.1 the CommonJS module also has a non-enumerable `default` property, so
|
|
738
|
+
* `import sqlcache from 'sqlcache'` works without `esModuleInterop`; with 2.9.0 and earlier it
|
|
739
|
+
* needs `esModuleInterop` (or use `import sqlcache = require('sqlcache')`). Since v2.9.1 named
|
|
740
|
+
* imports also work in native ESM; with 2.9.0 and earlier, native ESM code should use the
|
|
741
|
+
* default import.
|
|
633
742
|
*
|
|
634
743
|
* @example
|
|
635
744
|
* ```typescript
|
|
@@ -640,6 +749,10 @@ declare module 'sqlcache' {
|
|
|
640
749
|
* // v2.5.0 style (recommended)
|
|
641
750
|
* import { QuaryCache, getCacheQuery } from 'sqlcache';
|
|
642
751
|
* QuaryCache(...);
|
|
752
|
+
*
|
|
753
|
+
* // Default import
|
|
754
|
+
* import sqlcache from 'sqlcache';
|
|
755
|
+
* sqlcache.getCacheQuery(...);
|
|
643
756
|
* ```
|
|
644
757
|
*/
|
|
645
758
|
const connector: {
|
package/index.js
CHANGED
|
@@ -3,40 +3,67 @@ const redisConnector = require('./redis.Connector');
|
|
|
3
3
|
const { enableAutoKey } = require('./core/autoKey');
|
|
4
4
|
const { enableAutoInvalidation } = require('./core/autoInvalidate');
|
|
5
5
|
|
|
6
|
+
// Exported below as shorthand properties, which lets Node detect every name for ES module
|
|
7
|
+
// named imports (import { getCacheQuery } from 'sqlcache')
|
|
8
|
+
const {
|
|
9
|
+
QuaryCache,
|
|
10
|
+
getCacheQuery,
|
|
11
|
+
getCacheQueryPagination,
|
|
12
|
+
bulkInsert,
|
|
13
|
+
getCacheQueryWithTimeout,
|
|
14
|
+
closeConnections,
|
|
15
|
+
getPoolStats,
|
|
16
|
+
withTransaction
|
|
17
|
+
} = dbConnector;
|
|
18
|
+
const {
|
|
19
|
+
getArrayItem,
|
|
20
|
+
addArrayItem,
|
|
21
|
+
delKeyItem,
|
|
22
|
+
delPrefixKeyItem,
|
|
23
|
+
isRedisConnected,
|
|
24
|
+
getRedisClient
|
|
25
|
+
} = redisConnector;
|
|
26
|
+
|
|
27
|
+
// All-in-one configuration helper
|
|
28
|
+
function configure(config = {}) {
|
|
29
|
+
if (config.autoKey !== undefined) {
|
|
30
|
+
enableAutoKey(config.autoKey);
|
|
31
|
+
}
|
|
32
|
+
if (config.autoInvalidation !== undefined) {
|
|
33
|
+
enableAutoInvalidation(config.autoInvalidation);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
6
37
|
module.exports = {
|
|
7
38
|
// Database functions
|
|
8
|
-
QuaryCache
|
|
9
|
-
getCacheQuery
|
|
10
|
-
getCacheQueryPagination
|
|
39
|
+
QuaryCache,
|
|
40
|
+
getCacheQuery,
|
|
41
|
+
getCacheQueryPagination,
|
|
11
42
|
|
|
12
43
|
// Production-grade features (v2.5.3+)
|
|
13
|
-
bulkInsert
|
|
14
|
-
getCacheQueryWithTimeout
|
|
15
|
-
closeConnections
|
|
16
|
-
getPoolStats
|
|
44
|
+
bulkInsert,
|
|
45
|
+
getCacheQueryWithTimeout,
|
|
46
|
+
closeConnections,
|
|
47
|
+
getPoolStats,
|
|
17
48
|
|
|
18
49
|
// Transaction support (v2.7.0+)
|
|
19
|
-
withTransaction
|
|
50
|
+
withTransaction,
|
|
20
51
|
|
|
21
52
|
// Redis functions
|
|
22
|
-
getArrayItem
|
|
23
|
-
addArrayItem
|
|
24
|
-
delKeyItem
|
|
25
|
-
delPrefixKeyItem
|
|
26
|
-
isRedisConnected
|
|
27
|
-
getRedisClient
|
|
53
|
+
getArrayItem,
|
|
54
|
+
addArrayItem,
|
|
55
|
+
delKeyItem,
|
|
56
|
+
delPrefixKeyItem,
|
|
57
|
+
isRedisConnected,
|
|
58
|
+
getRedisClient,
|
|
28
59
|
|
|
29
60
|
// v2.6.0 Core Features (Opt-in)
|
|
30
61
|
enableAutoKey,
|
|
31
62
|
enableAutoInvalidation,
|
|
32
63
|
|
|
33
64
|
// All-in-one configuration helper
|
|
34
|
-
configure
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
enableAutoInvalidation(config.autoInvalidation);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
};
|
|
65
|
+
configure
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// import sqlcache from 'sqlcache' and require('sqlcache').default give the same object
|
|
69
|
+
Object.defineProperty(module.exports, 'default', { value: module.exports, enumerable: false });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sqlcache",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.1",
|
|
4
4
|
"description": "Read-through Redis caching for MySQL: invalidation, pagination, transactions, resilience, TypeScript (formerly node-caching-mysql-connector-with-redis)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -24,9 +24,11 @@
|
|
|
24
24
|
"auto-key",
|
|
25
25
|
"auto-invalidation",
|
|
26
26
|
"smart-cache",
|
|
27
|
-
"zero-config",
|
|
28
27
|
"transaction",
|
|
29
|
-
"
|
|
28
|
+
"read-through",
|
|
29
|
+
"cache-invalidation",
|
|
30
|
+
"redis-cache",
|
|
31
|
+
"mysql-cache"
|
|
30
32
|
],
|
|
31
33
|
"repository": {
|
|
32
34
|
"type": "git",
|
|
@@ -48,16 +50,20 @@
|
|
|
48
50
|
],
|
|
49
51
|
"dependencies": {
|
|
50
52
|
"dotenv": "^16.0.3",
|
|
51
|
-
"mysql2": "^3.
|
|
53
|
+
"mysql2": "^3.23.1",
|
|
52
54
|
"redis": "^3.1.2"
|
|
53
55
|
},
|
|
54
56
|
"devDependencies": {
|
|
57
|
+
"@types/node": "^22.20.5",
|
|
55
58
|
"chai": "^4.3.6",
|
|
56
59
|
"chai-http": "^4.3.0",
|
|
57
|
-
"mocha": "^
|
|
60
|
+
"mocha": "^10.8.2",
|
|
58
61
|
"nyc": "^17.1.0",
|
|
59
62
|
"proxyquire": "^2.1.3",
|
|
60
63
|
"sinon": "^17.0.1",
|
|
61
64
|
"sinon-chai": "^3.7.0"
|
|
65
|
+
},
|
|
66
|
+
"engines": {
|
|
67
|
+
"node": ">=14"
|
|
62
68
|
}
|
|
63
69
|
}
|