Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
f113ffc
Update README.md
Mikhus Mar 19, 2020
82b24cc
Merge branch 'master' of github.com:imqueue/pg-cache
Mikhus Mar 19, 2020
d14c127
fix: passig args to filter, +docs update
Mikhus Mar 19, 2020
1a9dc91
1.3.0
Mikhus Mar 19, 2020
a2e521e
feat: implemented possibility to publish db channel events to clients…
Mikhus Mar 19, 2020
bc40609
1.3.1
Mikhus Mar 19, 2020
b1aa469
feat: publish tag info
Mikhus Mar 19, 2020
cad510a
1.3.2
Mikhus Mar 19, 2020
cc0f8e7
fix: deps updated
Mikhus Mar 20, 2020
b91de48
1.3.3
Mikhus Mar 20, 2020
f353c53
fix: deps updated
Mikhus Mar 20, 2020
b13fb59
1.3.4
Mikhus Mar 20, 2020
91220e5
fix: deps up
Mikhus Mar 20, 2020
885adde
1.3.5
Mikhus Mar 20, 2020
625db28
fix: deps update
Mikhus Mar 20, 2020
76e2813
1.3.6
Mikhus Mar 20, 2020
e60e870
feat: debug options added; +ability to override trigger sql function
Mikhus Mar 20, 2020
1c7a6df
1.4.0
Mikhus Mar 20, 2020
a2231c0
fix: install triggers
Mikhus Mar 20, 2020
2cde1f8
1.4.1-0
Mikhus Mar 20, 2020
7335834
1.4.1
Mikhus Mar 20, 2020
c460671
fix: trigger creation
Mikhus Mar 20, 2020
f453b2e
1.4.2-0
Mikhus Mar 20, 2020
2c19c26
1.4.2
Mikhus Mar 20, 2020
9ecf6c0
fix: trigger creation
Mikhus Mar 20, 2020
52a765c
1.4.3
Mikhus Mar 20, 2020
995b6d8
fix: trigger creation
Mikhus Mar 20, 2020
1c0eddd
1.4.4
Mikhus Mar 20, 2020
86421a2
fix: auto-publish service events by default
Mikhus Mar 20, 2020
eb23dba
1.5.0
Mikhus Mar 20, 2020
ecf936f
fix: max listeners warn fixed
Mikhus Mar 20, 2020
5b13106
1.5.1
Mikhus Mar 20, 2020
d58d663
fix: proper tag cache version with fixed invalidation
Mikhus Mar 20, 2020
3b41527
1.5.2
Mikhus Mar 20, 2020
f167153
feat: cacheBy implemented; +refactoring
Mikhus Mar 22, 2020
002400a
docs update and minor fixes
Mikhus Mar 22, 2020
ae30773
Merge pull request #1 from imqueue/v2.0.0-dev
Mikhus Mar 22, 2020
11c7562
chore: deps update
Mikhus Mar 22, 2020
ff0ab7a
2.0.0
Mikhus Mar 22, 2020
50afc5b
fix: exports
Mikhus Mar 22, 2020
326eb5c
2.0.1
Mikhus Mar 22, 2020
e477356
fix: if no prevent error on start if no channels set for caching
Mikhus Mar 22, 2020
76136c4
2.0.2
Mikhus Mar 22, 2020
05e6499
fix: update outdated deps
Mikhus Nov 27, 2020
4948597
2.1.0
Mikhus Nov 27, 2020
5295bbc
fix: deps update
Mikhus Nov 30, 2020
0bab44b
2.1.1-0
Mikhus Nov 30, 2020
5faa740
2.1.1
Mikhus Nov 30, 2020
4a2e49e
fix: deps updated
Mikhus May 28, 2021
f580763
2.1.2
Mikhus May 28, 2021
0b38f12
fix: deps up
Mikhus Nov 1, 2021
791366e
2.1.3
Mikhus Nov 1, 2021
7369c1f
chore: build up
Mikhus Nov 1, 2021
d1bb1d6
2.1.4
Mikhus Nov 1, 2021
f584ba3
fix: compatibility to new js versions & tag key hashing
Mar 22, 2022
39e4f7c
fix: deps up
Mikhus Mar 22, 2022
0b54545
2.1.5
Mikhus Mar 22, 2022
5970bc3
fix: deps up
Mikhus Mar 22, 2022
168b0cc
2.1.6
Mikhus Mar 22, 2022
1480e86
fix: install
Mar 22, 2022
125761a
Merge branch 'master' into fix-invalidating-on-change
Mar 22, 2022
4f862e7
Merge pull request #14 from imqueue/fix-invalidating-on-change
SerhiyGreench Mar 22, 2022
8214b7f
2.1.7
Mikhus Mar 22, 2022
106fa4a
fix: removed creating PubSub instance in class properties
Mar 31, 2022
f72e308
2.1.8
Mikhus Mar 31, 2022
ab05c6b
fix: deps updated
Mikhus Apr 1, 2022
3416cdf
2.1.9
Mikhus Apr 1, 2022
2a025a4
fix: deps updated
Mikhus Apr 28, 2022
dade8dc
2.1.10
Mikhus Apr 28, 2022
51f72a8
fix: deps up
Mikhus Apr 28, 2022
5c742ea
2.1.11
Mikhus Apr 28, 2022
d901663
fix: deps updated
Mikhus Apr 29, 2022
056e6bb
2.1.12
Mikhus Apr 29, 2022
d5346c6
fix: deps up
Mikhus May 3, 2022
d18481c
2.1.13
Mikhus May 3, 2022
1e93ce9
fix: deps updated
Mikhus May 10, 2022
2e50e6b
2.2.0
Mikhus May 10, 2022
543de56
chore(deps): bump json5 from 2.2.1 to 2.2.3
dependabot[bot] Jan 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .eslintrc.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -88,8 +88,7 @@
"string",
"Boolean",
"boolean",
"Undefined",
"undefined"
"Undefined"
],
"id-match": "error",
"max-classes-per-file": "off",
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
dist: xenial
dist: focal
language: node_js
env:
global:
Expand Down
123 changes: 123 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,129 @@ Links `@imqueue/pg-pubsub` with `@imqueue/tag-cache` and provides generic
way to implement intellectual cache management based on database changes
notifications for @imqueue-based service methods.

## Usage

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheWith } from '@imqueue/pg-cache';
import { MyDbEntity } from './orm/models';

@PgCache({
postgres: 'postgres://localhost:5432/db-name',
redis: { host: 'localhost', port: 6379 },
prefix: 'my-cool-service', // optional, if not passed will use class name as prefix
})
class MyCoolService extends IMQService {
@expose()
@cacheWith({ channels: [MyDbEnity.tableName] })
public async listEntities(): Promise<MyDbEntity> {
return await MyDbEntity.findAll();
}
}
~~~

With the setup, described above first call to `MyCoolService.listEntities()`
will save method return value to cache and each next call will return cached
value, stored in redis instead of making database query.
Each function call is signed by a call signature, so if your method accepts
arguments which influence database query execution caching is made for each
unique method call. Cached result will be automatically invalidated each time
each table described in channels will trigger `INSERT`, `UPDATE` or `DELETE`. Or
when TTL on a cache entity expires. By default TTL is 24 hours. If you want
different TTL to be used, do it as:

~~~typescript
@cacheWith({ channels: [MyDbEnity.tableName], ttl: 5 * 60 * 1000 })
~~~

In this example TTL is set to 5 minutes. TTL should be provided in milliseconds.

### Using @cacheBy

Since v2.0.0 @cacheBy decorator introduced and helps simplify caching
invalidation definition for those service methods which rely on a root sequelize
model output. In combination of passing the fields map to such service methods
it will also provide more efficient caching for the method calls.

Take a look at such example:

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheBy } from '@imqueue/pg-cache';
import {
FieldsInput,
FindOptions,
OrderByInput,
PaginationInput,
query,
} from '@imqueue/sequelize';
import { cacheConfig } from '../config';
import { MyDbEntity } from './orm/models';
import { MyDbEntityFilter } from './types';
import withRangeFilters = query.withRangeFilters;
import autoCountQuery = query.autoCountQuery;
import autoQuery = query.autoQuery;
import toWhereOptions = query.toWhereOptions;
import toLimitOptions = query.toLimitOptions;
import toOrderOptions = query.toOrderOptions;

@PgCache(cacheConfig)
class MyCoolService extends IMQService {
@expose()
@cacheBy(MyDbEntity, { fieldsArg: 1 })
public async listEntities(
filter?: MyDbEntityFilter,
fields?: FieldsInput,
pageOptions?: PaginationInput,
orderBy?: OrderByInput,
): Promise<{ total: number, data: MyDbEntity[] }> {
const where = toWhereOptions<MyDbEntityFilter>(
withRangeFilters(filter),
MyDbEntityFilter,
);
const countQuery = autoCountQuery(MyDbEntity, fields, where);
const findQuery = autoQuery<FindOptions>(
MyDbEntity, fields, where,
toLimitOptions<MyDbEntity>(pageOptions),
toOrderOptions(orderBy),
);
const [total, data] = await Promise.all([
MyDbEntity.count(countQuery),
MyDbEntity.findAll(findQuery),
]);

return { total, data } as { total: number, data: MyDbEntity[] };
}
}
~~~

By doing so, `@cacheBy` will take care of invalidating only those queries
which has selection of fields matching db changes events, so if the actual
query was not selecting some joined data, but there was a change only on that
joined data - cache won't invalidate, as far as real selection was not
influenced by a data change. And yes, it will automatically monitor
all related to the root model entities for changes and match them with runtime
selections. This makes caching more efficient and more obvious for
developer.

### Extended channels API

~~~typescript
import { cacheWith, ChannelOperation, ChannelPayload } from '@imqueue/pg-cache';

// using simple filtering by operation
@cacheWith({ channels: {
[MyDbEnity.tableName]: [ChannelOperation.UPDATE, ChannelOperation.INSERT]
}})

// or by using custom filtering function
@cacheWith({ channels: {
[MyDbEnity.tableName]: (
payload: ChannelPayload, // payload caught from db event
) => payload.operation === ChannelOperation.DELETE,
}})
~~~

## Contributing

Any contributions are greatly appreciated. Feel free to fork, propose PRs, open
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
f113ffc
Update README.md
Mikhus Mar 19, 2020
82b24cc
Merge branch 'master' of github.com:imqueue/pg-cache
Mikhus Mar 19, 2020
d14c127
fix: passig args to filter, +docs update
Mikhus Mar 19, 2020
1a9dc91
1.3.0
Mikhus Mar 19, 2020
a2e521e
feat: implemented possibility to publish db channel events to clients…
Mikhus Mar 19, 2020
bc40609
1.3.1
Mikhus Mar 19, 2020
b1aa469
feat: publish tag info
Mikhus Mar 19, 2020
cad510a
1.3.2
Mikhus Mar 19, 2020
cc0f8e7
fix: deps updated
Mikhus Mar 20, 2020
b91de48
1.3.3
Mikhus Mar 20, 2020
f353c53
fix: deps updated
Mikhus Mar 20, 2020
b13fb59
1.3.4
Mikhus Mar 20, 2020
91220e5
fix: deps up
Mikhus Mar 20, 2020
885adde
1.3.5
Mikhus Mar 20, 2020
625db28
fix: deps update
Mikhus Mar 20, 2020
76e2813
1.3.6
Mikhus Mar 20, 2020
e60e870
feat: debug options added; +ability to override trigger sql function
Mikhus Mar 20, 2020
1c7a6df
1.4.0
Mikhus Mar 20, 2020
a2231c0
fix: install triggers
Mikhus Mar 20, 2020
2cde1f8
1.4.1-0
Mikhus Mar 20, 2020
7335834
1.4.1
Mikhus Mar 20, 2020
c460671
fix: trigger creation
Mikhus Mar 20, 2020
f453b2e
1.4.2-0
Mikhus Mar 20, 2020
2c19c26
1.4.2
Mikhus Mar 20, 2020
9ecf6c0
fix: trigger creation
Mikhus Mar 20, 2020
52a765c
1.4.3
Mikhus Mar 20, 2020
995b6d8
fix: trigger creation
Mikhus Mar 20, 2020
1c0eddd
1.4.4
Mikhus Mar 20, 2020
86421a2
fix: auto-publish service events by default
Mikhus Mar 20, 2020
eb23dba
1.5.0
Mikhus Mar 20, 2020
ecf936f
fix: max listeners warn fixed
Mikhus Mar 20, 2020
5b13106
1.5.1
Mikhus Mar 20, 2020
d58d663
fix: proper tag cache version with fixed invalidation
Mikhus Mar 20, 2020
3b41527
1.5.2
Mikhus Mar 20, 2020
f167153
feat: cacheBy implemented; +refactoring
Mikhus Mar 22, 2020
002400a
docs update and minor fixes
Mikhus Mar 22, 2020
ae30773
Merge pull request #1 from imqueue/v2.0.0-dev
Mikhus Mar 22, 2020
11c7562
chore: deps update
Mikhus Mar 22, 2020
ff0ab7a
2.0.0
Mikhus Mar 22, 2020
50afc5b
fix: exports
Mikhus Mar 22, 2020
326eb5c
2.0.1
Mikhus Mar 22, 2020
e477356
fix: if no prevent error on start if no channels set for caching
Mikhus Mar 22, 2020
76136c4
2.0.2
Mikhus Mar 22, 2020
05e6499
fix: update outdated deps
Mikhus Nov 27, 2020
4948597
2.1.0
Mikhus Nov 27, 2020
5295bbc
fix: deps update
Mikhus Nov 30, 2020
0bab44b
2.1.1-0
Mikhus Nov 30, 2020
5faa740
2.1.1
Mikhus Nov 30, 2020
4a2e49e
fix: deps updated
Mikhus May 28, 2021
f580763
2.1.2
Mikhus May 28, 2021
0b38f12
fix: deps up
Mikhus Nov 1, 2021
791366e
2.1.3
Mikhus Nov 1, 2021
7369c1f
chore: build up
Mikhus Nov 1, 2021
d1bb1d6
2.1.4
Mikhus Nov 1, 2021
f584ba3
fix: compatibility to new js versions & tag key hashing
Mar 22, 2022
39e4f7c
fix: deps up
Mikhus Mar 22, 2022
0b54545
2.1.5
Mikhus Mar 22, 2022
5970bc3
fix: deps up
Mikhus Mar 22, 2022
168b0cc
2.1.6
Mikhus Mar 22, 2022
1480e86
fix: install
Mar 22, 2022
125761a
Merge branch 'master' into fix-invalidating-on-change
Mar 22, 2022
4f862e7
Merge pull request #14 from imqueue/fix-invalidating-on-change
SerhiyGreench Mar 22, 2022
8214b7f
2.1.7
Mikhus Mar 22, 2022
106fa4a
fix: removed creating PubSub instance in class properties
Mar 31, 2022
f72e308
2.1.8
Mikhus Mar 31, 2022
ab05c6b
fix: deps updated
Mikhus Apr 1, 2022
3416cdf
2.1.9
Mikhus Apr 1, 2022
2a025a4
fix: deps updated
Mikhus Apr 28, 2022
dade8dc
2.1.10
Mikhus Apr 28, 2022
51f72a8
fix: deps up
Mikhus Apr 28, 2022
5c742ea
2.1.11
Mikhus Apr 28, 2022
d901663
fix: deps updated
Mikhus Apr 29, 2022
056e6bb
2.1.12
Mikhus Apr 29, 2022
d5346c6
fix: deps up
Mikhus May 3, 2022
d18481c
2.1.13
Mikhus May 3, 2022
1e93ce9
fix: deps updated
Mikhus May 10, 2022
2e50e6b
2.2.0
Mikhus May 10, 2022
543de56
chore(deps): bump json5 from 2.2.1 to 2.2.3
dependabot[bot] Jan 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .eslintrc.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -88,8 +88,7 @@
"string",
"Boolean",
"boolean",
"Undefined",
"undefined"
"Undefined"
],
"id-match": "error",
"max-classes-per-file": "off",
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
dist: xenial
dist: focal
language: node_js
env:
global:
Expand Down
123 changes: 123 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,129 @@ Links `@imqueue/pg-pubsub` with `@imqueue/tag-cache` and provides generic
way to implement intellectual cache management based on database changes
notifications for @imqueue-based service methods.

## Usage

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheWith } from '@imqueue/pg-cache';
import { MyDbEntity } from './orm/models';

@PgCache({
postgres: 'postgres://localhost:5432/db-name',
redis: { host: 'localhost', port: 6379 },
prefix: 'my-cool-service', // optional, if not passed will use class name as prefix
})
class MyCoolService extends IMQService {
@expose()
@cacheWith({ channels: [MyDbEnity.tableName] })
public async listEntities(): Promise<MyDbEntity> {
return await MyDbEntity.findAll();
}
}
~~~

With the setup, described above first call to `MyCoolService.listEntities()`
will save method return value to cache and each next call will return cached
value, stored in redis instead of making database query.
Each function call is signed by a call signature, so if your method accepts
arguments which influence database query execution caching is made for each
unique method call. Cached result will be automatically invalidated each time
each table described in channels will trigger `INSERT`, `UPDATE` or `DELETE`. Or
when TTL on a cache entity expires. By default TTL is 24 hours. If you want
different TTL to be used, do it as:

~~~typescript
@cacheWith({ channels: [MyDbEnity.tableName], ttl: 5 * 60 * 1000 })
~~~

In this example TTL is set to 5 minutes. TTL should be provided in milliseconds.

### Using @cacheBy

Since v2.0.0 @cacheBy decorator introduced and helps simplify caching
invalidation definition for those service methods which rely on a root sequelize
model output. In combination of passing the fields map to such service methods
it will also provide more efficient caching for the method calls.

Take a look at such example:

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheBy } from '@imqueue/pg-cache';
import {
FieldsInput,
FindOptions,
OrderByInput,
PaginationInput,
query,
} from '@imqueue/sequelize';
import { cacheConfig } from '../config';
import { MyDbEntity } from './orm/models';
import { MyDbEntityFilter } from './types';
import withRangeFilters = query.withRangeFilters;
import autoCountQuery = query.autoCountQuery;
import autoQuery = query.autoQuery;
import toWhereOptions = query.toWhereOptions;
import toLimitOptions = query.toLimitOptions;
import toOrderOptions = query.toOrderOptions;

@PgCache(cacheConfig)
class MyCoolService extends IMQService {
@expose()
@cacheBy(MyDbEntity, { fieldsArg: 1 })
public async listEntities(
filter?: MyDbEntityFilter,
fields?: FieldsInput,
pageOptions?: PaginationInput,
orderBy?: OrderByInput,
): Promise<{ total: number, data: MyDbEntity[] }> {
const where = toWhereOptions<MyDbEntityFilter>(
withRangeFilters(filter),
MyDbEntityFilter,
);
const countQuery = autoCountQuery(MyDbEntity, fields, where);
const findQuery = autoQuery<FindOptions>(
MyDbEntity, fields, where,
toLimitOptions<MyDbEntity>(pageOptions),
toOrderOptions(orderBy),
);
const [total, data] = await Promise.all([
MyDbEntity.count(countQuery),
MyDbEntity.findAll(findQuery),
]);

return { total, data } as { total: number, data: MyDbEntity[] };
}
}
~~~

By doing so, `@cacheBy` will take care of invalidating only those queries
which has selection of fields matching db changes events, so if the actual
query was not selecting some joined data, but there was a change only on that
joined data - cache won't invalidate, as far as real selection was not
influenced by a data change. And yes, it will automatically monitor
all related to the root model entities for changes and match them with runtime
selections. This makes caching more efficient and more obvious for
developer.

### Extended channels API

~~~typescript
import { cacheWith, ChannelOperation, ChannelPayload } from '@imqueue/pg-cache';

// using simple filtering by operation
@cacheWith({ channels: {
[MyDbEnity.tableName]: [ChannelOperation.UPDATE, ChannelOperation.INSERT]
}})

// or by using custom filtering function
@cacheWith({ channels: {
[MyDbEnity.tableName]: (
payload: ChannelPayload, // payload caught from db event
) => payload.operation === ChannelOperation.DELETE,
}})
~~~

## Contributing

Any contributions are greatly appreciated. Feel free to fork, propose PRs, open
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
f113ffc
Update README.md
Mikhus Mar 19, 2020
82b24cc
Merge branch 'master' of github.com:imqueue/pg-cache
Mikhus Mar 19, 2020
d14c127
fix: passig args to filter, +docs update
Mikhus Mar 19, 2020
1a9dc91
1.3.0
Mikhus Mar 19, 2020
a2e521e
feat: implemented possibility to publish db channel events to clients…
Mikhus Mar 19, 2020
bc40609
1.3.1
Mikhus Mar 19, 2020
b1aa469
feat: publish tag info
Mikhus Mar 19, 2020
cad510a
1.3.2
Mikhus Mar 19, 2020
cc0f8e7
fix: deps updated
Mikhus Mar 20, 2020
b91de48
1.3.3
Mikhus Mar 20, 2020
f353c53
fix: deps updated
Mikhus Mar 20, 2020
b13fb59
1.3.4
Mikhus Mar 20, 2020
91220e5
fix: deps up
Mikhus Mar 20, 2020
885adde
1.3.5
Mikhus Mar 20, 2020
625db28
fix: deps update
Mikhus Mar 20, 2020
76e2813
1.3.6
Mikhus Mar 20, 2020
e60e870
feat: debug options added; +ability to override trigger sql function
Mikhus Mar 20, 2020
1c7a6df
1.4.0
Mikhus Mar 20, 2020
a2231c0
fix: install triggers
Mikhus Mar 20, 2020
2cde1f8
1.4.1-0
Mikhus Mar 20, 2020
7335834
1.4.1
Mikhus Mar 20, 2020
c460671
fix: trigger creation
Mikhus Mar 20, 2020
f453b2e
1.4.2-0
Mikhus Mar 20, 2020
2c19c26
1.4.2
Mikhus Mar 20, 2020
9ecf6c0
fix: trigger creation
Mikhus Mar 20, 2020
52a765c
1.4.3
Mikhus Mar 20, 2020
995b6d8
fix: trigger creation
Mikhus Mar 20, 2020
1c0eddd
1.4.4
Mikhus Mar 20, 2020
86421a2
fix: auto-publish service events by default
Mikhus Mar 20, 2020
eb23dba
1.5.0
Mikhus Mar 20, 2020
ecf936f
fix: max listeners warn fixed
Mikhus Mar 20, 2020
5b13106
1.5.1
Mikhus Mar 20, 2020
d58d663
fix: proper tag cache version with fixed invalidation
Mikhus Mar 20, 2020
3b41527
1.5.2
Mikhus Mar 20, 2020
f167153
feat: cacheBy implemented; +refactoring
Mikhus Mar 22, 2020
002400a
docs update and minor fixes
Mikhus Mar 22, 2020
ae30773
Merge pull request #1 from imqueue/v2.0.0-dev
Mikhus Mar 22, 2020
11c7562
chore: deps update
Mikhus Mar 22, 2020
ff0ab7a
2.0.0
Mikhus Mar 22, 2020
50afc5b
fix: exports
Mikhus Mar 22, 2020
326eb5c
2.0.1
Mikhus Mar 22, 2020
e477356
fix: if no prevent error on start if no channels set for caching
Mikhus Mar 22, 2020
76136c4
2.0.2
Mikhus Mar 22, 2020
05e6499
fix: update outdated deps
Mikhus Nov 27, 2020
4948597
2.1.0
Mikhus Nov 27, 2020
5295bbc
fix: deps update
Mikhus Nov 30, 2020
0bab44b
2.1.1-0
Mikhus Nov 30, 2020
5faa740
2.1.1
Mikhus Nov 30, 2020
4a2e49e
fix: deps updated
Mikhus May 28, 2021
f580763
2.1.2
Mikhus May 28, 2021
0b38f12
fix: deps up
Mikhus Nov 1, 2021
791366e
2.1.3
Mikhus Nov 1, 2021
7369c1f
chore: build up
Mikhus Nov 1, 2021
d1bb1d6
2.1.4
Mikhus Nov 1, 2021
f584ba3
fix: compatibility to new js versions & tag key hashing
Mar 22, 2022
39e4f7c
fix: deps up
Mikhus Mar 22, 2022
0b54545
2.1.5
Mikhus Mar 22, 2022
5970bc3
fix: deps up
Mikhus Mar 22, 2022
168b0cc
2.1.6
Mikhus Mar 22, 2022
1480e86
fix: install
Mar 22, 2022
125761a
Merge branch 'master' into fix-invalidating-on-change
Mar 22, 2022
4f862e7
Merge pull request #14 from imqueue/fix-invalidating-on-change
SerhiyGreench Mar 22, 2022
8214b7f
2.1.7
Mikhus Mar 22, 2022
106fa4a
fix: removed creating PubSub instance in class properties
Mar 31, 2022
f72e308
2.1.8
Mikhus Mar 31, 2022
ab05c6b
fix: deps updated
Mikhus Apr 1, 2022
3416cdf
2.1.9
Mikhus Apr 1, 2022
2a025a4
fix: deps updated
Mikhus Apr 28, 2022
dade8dc
2.1.10
Mikhus Apr 28, 2022
51f72a8
fix: deps up
Mikhus Apr 28, 2022
5c742ea
2.1.11
Mikhus Apr 28, 2022
d901663
fix: deps updated
Mikhus Apr 29, 2022
056e6bb
2.1.12
Mikhus Apr 29, 2022
d5346c6
fix: deps up
Mikhus May 3, 2022
d18481c
2.1.13
Mikhus May 3, 2022
1e93ce9
fix: deps updated
Mikhus May 10, 2022
2e50e6b
2.2.0
Mikhus May 10, 2022
543de56
chore(deps): bump json5 from 2.2.1 to 2.2.3
dependabot[bot] Jan 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .eslintrc.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -88,8 +88,7 @@
"string",
"Boolean",
"boolean",
"Undefined",
"undefined"
"Undefined"
],
"id-match": "error",
"max-classes-per-file": "off",
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
dist: xenial
dist: focal
language: node_js
env:
global:
Expand Down
123 changes: 123 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,129 @@ Links `@imqueue/pg-pubsub` with `@imqueue/tag-cache` and provides generic
way to implement intellectual cache management based on database changes
notifications for @imqueue-based service methods.

## Usage

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheWith } from '@imqueue/pg-cache';
import { MyDbEntity } from './orm/models';

@PgCache({
postgres: 'postgres://localhost:5432/db-name',
redis: { host: 'localhost', port: 6379 },
prefix: 'my-cool-service', // optional, if not passed will use class name as prefix
})
class MyCoolService extends IMQService {
@expose()
@cacheWith({ channels: [MyDbEnity.tableName] })
public async listEntities(): Promise<MyDbEntity> {
return await MyDbEntity.findAll();
}
}
~~~

With the setup, described above first call to `MyCoolService.listEntities()`
will save method return value to cache and each next call will return cached
value, stored in redis instead of making database query.
Each function call is signed by a call signature, so if your method accepts
arguments which influence database query execution caching is made for each
unique method call. Cached result will be automatically invalidated each time
each table described in channels will trigger `INSERT`, `UPDATE` or `DELETE`. Or
when TTL on a cache entity expires. By default TTL is 24 hours. If you want
different TTL to be used, do it as:

~~~typescript
@cacheWith({ channels: [MyDbEnity.tableName], ttl: 5 * 60 * 1000 })
~~~

In this example TTL is set to 5 minutes. TTL should be provided in milliseconds.

### Using @cacheBy

Since v2.0.0 @cacheBy decorator introduced and helps simplify caching
invalidation definition for those service methods which rely on a root sequelize
model output. In combination of passing the fields map to such service methods
it will also provide more efficient caching for the method calls.

Take a look at such example:

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheBy } from '@imqueue/pg-cache';
import {
FieldsInput,
FindOptions,
OrderByInput,
PaginationInput,
query,
} from '@imqueue/sequelize';
import { cacheConfig } from '../config';
import { MyDbEntity } from './orm/models';
import { MyDbEntityFilter } from './types';
import withRangeFilters = query.withRangeFilters;
import autoCountQuery = query.autoCountQuery;
import autoQuery = query.autoQuery;
import toWhereOptions = query.toWhereOptions;
import toLimitOptions = query.toLimitOptions;
import toOrderOptions = query.toOrderOptions;

@PgCache(cacheConfig)
class MyCoolService extends IMQService {
@expose()
@cacheBy(MyDbEntity, { fieldsArg: 1 })
public async listEntities(
filter?: MyDbEntityFilter,
fields?: FieldsInput,
pageOptions?: PaginationInput,
orderBy?: OrderByInput,
): Promise<{ total: number, data: MyDbEntity[] }> {
const where = toWhereOptions<MyDbEntityFilter>(
withRangeFilters(filter),
MyDbEntityFilter,
);
const countQuery = autoCountQuery(MyDbEntity, fields, where);
const findQuery = autoQuery<FindOptions>(
MyDbEntity, fields, where,
toLimitOptions<MyDbEntity>(pageOptions),
toOrderOptions(orderBy),
);
const [total, data] = await Promise.all([
MyDbEntity.count(countQuery),
MyDbEntity.findAll(findQuery),
]);

return { total, data } as { total: number, data: MyDbEntity[] };
}
}
~~~

By doing so, `@cacheBy` will take care of invalidating only those queries
which has selection of fields matching db changes events, so if the actual
query was not selecting some joined data, but there was a change only on that
joined data - cache won't invalidate, as far as real selection was not
influenced by a data change. And yes, it will automatically monitor
all related to the root model entities for changes and match them with runtime
selections. This makes caching more efficient and more obvious for
developer.

### Extended channels API

~~~typescript
import { cacheWith, ChannelOperation, ChannelPayload } from '@imqueue/pg-cache';

// using simple filtering by operation
@cacheWith({ channels: {
[MyDbEnity.tableName]: [ChannelOperation.UPDATE, ChannelOperation.INSERT]
}})

// or by using custom filtering function
@cacheWith({ channels: {
[MyDbEnity.tableName]: (
payload: ChannelPayload, // payload caught from db event
) => payload.operation === ChannelOperation.DELETE,
}})
~~~

## Contributing

Any contributions are greatly appreciated. Feel free to fork, propose PRs, open
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
f113ffc
Update README.md
Mikhus Mar 19, 2020
82b24cc
Merge branch 'master' of github.com:imqueue/pg-cache
Mikhus Mar 19, 2020
d14c127
fix: passig args to filter, +docs update
Mikhus Mar 19, 2020
1a9dc91
1.3.0
Mikhus Mar 19, 2020
a2e521e
feat: implemented possibility to publish db channel events to clients…
Mikhus Mar 19, 2020
bc40609
1.3.1
Mikhus Mar 19, 2020
b1aa469
feat: publish tag info
Mikhus Mar 19, 2020
cad510a
1.3.2
Mikhus Mar 19, 2020
cc0f8e7
fix: deps updated
Mikhus Mar 20, 2020
b91de48
1.3.3
Mikhus Mar 20, 2020
f353c53
fix: deps updated
Mikhus Mar 20, 2020
b13fb59
1.3.4
Mikhus Mar 20, 2020
91220e5
fix: deps up
Mikhus Mar 20, 2020
885adde
1.3.5
Mikhus Mar 20, 2020
625db28
fix: deps update
Mikhus Mar 20, 2020
76e2813
1.3.6
Mikhus Mar 20, 2020
e60e870
feat: debug options added; +ability to override trigger sql function
Mikhus Mar 20, 2020
1c7a6df
1.4.0
Mikhus Mar 20, 2020
a2231c0
fix: install triggers
Mikhus Mar 20, 2020
2cde1f8
1.4.1-0
Mikhus Mar 20, 2020
7335834
1.4.1
Mikhus Mar 20, 2020
c460671
fix: trigger creation
Mikhus Mar 20, 2020
f453b2e
1.4.2-0
Mikhus Mar 20, 2020
2c19c26
1.4.2
Mikhus Mar 20, 2020
9ecf6c0
fix: trigger creation
Mikhus Mar 20, 2020
52a765c
1.4.3
Mikhus Mar 20, 2020
995b6d8
fix: trigger creation
Mikhus Mar 20, 2020
1c0eddd
1.4.4
Mikhus Mar 20, 2020
86421a2
fix: auto-publish service events by default
Mikhus Mar 20, 2020
eb23dba
1.5.0
Mikhus Mar 20, 2020
ecf936f
fix: max listeners warn fixed
Mikhus Mar 20, 2020
5b13106
1.5.1
Mikhus Mar 20, 2020
d58d663
fix: proper tag cache version with fixed invalidation
Mikhus Mar 20, 2020
3b41527
1.5.2
Mikhus Mar 20, 2020
f167153
feat: cacheBy implemented; +refactoring
Mikhus Mar 22, 2020
002400a
docs update and minor fixes
Mikhus Mar 22, 2020
ae30773
Merge pull request #1 from imqueue/v2.0.0-dev
Mikhus Mar 22, 2020
11c7562
chore: deps update
Mikhus Mar 22, 2020
ff0ab7a
2.0.0
Mikhus Mar 22, 2020
50afc5b
fix: exports
Mikhus Mar 22, 2020
326eb5c
2.0.1
Mikhus Mar 22, 2020
e477356
fix: if no prevent error on start if no channels set for caching
Mikhus Mar 22, 2020
76136c4
2.0.2
Mikhus Mar 22, 2020
05e6499
fix: update outdated deps
Mikhus Nov 27, 2020
4948597
2.1.0
Mikhus Nov 27, 2020
5295bbc
fix: deps update
Mikhus Nov 30, 2020
0bab44b
2.1.1-0
Mikhus Nov 30, 2020
5faa740
2.1.1
Mikhus Nov 30, 2020
4a2e49e
fix: deps updated
Mikhus May 28, 2021
f580763
2.1.2
Mikhus May 28, 2021
0b38f12
fix: deps up
Mikhus Nov 1, 2021
791366e
2.1.3
Mikhus Nov 1, 2021
7369c1f
chore: build up
Mikhus Nov 1, 2021
d1bb1d6
2.1.4
Mikhus Nov 1, 2021
f584ba3
fix: compatibility to new js versions & tag key hashing
Mar 22, 2022
39e4f7c
fix: deps up
Mikhus Mar 22, 2022
0b54545
2.1.5
Mikhus Mar 22, 2022
5970bc3
fix: deps up
Mikhus Mar 22, 2022
168b0cc
2.1.6
Mikhus Mar 22, 2022
1480e86
fix: install
Mar 22, 2022
125761a
Merge branch 'master' into fix-invalidating-on-change
Mar 22, 2022
4f862e7
Merge pull request #14 from imqueue/fix-invalidating-on-change
SerhiyGreench Mar 22, 2022
8214b7f
2.1.7
Mikhus Mar 22, 2022
106fa4a
fix: removed creating PubSub instance in class properties
Mar 31, 2022
f72e308
2.1.8
Mikhus Mar 31, 2022
ab05c6b
fix: deps updated
Mikhus Apr 1, 2022
3416cdf
2.1.9
Mikhus Apr 1, 2022
2a025a4
fix: deps updated
Mikhus Apr 28, 2022
dade8dc
2.1.10
Mikhus Apr 28, 2022
51f72a8
fix: deps up
Mikhus Apr 28, 2022
5c742ea
2.1.11
Mikhus Apr 28, 2022
d901663
fix: deps updated
Mikhus Apr 29, 2022
056e6bb
2.1.12
Mikhus Apr 29, 2022
d5346c6
fix: deps up
Mikhus May 3, 2022
d18481c
2.1.13
Mikhus May 3, 2022
1e93ce9
fix: deps updated
Mikhus May 10, 2022
2e50e6b
2.2.0
Mikhus May 10, 2022
543de56
chore(deps): bump json5 from 2.2.1 to 2.2.3
dependabot[bot] Jan 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .eslintrc.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -88,8 +88,7 @@
"string",
"Boolean",
"boolean",
"Undefined",
"undefined"
"Undefined"
],
"id-match": "error",
"max-classes-per-file": "off",
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
dist: xenial
dist: focal
language: node_js
env:
global:
Expand Down
123 changes: 123 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,129 @@ Links `@imqueue/pg-pubsub` with `@imqueue/tag-cache` and provides generic
way to implement intellectual cache management based on database changes
notifications for @imqueue-based service methods.

## Usage

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheWith } from '@imqueue/pg-cache';
import { MyDbEntity } from './orm/models';

@PgCache({
postgres: 'postgres://localhost:5432/db-name',
redis: { host: 'localhost', port: 6379 },
prefix: 'my-cool-service', // optional, if not passed will use class name as prefix
})
class MyCoolService extends IMQService {
@expose()
@cacheWith({ channels: [MyDbEnity.tableName] })
public async listEntities(): Promise<MyDbEntity> {
return await MyDbEntity.findAll();
}
}
~~~

With the setup, described above first call to `MyCoolService.listEntities()`
will save method return value to cache and each next call will return cached
value, stored in redis instead of making database query.
Each function call is signed by a call signature, so if your method accepts
arguments which influence database query execution caching is made for each
unique method call. Cached result will be automatically invalidated each time
each table described in channels will trigger `INSERT`, `UPDATE` or `DELETE`. Or
when TTL on a cache entity expires. By default TTL is 24 hours. If you want
different TTL to be used, do it as:

~~~typescript
@cacheWith({ channels: [MyDbEnity.tableName], ttl: 5 * 60 * 1000 })
~~~

In this example TTL is set to 5 minutes. TTL should be provided in milliseconds.

### Using @cacheBy

Since v2.0.0 @cacheBy decorator introduced and helps simplify caching
invalidation definition for those service methods which rely on a root sequelize
model output. In combination of passing the fields map to such service methods
it will also provide more efficient caching for the method calls.

Take a look at such example:

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheBy } from '@imqueue/pg-cache';
import {
FieldsInput,
FindOptions,
OrderByInput,
PaginationInput,
query,
} from '@imqueue/sequelize';
import { cacheConfig } from '../config';
import { MyDbEntity } from './orm/models';
import { MyDbEntityFilter } from './types';
import withRangeFilters = query.withRangeFilters;
import autoCountQuery = query.autoCountQuery;
import autoQuery = query.autoQuery;
import toWhereOptions = query.toWhereOptions;
import toLimitOptions = query.toLimitOptions;
import toOrderOptions = query.toOrderOptions;

@PgCache(cacheConfig)
class MyCoolService extends IMQService {
@expose()
@cacheBy(MyDbEntity, { fieldsArg: 1 })
public async listEntities(
filter?: MyDbEntityFilter,
fields?: FieldsInput,
pageOptions?: PaginationInput,
orderBy?: OrderByInput,
): Promise<{ total: number, data: MyDbEntity[] }> {
const where = toWhereOptions<MyDbEntityFilter>(
withRangeFilters(filter),
MyDbEntityFilter,
);
const countQuery = autoCountQuery(MyDbEntity, fields, where);
const findQuery = autoQuery<FindOptions>(
MyDbEntity, fields, where,
toLimitOptions<MyDbEntity>(pageOptions),
toOrderOptions(orderBy),
);
const [total, data] = await Promise.all([
MyDbEntity.count(countQuery),
MyDbEntity.findAll(findQuery),
]);

return { total, data } as { total: number, data: MyDbEntity[] };
}
}
~~~

By doing so, `@cacheBy` will take care of invalidating only those queries
which has selection of fields matching db changes events, so if the actual
query was not selecting some joined data, but there was a change only on that
joined data - cache won't invalidate, as far as real selection was not
influenced by a data change. And yes, it will automatically monitor
all related to the root model entities for changes and match them with runtime
selections. This makes caching more efficient and more obvious for
developer.

### Extended channels API

~~~typescript
import { cacheWith, ChannelOperation, ChannelPayload } from '@imqueue/pg-cache';

// using simple filtering by operation
@cacheWith({ channels: {
[MyDbEnity.tableName]: [ChannelOperation.UPDATE, ChannelOperation.INSERT]
}})

// or by using custom filtering function
@cacheWith({ channels: {
[MyDbEnity.tableName]: (
payload: ChannelPayload, // payload caught from db event
) => payload.operation === ChannelOperation.DELETE,
}})
~~~

## Contributing

Any contributions are greatly appreciated. Feel free to fork, propose PRs, open
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
f113ffc
Update README.md
Mikhus Mar 19, 2020
82b24cc
Merge branch 'master' of github.com:imqueue/pg-cache
Mikhus Mar 19, 2020
d14c127
fix: passig args to filter, +docs update
Mikhus Mar 19, 2020
1a9dc91
1.3.0
Mikhus Mar 19, 2020
a2e521e
feat: implemented possibility to publish db channel events to clients…
Mikhus Mar 19, 2020
bc40609
1.3.1
Mikhus Mar 19, 2020
b1aa469
feat: publish tag info
Mikhus Mar 19, 2020
cad510a
1.3.2
Mikhus Mar 19, 2020
cc0f8e7
fix: deps updated
Mikhus Mar 20, 2020
b91de48
1.3.3
Mikhus Mar 20, 2020
f353c53
fix: deps updated
Mikhus Mar 20, 2020
b13fb59
1.3.4
Mikhus Mar 20, 2020
91220e5
fix: deps up
Mikhus Mar 20, 2020
885adde
1.3.5
Mikhus Mar 20, 2020
625db28
fix: deps update
Mikhus Mar 20, 2020
76e2813
1.3.6
Mikhus Mar 20, 2020
e60e870
feat: debug options added; +ability to override trigger sql function
Mikhus Mar 20, 2020
1c7a6df
1.4.0
Mikhus Mar 20, 2020
a2231c0
fix: install triggers
Mikhus Mar 20, 2020
2cde1f8
1.4.1-0
Mikhus Mar 20, 2020
7335834
1.4.1
Mikhus Mar 20, 2020
c460671
fix: trigger creation
Mikhus Mar 20, 2020
f453b2e
1.4.2-0
Mikhus Mar 20, 2020
2c19c26
1.4.2
Mikhus Mar 20, 2020
9ecf6c0
fix: trigger creation
Mikhus Mar 20, 2020
52a765c
1.4.3
Mikhus Mar 20, 2020
995b6d8
fix: trigger creation
Mikhus Mar 20, 2020
1c0eddd
1.4.4
Mikhus Mar 20, 2020
86421a2
fix: auto-publish service events by default
Mikhus Mar 20, 2020
eb23dba
1.5.0
Mikhus Mar 20, 2020
ecf936f
fix: max listeners warn fixed
Mikhus Mar 20, 2020
5b13106
1.5.1
Mikhus Mar 20, 2020
d58d663
fix: proper tag cache version with fixed invalidation
Mikhus Mar 20, 2020
3b41527
1.5.2
Mikhus Mar 20, 2020
f167153
feat: cacheBy implemented; +refactoring
Mikhus Mar 22, 2020
002400a
docs update and minor fixes
Mikhus Mar 22, 2020
ae30773
Merge pull request #1 from imqueue/v2.0.0-dev
Mikhus Mar 22, 2020
11c7562
chore: deps update
Mikhus Mar 22, 2020
ff0ab7a
2.0.0
Mikhus Mar 22, 2020
50afc5b
fix: exports
Mikhus Mar 22, 2020
326eb5c
2.0.1
Mikhus Mar 22, 2020
e477356
fix: if no prevent error on start if no channels set for caching
Mikhus Mar 22, 2020
76136c4
2.0.2
Mikhus Mar 22, 2020
05e6499
fix: update outdated deps
Mikhus Nov 27, 2020
4948597
2.1.0
Mikhus Nov 27, 2020
5295bbc
fix: deps update
Mikhus Nov 30, 2020
0bab44b
2.1.1-0
Mikhus Nov 30, 2020
5faa740
2.1.1
Mikhus Nov 30, 2020
4a2e49e
fix: deps updated
Mikhus May 28, 2021
f580763
2.1.2
Mikhus May 28, 2021
0b38f12
fix: deps up
Mikhus Nov 1, 2021
791366e
2.1.3
Mikhus Nov 1, 2021
7369c1f
chore: build up
Mikhus Nov 1, 2021
d1bb1d6
2.1.4
Mikhus Nov 1, 2021
f584ba3
fix: compatibility to new js versions & tag key hashing
Mar 22, 2022
39e4f7c
fix: deps up
Mikhus Mar 22, 2022
0b54545
2.1.5
Mikhus Mar 22, 2022
5970bc3
fix: deps up
Mikhus Mar 22, 2022
168b0cc
2.1.6
Mikhus Mar 22, 2022
1480e86
fix: install
Mar 22, 2022
125761a
Merge branch 'master' into fix-invalidating-on-change
Mar 22, 2022
4f862e7
Merge pull request #14 from imqueue/fix-invalidating-on-change
SerhiyGreench Mar 22, 2022
8214b7f
2.1.7
Mikhus Mar 22, 2022
106fa4a
fix: removed creating PubSub instance in class properties
Mar 31, 2022
f72e308
2.1.8
Mikhus Mar 31, 2022
ab05c6b
fix: deps updated
Mikhus Apr 1, 2022
3416cdf
2.1.9
Mikhus Apr 1, 2022
2a025a4
fix: deps updated
Mikhus Apr 28, 2022
dade8dc
2.1.10
Mikhus Apr 28, 2022
51f72a8
fix: deps up
Mikhus Apr 28, 2022
5c742ea
2.1.11
Mikhus Apr 28, 2022
d901663
fix: deps updated
Mikhus Apr 29, 2022
056e6bb
2.1.12
Mikhus Apr 29, 2022
d5346c6
fix: deps up
Mikhus May 3, 2022
d18481c
2.1.13
Mikhus May 3, 2022
1e93ce9
fix: deps updated
Mikhus May 10, 2022
2e50e6b
2.2.0
Mikhus May 10, 2022
543de56
chore(deps): bump json5 from 2.2.1 to 2.2.3
dependabot[bot] Jan 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .eslintrc.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -88,8 +88,7 @@
"string",
"Boolean",
"boolean",
"Undefined",
"undefined"
"Undefined"
],
"id-match": "error",
"max-classes-per-file": "off",
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
dist: xenial
dist: focal
language: node_js
env:
global:
Expand Down
123 changes: 123 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,129 @@ Links `@imqueue/pg-pubsub` with `@imqueue/tag-cache` and provides generic
way to implement intellectual cache management based on database changes
notifications for @imqueue-based service methods.

## Usage

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheWith } from '@imqueue/pg-cache';
import { MyDbEntity } from './orm/models';

@PgCache({
postgres: 'postgres://localhost:5432/db-name',
redis: { host: 'localhost', port: 6379 },
prefix: 'my-cool-service', // optional, if not passed will use class name as prefix
})
class MyCoolService extends IMQService {
@expose()
@cacheWith({ channels: [MyDbEnity.tableName] })
public async listEntities(): Promise<MyDbEntity> {
return await MyDbEntity.findAll();
}
}
~~~

With the setup, described above first call to `MyCoolService.listEntities()`
will save method return value to cache and each next call will return cached
value, stored in redis instead of making database query.
Each function call is signed by a call signature, so if your method accepts
arguments which influence database query execution caching is made for each
unique method call. Cached result will be automatically invalidated each time
each table described in channels will trigger `INSERT`, `UPDATE` or `DELETE`. Or
when TTL on a cache entity expires. By default TTL is 24 hours. If you want
different TTL to be used, do it as:

~~~typescript
@cacheWith({ channels: [MyDbEnity.tableName], ttl: 5 * 60 * 1000 })
~~~

In this example TTL is set to 5 minutes. TTL should be provided in milliseconds.

### Using @cacheBy

Since v2.0.0 @cacheBy decorator introduced and helps simplify caching
invalidation definition for those service methods which rely on a root sequelize
model output. In combination of passing the fields map to such service methods
it will also provide more efficient caching for the method calls.

Take a look at such example:

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheBy } from '@imqueue/pg-cache';
import {
FieldsInput,
FindOptions,
OrderByInput,
PaginationInput,
query,
} from '@imqueue/sequelize';
import { cacheConfig } from '../config';
import { MyDbEntity } from './orm/models';
import { MyDbEntityFilter } from './types';
import withRangeFilters = query.withRangeFilters;
import autoCountQuery = query.autoCountQuery;
import autoQuery = query.autoQuery;
import toWhereOptions = query.toWhereOptions;
import toLimitOptions = query.toLimitOptions;
import toOrderOptions = query.toOrderOptions;

@PgCache(cacheConfig)
class MyCoolService extends IMQService {
@expose()
@cacheBy(MyDbEntity, { fieldsArg: 1 })
public async listEntities(
filter?: MyDbEntityFilter,
fields?: FieldsInput,
pageOptions?: PaginationInput,
orderBy?: OrderByInput,
): Promise<{ total: number, data: MyDbEntity[] }> {
const where = toWhereOptions<MyDbEntityFilter>(
withRangeFilters(filter),
MyDbEntityFilter,
);
const countQuery = autoCountQuery(MyDbEntity, fields, where);
const findQuery = autoQuery<FindOptions>(
MyDbEntity, fields, where,
toLimitOptions<MyDbEntity>(pageOptions),
toOrderOptions(orderBy),
);
const [total, data] = await Promise.all([
MyDbEntity.count(countQuery),
MyDbEntity.findAll(findQuery),
]);

return { total, data } as { total: number, data: MyDbEntity[] };
}
}
~~~

By doing so, `@cacheBy` will take care of invalidating only those queries
which has selection of fields matching db changes events, so if the actual
query was not selecting some joined data, but there was a change only on that
joined data - cache won't invalidate, as far as real selection was not
influenced by a data change. And yes, it will automatically monitor
all related to the root model entities for changes and match them with runtime
selections. This makes caching more efficient and more obvious for
developer.

### Extended channels API

~~~typescript
import { cacheWith, ChannelOperation, ChannelPayload } from '@imqueue/pg-cache';

// using simple filtering by operation
@cacheWith({ channels: {
[MyDbEnity.tableName]: [ChannelOperation.UPDATE, ChannelOperation.INSERT]
}})

// or by using custom filtering function
@cacheWith({ channels: {
[MyDbEnity.tableName]: (
payload: ChannelPayload, // payload caught from db event
) => payload.operation === ChannelOperation.DELETE,
}})
~~~

## Contributing

Any contributions are greatly appreciated. Feel free to fork, propose PRs, open
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
f113ffc
Update README.md
Mikhus Mar 19, 2020
82b24cc
Merge branch 'master' of github.com:imqueue/pg-cache
Mikhus Mar 19, 2020
d14c127
fix: passig args to filter, +docs update
Mikhus Mar 19, 2020
1a9dc91
1.3.0
Mikhus Mar 19, 2020
a2e521e
feat: implemented possibility to publish db channel events to clients…
Mikhus Mar 19, 2020
bc40609
1.3.1
Mikhus Mar 19, 2020
b1aa469
feat: publish tag info
Mikhus Mar 19, 2020
cad510a
1.3.2
Mikhus Mar 19, 2020
cc0f8e7
fix: deps updated
Mikhus Mar 20, 2020
b91de48
1.3.3
Mikhus Mar 20, 2020
f353c53
fix: deps updated
Mikhus Mar 20, 2020
b13fb59
1.3.4
Mikhus Mar 20, 2020
91220e5
fix: deps up
Mikhus Mar 20, 2020
885adde
1.3.5
Mikhus Mar 20, 2020
625db28
fix: deps update
Mikhus Mar 20, 2020
76e2813
1.3.6
Mikhus Mar 20, 2020
e60e870
feat: debug options added; +ability to override trigger sql function
Mikhus Mar 20, 2020
1c7a6df
1.4.0
Mikhus Mar 20, 2020
a2231c0
fix: install triggers
Mikhus Mar 20, 2020
2cde1f8
1.4.1-0
Mikhus Mar 20, 2020
7335834
1.4.1
Mikhus Mar 20, 2020
c460671
fix: trigger creation
Mikhus Mar 20, 2020
f453b2e
1.4.2-0
Mikhus Mar 20, 2020
2c19c26
1.4.2
Mikhus Mar 20, 2020
9ecf6c0
fix: trigger creation
Mikhus Mar 20, 2020
52a765c
1.4.3
Mikhus Mar 20, 2020
995b6d8
fix: trigger creation
Mikhus Mar 20, 2020
1c0eddd
1.4.4
Mikhus Mar 20, 2020
86421a2
fix: auto-publish service events by default
Mikhus Mar 20, 2020
eb23dba
1.5.0
Mikhus Mar 20, 2020
ecf936f
fix: max listeners warn fixed
Mikhus Mar 20, 2020
5b13106
1.5.1
Mikhus Mar 20, 2020
d58d663
fix: proper tag cache version with fixed invalidation
Mikhus Mar 20, 2020
3b41527
1.5.2
Mikhus Mar 20, 2020
f167153
feat: cacheBy implemented; +refactoring
Mikhus Mar 22, 2020
002400a
docs update and minor fixes
Mikhus Mar 22, 2020
ae30773
Merge pull request #1 from imqueue/v2.0.0-dev
Mikhus Mar 22, 2020
11c7562
chore: deps update
Mikhus Mar 22, 2020
ff0ab7a
2.0.0
Mikhus Mar 22, 2020
50afc5b
fix: exports
Mikhus Mar 22, 2020
326eb5c
2.0.1
Mikhus Mar 22, 2020
e477356
fix: if no prevent error on start if no channels set for caching
Mikhus Mar 22, 2020
76136c4
2.0.2
Mikhus Mar 22, 2020
05e6499
fix: update outdated deps
Mikhus Nov 27, 2020
4948597
2.1.0
Mikhus Nov 27, 2020
5295bbc
fix: deps update
Mikhus Nov 30, 2020
0bab44b
2.1.1-0
Mikhus Nov 30, 2020
5faa740
2.1.1
Mikhus Nov 30, 2020
4a2e49e
fix: deps updated
Mikhus May 28, 2021
f580763
2.1.2
Mikhus May 28, 2021
0b38f12
fix: deps up
Mikhus Nov 1, 2021
791366e
2.1.3
Mikhus Nov 1, 2021
7369c1f
chore: build up
Mikhus Nov 1, 2021
d1bb1d6
2.1.4
Mikhus Nov 1, 2021
f584ba3
fix: compatibility to new js versions & tag key hashing
Mar 22, 2022
39e4f7c
fix: deps up
Mikhus Mar 22, 2022
0b54545
2.1.5
Mikhus Mar 22, 2022
5970bc3
fix: deps up
Mikhus Mar 22, 2022
168b0cc
2.1.6
Mikhus Mar 22, 2022
1480e86
fix: install
Mar 22, 2022
125761a
Merge branch 'master' into fix-invalidating-on-change
Mar 22, 2022
4f862e7
Merge pull request #14 from imqueue/fix-invalidating-on-change
SerhiyGreench Mar 22, 2022
8214b7f
2.1.7
Mikhus Mar 22, 2022
106fa4a
fix: removed creating PubSub instance in class properties
Mar 31, 2022
f72e308
2.1.8
Mikhus Mar 31, 2022
ab05c6b
fix: deps updated
Mikhus Apr 1, 2022
3416cdf
2.1.9
Mikhus Apr 1, 2022
2a025a4
fix: deps updated
Mikhus Apr 28, 2022
dade8dc
2.1.10
Mikhus Apr 28, 2022
51f72a8
fix: deps up
Mikhus Apr 28, 2022
5c742ea
2.1.11
Mikhus Apr 28, 2022
d901663
fix: deps updated
Mikhus Apr 29, 2022
056e6bb
2.1.12
Mikhus Apr 29, 2022
d5346c6
fix: deps up
Mikhus May 3, 2022
d18481c
2.1.13
Mikhus May 3, 2022
1e93ce9
fix: deps updated
Mikhus May 10, 2022
2e50e6b
2.2.0
Mikhus May 10, 2022
543de56
chore(deps): bump json5 from 2.2.1 to 2.2.3
dependabot[bot] Jan 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .eslintrc.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -88,8 +88,7 @@
"string",
"Boolean",
"boolean",
"Undefined",
"undefined"
"Undefined"
],
"id-match": "error",
"max-classes-per-file": "off",
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
dist: xenial
dist: focal
language: node_js
env:
global:
Expand Down
123 changes: 123 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,129 @@ Links `@imqueue/pg-pubsub` with `@imqueue/tag-cache` and provides generic
way to implement intellectual cache management based on database changes
notifications for @imqueue-based service methods.

## Usage

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheWith } from '@imqueue/pg-cache';
import { MyDbEntity } from './orm/models';

@PgCache({
postgres: 'postgres://localhost:5432/db-name',
redis: { host: 'localhost', port: 6379 },
prefix: 'my-cool-service', // optional, if not passed will use class name as prefix
})
class MyCoolService extends IMQService {
@expose()
@cacheWith({ channels: [MyDbEnity.tableName] })
public async listEntities(): Promise<MyDbEntity> {
return await MyDbEntity.findAll();
}
}
~~~

With the setup, described above first call to `MyCoolService.listEntities()`
will save method return value to cache and each next call will return cached
value, stored in redis instead of making database query.
Each function call is signed by a call signature, so if your method accepts
arguments which influence database query execution caching is made for each
unique method call. Cached result will be automatically invalidated each time
each table described in channels will trigger `INSERT`, `UPDATE` or `DELETE`. Or
when TTL on a cache entity expires. By default TTL is 24 hours. If you want
different TTL to be used, do it as:

~~~typescript
@cacheWith({ channels: [MyDbEnity.tableName], ttl: 5 * 60 * 1000 })
~~~

In this example TTL is set to 5 minutes. TTL should be provided in milliseconds.

### Using @cacheBy

Since v2.0.0 @cacheBy decorator introduced and helps simplify caching
invalidation definition for those service methods which rely on a root sequelize
model output. In combination of passing the fields map to such service methods
it will also provide more efficient caching for the method calls.

Take a look at such example:

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheBy } from '@imqueue/pg-cache';
import {
FieldsInput,
FindOptions,
OrderByInput,
PaginationInput,
query,
} from '@imqueue/sequelize';
import { cacheConfig } from '../config';
import { MyDbEntity } from './orm/models';
import { MyDbEntityFilter } from './types';
import withRangeFilters = query.withRangeFilters;
import autoCountQuery = query.autoCountQuery;
import autoQuery = query.autoQuery;
import toWhereOptions = query.toWhereOptions;
import toLimitOptions = query.toLimitOptions;
import toOrderOptions = query.toOrderOptions;

@PgCache(cacheConfig)
class MyCoolService extends IMQService {
@expose()
@cacheBy(MyDbEntity, { fieldsArg: 1 })
public async listEntities(
filter?: MyDbEntityFilter,
fields?: FieldsInput,
pageOptions?: PaginationInput,
orderBy?: OrderByInput,
): Promise<{ total: number, data: MyDbEntity[] }> {
const where = toWhereOptions<MyDbEntityFilter>(
withRangeFilters(filter),
MyDbEntityFilter,
);
const countQuery = autoCountQuery(MyDbEntity, fields, where);
const findQuery = autoQuery<FindOptions>(
MyDbEntity, fields, where,
toLimitOptions<MyDbEntity>(pageOptions),
toOrderOptions(orderBy),
);
const [total, data] = await Promise.all([
MyDbEntity.count(countQuery),
MyDbEntity.findAll(findQuery),
]);

return { total, data } as { total: number, data: MyDbEntity[] };
}
}
~~~

By doing so, `@cacheBy` will take care of invalidating only those queries
which has selection of fields matching db changes events, so if the actual
query was not selecting some joined data, but there was a change only on that
joined data - cache won't invalidate, as far as real selection was not
influenced by a data change. And yes, it will automatically monitor
all related to the root model entities for changes and match them with runtime
selections. This makes caching more efficient and more obvious for
developer.

### Extended channels API

~~~typescript
import { cacheWith, ChannelOperation, ChannelPayload } from '@imqueue/pg-cache';

// using simple filtering by operation
@cacheWith({ channels: {
[MyDbEnity.tableName]: [ChannelOperation.UPDATE, ChannelOperation.INSERT]
}})

// or by using custom filtering function
@cacheWith({ channels: {
[MyDbEnity.tableName]: (
payload: ChannelPayload, // payload caught from db event
) => payload.operation === ChannelOperation.DELETE,
}})
~~~

## Contributing

Any contributions are greatly appreciated. Feel free to fork, propose PRs, open
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
f113ffc
Update README.md
Mikhus Mar 19, 2020
82b24cc
Merge branch 'master' of github.com:imqueue/pg-cache
Mikhus Mar 19, 2020
d14c127
fix: passig args to filter, +docs update
Mikhus Mar 19, 2020
1a9dc91
1.3.0
Mikhus Mar 19, 2020
a2e521e
feat: implemented possibility to publish db channel events to clients…
Mikhus Mar 19, 2020
bc40609
1.3.1
Mikhus Mar 19, 2020
b1aa469
feat: publish tag info
Mikhus Mar 19, 2020
cad510a
1.3.2
Mikhus Mar 19, 2020
cc0f8e7
fix: deps updated
Mikhus Mar 20, 2020
b91de48
1.3.3
Mikhus Mar 20, 2020
f353c53
fix: deps updated
Mikhus Mar 20, 2020
b13fb59
1.3.4
Mikhus Mar 20, 2020
91220e5
fix: deps up
Mikhus Mar 20, 2020
885adde
1.3.5
Mikhus Mar 20, 2020
625db28
fix: deps update
Mikhus Mar 20, 2020
76e2813
1.3.6
Mikhus Mar 20, 2020
e60e870
feat: debug options added; +ability to override trigger sql function
Mikhus Mar 20, 2020
1c7a6df
1.4.0
Mikhus Mar 20, 2020
a2231c0
fix: install triggers
Mikhus Mar 20, 2020
2cde1f8
1.4.1-0
Mikhus Mar 20, 2020
7335834
1.4.1
Mikhus Mar 20, 2020
c460671
fix: trigger creation
Mikhus Mar 20, 2020
f453b2e
1.4.2-0
Mikhus Mar 20, 2020
2c19c26
1.4.2
Mikhus Mar 20, 2020
9ecf6c0
fix: trigger creation
Mikhus Mar 20, 2020
52a765c
1.4.3
Mikhus Mar 20, 2020
995b6d8
fix: trigger creation
Mikhus Mar 20, 2020
1c0eddd
1.4.4
Mikhus Mar 20, 2020
86421a2
fix: auto-publish service events by default
Mikhus Mar 20, 2020
eb23dba
1.5.0
Mikhus Mar 20, 2020
ecf936f
fix: max listeners warn fixed
Mikhus Mar 20, 2020
5b13106
1.5.1
Mikhus Mar 20, 2020
d58d663
fix: proper tag cache version with fixed invalidation
Mikhus Mar 20, 2020
3b41527
1.5.2
Mikhus Mar 20, 2020
f167153
feat: cacheBy implemented; +refactoring
Mikhus Mar 22, 2020
002400a
docs update and minor fixes
Mikhus Mar 22, 2020
ae30773
Merge pull request #1 from imqueue/v2.0.0-dev
Mikhus Mar 22, 2020
11c7562
chore: deps update
Mikhus Mar 22, 2020
ff0ab7a
2.0.0
Mikhus Mar 22, 2020
50afc5b
fix: exports
Mikhus Mar 22, 2020
326eb5c
2.0.1
Mikhus Mar 22, 2020
e477356
fix: if no prevent error on start if no channels set for caching
Mikhus Mar 22, 2020
76136c4
2.0.2
Mikhus Mar 22, 2020
05e6499
fix: update outdated deps
Mikhus Nov 27, 2020
4948597
2.1.0
Mikhus Nov 27, 2020
5295bbc
fix: deps update
Mikhus Nov 30, 2020
0bab44b
2.1.1-0
Mikhus Nov 30, 2020
5faa740
2.1.1
Mikhus Nov 30, 2020
4a2e49e
fix: deps updated
Mikhus May 28, 2021
f580763
2.1.2
Mikhus May 28, 2021
0b38f12
fix: deps up
Mikhus Nov 1, 2021
791366e
2.1.3
Mikhus Nov 1, 2021
7369c1f
chore: build up
Mikhus Nov 1, 2021
d1bb1d6
2.1.4
Mikhus Nov 1, 2021
f584ba3
fix: compatibility to new js versions & tag key hashing
Mar 22, 2022
39e4f7c
fix: deps up
Mikhus Mar 22, 2022
0b54545
2.1.5
Mikhus Mar 22, 2022
5970bc3
fix: deps up
Mikhus Mar 22, 2022
168b0cc
2.1.6
Mikhus Mar 22, 2022
1480e86
fix: install
Mar 22, 2022
125761a
Merge branch 'master' into fix-invalidating-on-change
Mar 22, 2022
4f862e7
Merge pull request #14 from imqueue/fix-invalidating-on-change
SerhiyGreench Mar 22, 2022
8214b7f
2.1.7
Mikhus Mar 22, 2022
106fa4a
fix: removed creating PubSub instance in class properties
Mar 31, 2022
f72e308
2.1.8
Mikhus Mar 31, 2022
ab05c6b
fix: deps updated
Mikhus Apr 1, 2022
3416cdf
2.1.9
Mikhus Apr 1, 2022
2a025a4
fix: deps updated
Mikhus Apr 28, 2022
dade8dc
2.1.10
Mikhus Apr 28, 2022
51f72a8
fix: deps up
Mikhus Apr 28, 2022
5c742ea
2.1.11
Mikhus Apr 28, 2022
d901663
fix: deps updated
Mikhus Apr 29, 2022
056e6bb
2.1.12
Mikhus Apr 29, 2022
d5346c6
fix: deps up
Mikhus May 3, 2022
d18481c
2.1.13
Mikhus May 3, 2022
1e93ce9
fix: deps updated
Mikhus May 10, 2022
2e50e6b
2.2.0
Mikhus May 10, 2022
543de56
chore(deps): bump json5 from 2.2.1 to 2.2.3
dependabot[bot] Jan 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .eslintrc.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -88,8 +88,7 @@
"string",
"Boolean",
"boolean",
"Undefined",
"undefined"
"Undefined"
],
"id-match": "error",
"max-classes-per-file": "off",
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
dist: xenial
dist: focal
language: node_js
env:
global:
Expand Down
123 changes: 123 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,129 @@ Links `@imqueue/pg-pubsub` with `@imqueue/tag-cache` and provides generic
way to implement intellectual cache management based on database changes
notifications for @imqueue-based service methods.

## Usage

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheWith } from '@imqueue/pg-cache';
import { MyDbEntity } from './orm/models';

@PgCache({
postgres: 'postgres://localhost:5432/db-name',
redis: { host: 'localhost', port: 6379 },
prefix: 'my-cool-service', // optional, if not passed will use class name as prefix
})
class MyCoolService extends IMQService {
@expose()
@cacheWith({ channels: [MyDbEnity.tableName] })
public async listEntities(): Promise<MyDbEntity> {
return await MyDbEntity.findAll();
}
}
~~~

With the setup, described above first call to `MyCoolService.listEntities()`
will save method return value to cache and each next call will return cached
value, stored in redis instead of making database query.
Each function call is signed by a call signature, so if your method accepts
arguments which influence database query execution caching is made for each
unique method call. Cached result will be automatically invalidated each time
each table described in channels will trigger `INSERT`, `UPDATE` or `DELETE`. Or
when TTL on a cache entity expires. By default TTL is 24 hours. If you want
different TTL to be used, do it as:

~~~typescript
@cacheWith({ channels: [MyDbEnity.tableName], ttl: 5 * 60 * 1000 })
~~~

In this example TTL is set to 5 minutes. TTL should be provided in milliseconds.

### Using @cacheBy

Since v2.0.0 @cacheBy decorator introduced and helps simplify caching
invalidation definition for those service methods which rely on a root sequelize
model output. In combination of passing the fields map to such service methods
it will also provide more efficient caching for the method calls.

Take a look at such example:

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheBy } from '@imqueue/pg-cache';
import {
FieldsInput,
FindOptions,
OrderByInput,
PaginationInput,
query,
} from '@imqueue/sequelize';
import { cacheConfig } from '../config';
import { MyDbEntity } from './orm/models';
import { MyDbEntityFilter } from './types';
import withRangeFilters = query.withRangeFilters;
import autoCountQuery = query.autoCountQuery;
import autoQuery = query.autoQuery;
import toWhereOptions = query.toWhereOptions;
import toLimitOptions = query.toLimitOptions;
import toOrderOptions = query.toOrderOptions;

@PgCache(cacheConfig)
class MyCoolService extends IMQService {
@expose()
@cacheBy(MyDbEntity, { fieldsArg: 1 })
public async listEntities(
filter?: MyDbEntityFilter,
fields?: FieldsInput,
pageOptions?: PaginationInput,
orderBy?: OrderByInput,
): Promise<{ total: number, data: MyDbEntity[] }> {
const where = toWhereOptions<MyDbEntityFilter>(
withRangeFilters(filter),
MyDbEntityFilter,
);
const countQuery = autoCountQuery(MyDbEntity, fields, where);
const findQuery = autoQuery<FindOptions>(
MyDbEntity, fields, where,
toLimitOptions<MyDbEntity>(pageOptions),
toOrderOptions(orderBy),
);
const [total, data] = await Promise.all([
MyDbEntity.count(countQuery),
MyDbEntity.findAll(findQuery),
]);

return { total, data } as { total: number, data: MyDbEntity[] };
}
}
~~~

By doing so, `@cacheBy` will take care of invalidating only those queries
which has selection of fields matching db changes events, so if the actual
query was not selecting some joined data, but there was a change only on that
joined data - cache won't invalidate, as far as real selection was not
influenced by a data change. And yes, it will automatically monitor
all related to the root model entities for changes and match them with runtime
selections. This makes caching more efficient and more obvious for
developer.

### Extended channels API

~~~typescript
import { cacheWith, ChannelOperation, ChannelPayload } from '@imqueue/pg-cache';

// using simple filtering by operation
@cacheWith({ channels: {
[MyDbEnity.tableName]: [ChannelOperation.UPDATE, ChannelOperation.INSERT]
}})

// or by using custom filtering function
@cacheWith({ channels: {
[MyDbEnity.tableName]: (
payload: ChannelPayload, // payload caught from db event
) => payload.operation === ChannelOperation.DELETE,
}})
~~~

## Contributing

Any contributions are greatly appreciated. Feel free to fork, propose PRs, open
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
f113ffc
Update README.md
Mikhus Mar 19, 2020
82b24cc
Merge branch 'master' of github.com:imqueue/pg-cache
Mikhus Mar 19, 2020
d14c127
fix: passig args to filter, +docs update
Mikhus Mar 19, 2020
1a9dc91
1.3.0
Mikhus Mar 19, 2020
a2e521e
feat: implemented possibility to publish db channel events to clients…
Mikhus Mar 19, 2020
bc40609
1.3.1
Mikhus Mar 19, 2020
b1aa469
feat: publish tag info
Mikhus Mar 19, 2020
cad510a
1.3.2
Mikhus Mar 19, 2020
cc0f8e7
fix: deps updated
Mikhus Mar 20, 2020
b91de48
1.3.3
Mikhus Mar 20, 2020
f353c53
fix: deps updated
Mikhus Mar 20, 2020
b13fb59
1.3.4
Mikhus Mar 20, 2020
91220e5
fix: deps up
Mikhus Mar 20, 2020
885adde
1.3.5
Mikhus Mar 20, 2020
625db28
fix: deps update
Mikhus Mar 20, 2020
76e2813
1.3.6
Mikhus Mar 20, 2020
e60e870
feat: debug options added; +ability to override trigger sql function
Mikhus Mar 20, 2020
1c7a6df
1.4.0
Mikhus Mar 20, 2020
a2231c0
fix: install triggers
Mikhus Mar 20, 2020
2cde1f8
1.4.1-0
Mikhus Mar 20, 2020
7335834
1.4.1
Mikhus Mar 20, 2020
c460671
fix: trigger creation
Mikhus Mar 20, 2020
f453b2e
1.4.2-0
Mikhus Mar 20, 2020
2c19c26
1.4.2
Mikhus Mar 20, 2020
9ecf6c0
fix: trigger creation
Mikhus Mar 20, 2020
52a765c
1.4.3
Mikhus Mar 20, 2020
995b6d8
fix: trigger creation
Mikhus Mar 20, 2020
1c0eddd
1.4.4
Mikhus Mar 20, 2020
86421a2
fix: auto-publish service events by default
Mikhus Mar 20, 2020
eb23dba
1.5.0
Mikhus Mar 20, 2020
ecf936f
fix: max listeners warn fixed
Mikhus Mar 20, 2020
5b13106
1.5.1
Mikhus Mar 20, 2020
d58d663
fix: proper tag cache version with fixed invalidation
Mikhus Mar 20, 2020
3b41527
1.5.2
Mikhus Mar 20, 2020
f167153
feat: cacheBy implemented; +refactoring
Mikhus Mar 22, 2020
002400a
docs update and minor fixes
Mikhus Mar 22, 2020
ae30773
Merge pull request #1 from imqueue/v2.0.0-dev
Mikhus Mar 22, 2020
11c7562
chore: deps update
Mikhus Mar 22, 2020
ff0ab7a
2.0.0
Mikhus Mar 22, 2020
50afc5b
fix: exports
Mikhus Mar 22, 2020
326eb5c
2.0.1
Mikhus Mar 22, 2020
e477356
fix: if no prevent error on start if no channels set for caching
Mikhus Mar 22, 2020
76136c4
2.0.2
Mikhus Mar 22, 2020
05e6499
fix: update outdated deps
Mikhus Nov 27, 2020
4948597
2.1.0
Mikhus Nov 27, 2020
5295bbc
fix: deps update
Mikhus Nov 30, 2020
0bab44b
2.1.1-0
Mikhus Nov 30, 2020
5faa740
2.1.1
Mikhus Nov 30, 2020
4a2e49e
fix: deps updated
Mikhus May 28, 2021
f580763
2.1.2
Mikhus May 28, 2021
0b38f12
fix: deps up
Mikhus Nov 1, 2021
791366e
2.1.3
Mikhus Nov 1, 2021
7369c1f
chore: build up
Mikhus Nov 1, 2021
d1bb1d6
2.1.4
Mikhus Nov 1, 2021
f584ba3
fix: compatibility to new js versions & tag key hashing
Mar 22, 2022
39e4f7c
fix: deps up
Mikhus Mar 22, 2022
0b54545
2.1.5
Mikhus Mar 22, 2022
5970bc3
fix: deps up
Mikhus Mar 22, 2022
168b0cc
2.1.6
Mikhus Mar 22, 2022
1480e86
fix: install
Mar 22, 2022
125761a
Merge branch 'master' into fix-invalidating-on-change
Mar 22, 2022
4f862e7
Merge pull request #14 from imqueue/fix-invalidating-on-change
SerhiyGreench Mar 22, 2022
8214b7f
2.1.7
Mikhus Mar 22, 2022
106fa4a
fix: removed creating PubSub instance in class properties
Mar 31, 2022
f72e308
2.1.8
Mikhus Mar 31, 2022
ab05c6b
fix: deps updated
Mikhus Apr 1, 2022
3416cdf
2.1.9
Mikhus Apr 1, 2022
2a025a4
fix: deps updated
Mikhus Apr 28, 2022
dade8dc
2.1.10
Mikhus Apr 28, 2022
51f72a8
fix: deps up
Mikhus Apr 28, 2022
5c742ea
2.1.11
Mikhus Apr 28, 2022
d901663
fix: deps updated
Mikhus Apr 29, 2022
056e6bb
2.1.12
Mikhus Apr 29, 2022
d5346c6
fix: deps up
Mikhus May 3, 2022
d18481c
2.1.13
Mikhus May 3, 2022
1e93ce9
fix: deps updated
Mikhus May 10, 2022
2e50e6b
2.2.0
Mikhus May 10, 2022
543de56
chore(deps): bump json5 from 2.2.1 to 2.2.3
dependabot[bot] Jan 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .eslintrc.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -88,8 +88,7 @@
"string",
"Boolean",
"boolean",
"Undefined",
"undefined"
"Undefined"
],
"id-match": "error",
"max-classes-per-file": "off",
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
dist: xenial
dist: focal
language: node_js
env:
global:
Expand Down
123 changes: 123 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,129 @@ Links `@imqueue/pg-pubsub` with `@imqueue/tag-cache` and provides generic
way to implement intellectual cache management based on database changes
notifications for @imqueue-based service methods.

## Usage

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheWith } from '@imqueue/pg-cache';
import { MyDbEntity } from './orm/models';

@PgCache({
postgres: 'postgres://localhost:5432/db-name',
redis: { host: 'localhost', port: 6379 },
prefix: 'my-cool-service', // optional, if not passed will use class name as prefix
})
class MyCoolService extends IMQService {
@expose()
@cacheWith({ channels: [MyDbEnity.tableName] })
public async listEntities(): Promise<MyDbEntity> {
return await MyDbEntity.findAll();
}
}
~~~

With the setup, described above first call to `MyCoolService.listEntities()`
will save method return value to cache and each next call will return cached
value, stored in redis instead of making database query.
Each function call is signed by a call signature, so if your method accepts
arguments which influence database query execution caching is made for each
unique method call. Cached result will be automatically invalidated each time
each table described in channels will trigger `INSERT`, `UPDATE` or `DELETE`. Or
when TTL on a cache entity expires. By default TTL is 24 hours. If you want
different TTL to be used, do it as:

~~~typescript
@cacheWith({ channels: [MyDbEnity.tableName], ttl: 5 * 60 * 1000 })
~~~

In this example TTL is set to 5 minutes. TTL should be provided in milliseconds.

### Using @cacheBy

Since v2.0.0 @cacheBy decorator introduced and helps simplify caching
invalidation definition for those service methods which rely on a root sequelize
model output. In combination of passing the fields map to such service methods
it will also provide more efficient caching for the method calls.

Take a look at such example:

~~~typescript
import { IMQService, expose } from '@imqueue/rpc';
import { PgCache, cacheBy } from '@imqueue/pg-cache';
import {
FieldsInput,
FindOptions,
OrderByInput,
PaginationInput,
query,
} from '@imqueue/sequelize';
import { cacheConfig } from '../config';
import { MyDbEntity } from './orm/models';
import { MyDbEntityFilter } from './types';
import withRangeFilters = query.withRangeFilters;
import autoCountQuery = query.autoCountQuery;
import autoQuery = query.autoQuery;
import toWhereOptions = query.toWhereOptions;
import toLimitOptions = query.toLimitOptions;
import toOrderOptions = query.toOrderOptions;

@PgCache(cacheConfig)
class MyCoolService extends IMQService {
@expose()
@cacheBy(MyDbEntity, { fieldsArg: 1 })
public async listEntities(
filter?: MyDbEntityFilter,
fields?: FieldsInput,
pageOptions?: PaginationInput,
orderBy?: OrderByInput,
): Promise<{ total: number, data: MyDbEntity[] }> {
const where = toWhereOptions<MyDbEntityFilter>(
withRangeFilters(filter),
MyDbEntityFilter,
);
const countQuery = autoCountQuery(MyDbEntity, fields, where);
const findQuery = autoQuery<FindOptions>(
MyDbEntity, fields, where,
toLimitOptions<MyDbEntity>(pageOptions),
toOrderOptions(orderBy),
);
const [total, data] = await Promise.all([
MyDbEntity.count(countQuery),
MyDbEntity.findAll(findQuery),
]);

return { total, data } as { total: number, data: MyDbEntity[] };
}
}
~~~

By doing so, `@cacheBy` will take care of invalidating only those queries
which has selection of fields matching db changes events, so if the actual
query was not selecting some joined data, but there was a change only on that
joined data - cache won't invalidate, as far as real selection was not
influenced by a data change. And yes, it will automatically monitor
all related to the root model entities for changes and match them with runtime
selections. This makes caching more efficient and more obvious for
developer.

### Extended channels API

~~~typescript
import { cacheWith, ChannelOperation, ChannelPayload } from '@imqueue/pg-cache';

// using simple filtering by operation
@cacheWith({ channels: {
[MyDbEnity.tableName]: [ChannelOperation.UPDATE, ChannelOperation.INSERT]
}})

// or by using custom filtering function
@cacheWith({ channels: {
[MyDbEnity.tableName]: (
payload: ChannelPayload, // payload caught from db event
) => payload.operation === ChannelOperation.DELETE,
}})
~~~

## Contributing

Any contributions are greatly appreciated. Feel free to fork, propose PRs, open
Expand Down
Loading