Merged in fix/delete-fuzzy (pull request #1538)
Support for delete keys fuzzy * Support for delete keys fuzzy * Added some logs Approved-by: Anton Gunnarsson
This commit is contained in:
@@ -7,87 +7,108 @@ const MIN_LENGTH = 1;
|
|||||||
const QUERY_TYPE = t.Object({ key: t.String({ minLength: MIN_LENGTH }) });
|
const QUERY_TYPE = t.Object({ key: t.String({ minLength: MIN_LENGTH }) });
|
||||||
|
|
||||||
export const cacheRoutes = new Elysia({ prefix: "/cache" })
|
export const cacheRoutes = new Elysia({ prefix: "/cache" })
|
||||||
.get(
|
.get(
|
||||||
"/",
|
"/",
|
||||||
async ({ query: { key }, error }) => {
|
async ({ query: { key }, error }) => {
|
||||||
key = validateKey(key);
|
key = validateKey(key);
|
||||||
console.log("GET /cache", key);
|
console.log("GET /cache", key);
|
||||||
|
|
||||||
const value = await redis.get(key);
|
const value = await redis.get(key);
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return error("Not Found", "Not Found");
|
return error("Not Found", "Not Found");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const output = JSON.parse(value);
|
const output = JSON.parse(value);
|
||||||
return { data: output };
|
return { data: output };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
redis.del(key);
|
redis.del(key);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
query: QUERY_TYPE,
|
query: QUERY_TYPE,
|
||||||
response: { 200: t.Object({ data: t.Any() }), 404: t.String() },
|
response: { 200: t.Object({ data: t.Any() }), 404: t.String() },
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.put(
|
.put(
|
||||||
"/",
|
"/",
|
||||||
async ({ query: { key }, body, error, set }) => {
|
async ({ query: { key }, body, error, set }) => {
|
||||||
key = validateKey(key);
|
key = validateKey(key);
|
||||||
console.log("PUT /cache", key);
|
console.log("PUT /cache", key);
|
||||||
|
|
||||||
if (!body.ttl || body.ttl < 0) {
|
if (!body.ttl || body.ttl < 0) {
|
||||||
return error("Bad Request", "ttl is required");
|
return error("Bad Request", "ttl is required");
|
||||||
}
|
}
|
||||||
|
|
||||||
await redis.set(key, JSON.stringify(body.data), "EX", body.ttl);
|
await redis.set(key, JSON.stringify(body.data), "EX", body.ttl);
|
||||||
|
|
||||||
set.status = 204;
|
set.status = 204;
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
body: t.Object({ data: t.Any(), ttl: t.Number() }),
|
body: t.Object({ data: t.Any(), ttl: t.Number() }),
|
||||||
query: QUERY_TYPE,
|
query: QUERY_TYPE,
|
||||||
response: { 204: t.Void(), 400: t.String() },
|
response: { 204: t.Void(), 400: t.String() },
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.delete(
|
.delete(
|
||||||
"/",
|
"/",
|
||||||
async ({ query: { key, fuzzy }, set }) => {
|
async ({ query: { key, fuzzy }, set }) => {
|
||||||
key = validateKey(key);
|
key = validateKey(key);
|
||||||
console.log("DELETE /cache", key);
|
console.log("DELETE /cache", key, { fuzzy });
|
||||||
|
|
||||||
if (fuzzy) {
|
if (fuzzy) {
|
||||||
key = `*${key}*`;
|
await deleteWithPattern(`*${key}*`);
|
||||||
}
|
} else {
|
||||||
|
await redis.del(key);
|
||||||
|
console.log("Deleted key: ", key);
|
||||||
|
}
|
||||||
|
|
||||||
await redis.del(key);
|
set.status = 204;
|
||||||
|
return;
|
||||||
set.status = 204;
|
},
|
||||||
return;
|
{
|
||||||
},
|
query: t.Object({
|
||||||
{
|
...QUERY_TYPE.properties,
|
||||||
query: t.Object({
|
...t.Object({ fuzzy: t.Optional(t.Boolean()) }).properties,
|
||||||
...QUERY_TYPE.properties,
|
}),
|
||||||
...t.Object({ fuzzy: t.Optional(t.Boolean()) }).properties,
|
response: { 204: t.Void(), 400: t.String() },
|
||||||
}),
|
}
|
||||||
response: { 204: t.Void(), 400: t.String() },
|
);
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function validateKey(key: string) {
|
function validateKey(key: string) {
|
||||||
const parsedKey = decodeURIComponent(key);
|
const parsedKey = decodeURIComponent(key);
|
||||||
|
|
||||||
if (parsedKey.length < MIN_LENGTH) {
|
if (parsedKey.length < MIN_LENGTH) {
|
||||||
throw new ModelValidationError(
|
throw new ModelValidationError("Key has to be atleast 1 character long");
|
||||||
"Key has to be atleast 1 character long"
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parsedKey.includes("*")) {
|
if (parsedKey.includes("*")) {
|
||||||
throw new ModelValidationError("Key cannot contain wildcards");
|
throw new ModelValidationError("Key cannot contain wildcards");
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsedKey;
|
return parsedKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteWithPattern(pattern: string) {
|
||||||
|
let cursor = "0";
|
||||||
|
let keys: string[] = [];
|
||||||
|
|
||||||
|
do {
|
||||||
|
const [newCursor, foundKeys] = await redis.scan(
|
||||||
|
cursor,
|
||||||
|
"MATCH",
|
||||||
|
pattern,
|
||||||
|
"COUNT",
|
||||||
|
5000
|
||||||
|
);
|
||||||
|
cursor = newCursor;
|
||||||
|
keys.push(...foundKeys);
|
||||||
|
} while (cursor !== "0");
|
||||||
|
|
||||||
|
if (keys.length > 0) {
|
||||||
|
await redis.del(...keys);
|
||||||
|
}
|
||||||
|
console.log("Deleted number of keys: ", keys.length);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user