strapi-cache 1.8.2-rc.3 → 1.8.4
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/dist/server/index.js
CHANGED
|
@@ -5,7 +5,6 @@ const zlib = require("zlib");
|
|
|
5
5
|
const rawBody = require("raw-body");
|
|
6
6
|
const lruCache = require("lru-cache");
|
|
7
7
|
const ioredis = require("ioredis");
|
|
8
|
-
const iovalkey = require("iovalkey");
|
|
9
8
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
10
9
|
const Stream__default = /* @__PURE__ */ _interopDefault(Stream);
|
|
11
10
|
const rawBody__default = /* @__PURE__ */ _interopDefault(rawBody);
|
|
@@ -544,7 +543,8 @@ const config = {
|
|
|
544
543
|
autoPurgeCache: true,
|
|
545
544
|
autoPurgeCacheOnStart: true,
|
|
546
545
|
disableAdminPopups: false,
|
|
547
|
-
disableAdminButtons: false
|
|
546
|
+
disableAdminButtons: false,
|
|
547
|
+
redisScanDeleteCount: 100
|
|
548
548
|
}),
|
|
549
549
|
validator: (config2) => {
|
|
550
550
|
if (typeof config2.debug !== "boolean") {
|
|
@@ -624,6 +624,9 @@ const config = {
|
|
|
624
624
|
if (typeof config2.disableAdminButtons !== "boolean") {
|
|
625
625
|
throw new Error(`Invalid config: disableAdminButtons must be a boolean`);
|
|
626
626
|
}
|
|
627
|
+
if (typeof config2.redisScanDeleteCount !== "number") {
|
|
628
|
+
throw new Error(`Invalid config: redisScanDeleteCount must be a number`);
|
|
629
|
+
}
|
|
627
630
|
}
|
|
628
631
|
};
|
|
629
632
|
const contentTypes = {};
|
|
@@ -856,34 +859,20 @@ class RedisCacheProvider {
|
|
|
856
859
|
this.strapi.plugin("strapi-cache").config("cacheGetTimeoutInMs")
|
|
857
860
|
);
|
|
858
861
|
this.keyPrefix = this.strapi.plugin("strapi-cache").config("redisConfig")?.["keyPrefix"] ?? "";
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
this.client = new iovalkey.Cluster(
|
|
867
|
-
redisClusterNodes,
|
|
868
|
-
clusterOptions
|
|
869
|
-
);
|
|
870
|
-
} else {
|
|
871
|
-
this.client = new iovalkey.Redis(redisConfig);
|
|
862
|
+
this.redisScanDeleteCount = Number(
|
|
863
|
+
this.strapi.plugin("strapi-cache").config("redisScanDeleteCount")
|
|
864
|
+
);
|
|
865
|
+
if (redisClusterNodes.length) {
|
|
866
|
+
const redisClusterOptions = this.strapi.plugin("strapi-cache").config("redisClusterOptions");
|
|
867
|
+
if (!redisClusterOptions["redisOptions"]) {
|
|
868
|
+
redisClusterOptions.redisOptions = redisConfig;
|
|
872
869
|
}
|
|
873
|
-
|
|
870
|
+
this.client = new ioredis.Redis.Cluster(redisClusterNodes, redisClusterOptions);
|
|
874
871
|
} else {
|
|
875
|
-
|
|
876
|
-
const redisClusterOptions = this.strapi.plugin("strapi-cache").config("redisClusterOptions");
|
|
877
|
-
if (!redisClusterOptions["redisOptions"]) {
|
|
878
|
-
redisClusterOptions.redisOptions = redisConfig;
|
|
879
|
-
}
|
|
880
|
-
this.client = new ioredis.Redis.Cluster(redisClusterNodes, redisClusterOptions);
|
|
881
|
-
} else {
|
|
882
|
-
this.client = new ioredis.Redis(redisConfig);
|
|
883
|
-
}
|
|
884
|
-
loggy.info("Redis provider initialized");
|
|
872
|
+
this.client = new ioredis.Redis(redisConfig);
|
|
885
873
|
}
|
|
886
874
|
this.initialized = true;
|
|
875
|
+
loggy.info(`${provider === "valkey" ? "Valkey" : "Redis"} provider initialized`);
|
|
887
876
|
} catch (error) {
|
|
888
877
|
loggy.error(error);
|
|
889
878
|
}
|
|
@@ -931,18 +920,6 @@ class RedisCacheProvider {
|
|
|
931
920
|
return null;
|
|
932
921
|
}
|
|
933
922
|
}
|
|
934
|
-
/**
|
|
935
|
-
* Deletes all given keys in Redis pipeline.
|
|
936
|
-
* @param keys to delete from cache
|
|
937
|
-
*/
|
|
938
|
-
async delAll(keys) {
|
|
939
|
-
const pipeline = this.client.pipeline();
|
|
940
|
-
keys.forEach((key) => {
|
|
941
|
-
const relativeKey = key.slice(this.keyPrefix.length);
|
|
942
|
-
pipeline.del(relativeKey);
|
|
943
|
-
});
|
|
944
|
-
await pipeline.exec();
|
|
945
|
-
}
|
|
946
923
|
async keys() {
|
|
947
924
|
if (!this.ready) return null;
|
|
948
925
|
try {
|
|
@@ -972,13 +949,37 @@ class RedisCacheProvider {
|
|
|
972
949
|
return null;
|
|
973
950
|
}
|
|
974
951
|
}
|
|
952
|
+
async deleteBatch(client, batch, regExps) {
|
|
953
|
+
const toDelete = batch.filter((key) => regExps.some((re) => re.test(key)));
|
|
954
|
+
if (toDelete.length === 0) return;
|
|
955
|
+
const pipeline = client.pipeline();
|
|
956
|
+
for (const key of toDelete) {
|
|
957
|
+
const relativeKey = key.startsWith(this.keyPrefix) ? key.slice(this.keyPrefix.length) : key;
|
|
958
|
+
pipeline.del(relativeKey);
|
|
959
|
+
}
|
|
960
|
+
await pipeline.exec();
|
|
961
|
+
}
|
|
962
|
+
scanAndDelete(client, regExps) {
|
|
963
|
+
return new Promise((resolve, reject) => {
|
|
964
|
+
const stream = client.scanStream({ match: `${this.keyPrefix}*`, count: this.redisScanDeleteCount });
|
|
965
|
+
stream.on("data", (batch) => {
|
|
966
|
+
stream.pause();
|
|
967
|
+
this.deleteBatch(client, batch, regExps).then(() => stream.resume()).catch(reject);
|
|
968
|
+
});
|
|
969
|
+
stream.on("end", resolve);
|
|
970
|
+
stream.on("error", reject);
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* ScanStream keys and batch delete for Redis,
|
|
975
|
+
* iterates over master nodes in case of Cluster.
|
|
976
|
+
*/
|
|
975
977
|
async clearByRegexp(regExps) {
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
return;
|
|
978
|
+
if (this.client instanceof ioredis.Redis) {
|
|
979
|
+
return this.scanAndDelete(this.client, regExps);
|
|
979
980
|
}
|
|
980
|
-
const
|
|
981
|
-
await this.
|
|
981
|
+
const nodes = this.client.nodes("master");
|
|
982
|
+
await Promise.all(nodes.map((node) => this.scanAndDelete(node, regExps)));
|
|
982
983
|
}
|
|
983
984
|
}
|
|
984
985
|
const resolveCacheProvider = (strapi2) => {
|
package/dist/server/index.mjs
CHANGED
|
@@ -3,8 +3,7 @@ import Stream, { Readable } from "stream";
|
|
|
3
3
|
import { createInflate, createBrotliDecompress, createGunzip } from "zlib";
|
|
4
4
|
import rawBody from "raw-body";
|
|
5
5
|
import { LRUCache } from "lru-cache";
|
|
6
|
-
import { Redis
|
|
7
|
-
import { Cluster, Redis } from "iovalkey";
|
|
6
|
+
import { Redis } from "ioredis";
|
|
8
7
|
const loggy = {
|
|
9
8
|
info: (msg) => {
|
|
10
9
|
const shouldDebug = strapi.plugin("strapi-cache").config("debug") ?? false;
|
|
@@ -540,7 +539,8 @@ const config = {
|
|
|
540
539
|
autoPurgeCache: true,
|
|
541
540
|
autoPurgeCacheOnStart: true,
|
|
542
541
|
disableAdminPopups: false,
|
|
543
|
-
disableAdminButtons: false
|
|
542
|
+
disableAdminButtons: false,
|
|
543
|
+
redisScanDeleteCount: 100
|
|
544
544
|
}),
|
|
545
545
|
validator: (config2) => {
|
|
546
546
|
if (typeof config2.debug !== "boolean") {
|
|
@@ -620,6 +620,9 @@ const config = {
|
|
|
620
620
|
if (typeof config2.disableAdminButtons !== "boolean") {
|
|
621
621
|
throw new Error(`Invalid config: disableAdminButtons must be a boolean`);
|
|
622
622
|
}
|
|
623
|
+
if (typeof config2.redisScanDeleteCount !== "number") {
|
|
624
|
+
throw new Error(`Invalid config: redisScanDeleteCount must be a number`);
|
|
625
|
+
}
|
|
623
626
|
}
|
|
624
627
|
};
|
|
625
628
|
const contentTypes = {};
|
|
@@ -852,34 +855,20 @@ class RedisCacheProvider {
|
|
|
852
855
|
this.strapi.plugin("strapi-cache").config("cacheGetTimeoutInMs")
|
|
853
856
|
);
|
|
854
857
|
this.keyPrefix = this.strapi.plugin("strapi-cache").config("redisConfig")?.["keyPrefix"] ?? "";
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
this.client = new Cluster(
|
|
863
|
-
redisClusterNodes,
|
|
864
|
-
clusterOptions
|
|
865
|
-
);
|
|
866
|
-
} else {
|
|
867
|
-
this.client = new Redis(redisConfig);
|
|
858
|
+
this.redisScanDeleteCount = Number(
|
|
859
|
+
this.strapi.plugin("strapi-cache").config("redisScanDeleteCount")
|
|
860
|
+
);
|
|
861
|
+
if (redisClusterNodes.length) {
|
|
862
|
+
const redisClusterOptions = this.strapi.plugin("strapi-cache").config("redisClusterOptions");
|
|
863
|
+
if (!redisClusterOptions["redisOptions"]) {
|
|
864
|
+
redisClusterOptions.redisOptions = redisConfig;
|
|
868
865
|
}
|
|
869
|
-
|
|
866
|
+
this.client = new Redis.Cluster(redisClusterNodes, redisClusterOptions);
|
|
870
867
|
} else {
|
|
871
|
-
|
|
872
|
-
const redisClusterOptions = this.strapi.plugin("strapi-cache").config("redisClusterOptions");
|
|
873
|
-
if (!redisClusterOptions["redisOptions"]) {
|
|
874
|
-
redisClusterOptions.redisOptions = redisConfig;
|
|
875
|
-
}
|
|
876
|
-
this.client = new Redis$1.Cluster(redisClusterNodes, redisClusterOptions);
|
|
877
|
-
} else {
|
|
878
|
-
this.client = new Redis$1(redisConfig);
|
|
879
|
-
}
|
|
880
|
-
loggy.info("Redis provider initialized");
|
|
868
|
+
this.client = new Redis(redisConfig);
|
|
881
869
|
}
|
|
882
870
|
this.initialized = true;
|
|
871
|
+
loggy.info(`${provider === "valkey" ? "Valkey" : "Redis"} provider initialized`);
|
|
883
872
|
} catch (error) {
|
|
884
873
|
loggy.error(error);
|
|
885
874
|
}
|
|
@@ -927,18 +916,6 @@ class RedisCacheProvider {
|
|
|
927
916
|
return null;
|
|
928
917
|
}
|
|
929
918
|
}
|
|
930
|
-
/**
|
|
931
|
-
* Deletes all given keys in Redis pipeline.
|
|
932
|
-
* @param keys to delete from cache
|
|
933
|
-
*/
|
|
934
|
-
async delAll(keys) {
|
|
935
|
-
const pipeline = this.client.pipeline();
|
|
936
|
-
keys.forEach((key) => {
|
|
937
|
-
const relativeKey = key.slice(this.keyPrefix.length);
|
|
938
|
-
pipeline.del(relativeKey);
|
|
939
|
-
});
|
|
940
|
-
await pipeline.exec();
|
|
941
|
-
}
|
|
942
919
|
async keys() {
|
|
943
920
|
if (!this.ready) return null;
|
|
944
921
|
try {
|
|
@@ -968,13 +945,37 @@ class RedisCacheProvider {
|
|
|
968
945
|
return null;
|
|
969
946
|
}
|
|
970
947
|
}
|
|
948
|
+
async deleteBatch(client, batch, regExps) {
|
|
949
|
+
const toDelete = batch.filter((key) => regExps.some((re) => re.test(key)));
|
|
950
|
+
if (toDelete.length === 0) return;
|
|
951
|
+
const pipeline = client.pipeline();
|
|
952
|
+
for (const key of toDelete) {
|
|
953
|
+
const relativeKey = key.startsWith(this.keyPrefix) ? key.slice(this.keyPrefix.length) : key;
|
|
954
|
+
pipeline.del(relativeKey);
|
|
955
|
+
}
|
|
956
|
+
await pipeline.exec();
|
|
957
|
+
}
|
|
958
|
+
scanAndDelete(client, regExps) {
|
|
959
|
+
return new Promise((resolve, reject) => {
|
|
960
|
+
const stream = client.scanStream({ match: `${this.keyPrefix}*`, count: this.redisScanDeleteCount });
|
|
961
|
+
stream.on("data", (batch) => {
|
|
962
|
+
stream.pause();
|
|
963
|
+
this.deleteBatch(client, batch, regExps).then(() => stream.resume()).catch(reject);
|
|
964
|
+
});
|
|
965
|
+
stream.on("end", resolve);
|
|
966
|
+
stream.on("error", reject);
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* ScanStream keys and batch delete for Redis,
|
|
971
|
+
* iterates over master nodes in case of Cluster.
|
|
972
|
+
*/
|
|
971
973
|
async clearByRegexp(regExps) {
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
return;
|
|
974
|
+
if (this.client instanceof Redis) {
|
|
975
|
+
return this.scanAndDelete(this.client, regExps);
|
|
975
976
|
}
|
|
976
|
-
const
|
|
977
|
-
await this.
|
|
977
|
+
const nodes = this.client.nodes("master");
|
|
978
|
+
await Promise.all(nodes.map((node) => this.scanAndDelete(node, regExps)));
|
|
978
979
|
}
|
|
979
980
|
}
|
|
980
981
|
const resolveCacheProvider = (strapi2) => {
|
|
@@ -6,18 +6,20 @@ export declare class RedisCacheProvider implements CacheProvider {
|
|
|
6
6
|
private client;
|
|
7
7
|
private cacheGetTimeoutInMs;
|
|
8
8
|
private keyPrefix;
|
|
9
|
+
private redisScanDeleteCount;
|
|
9
10
|
constructor(strapi: Core.Strapi);
|
|
10
11
|
init(): void;
|
|
11
12
|
get ready(): boolean;
|
|
12
13
|
get(key: string): Promise<any | null>;
|
|
13
14
|
set(key: string, val: any): Promise<any | null>;
|
|
14
15
|
del(key: string): Promise<any | null>;
|
|
15
|
-
/**
|
|
16
|
-
* Deletes all given keys in Redis pipeline.
|
|
17
|
-
* @param keys to delete from cache
|
|
18
|
-
*/
|
|
19
|
-
delAll(keys: string[]): Promise<void>;
|
|
20
16
|
keys(): Promise<string[] | null>;
|
|
21
17
|
reset(): Promise<any | null>;
|
|
18
|
+
private deleteBatch;
|
|
19
|
+
private scanAndDelete;
|
|
20
|
+
/**
|
|
21
|
+
* ScanStream keys and batch delete for Redis,
|
|
22
|
+
* iterates over master nodes in case of Cluster.
|
|
23
|
+
*/
|
|
22
24
|
clearByRegexp(regExps: RegExp[]): Promise<void>;
|
|
23
25
|
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.8.
|
|
2
|
+
"version": "1.8.4",
|
|
3
3
|
"keywords": [
|
|
4
4
|
"strapi cache",
|
|
5
5
|
"strapi rest cache",
|
|
@@ -42,7 +42,6 @@
|
|
|
42
42
|
"@strapi/design-system": "^2.0.1",
|
|
43
43
|
"@strapi/icons": "^2.0.1",
|
|
44
44
|
"ioredis": "^5.6.1",
|
|
45
|
-
"iovalkey": "^0.3.3",
|
|
46
45
|
"lru-cache": "^11.1.0",
|
|
47
46
|
"raw-body": "^3.0.0",
|
|
48
47
|
"react-intl": "^7.1.10"
|