diff --git a/server/src/register.ts b/server/src/register.ts index 4211616..2112f12 100644 --- a/server/src/register.ts +++ b/server/src/register.ts @@ -1,11 +1,9 @@ import type { Core, Schema, UID } from "@strapi/strapi" import { async, sanitize } from "@strapi/utils" -import { omit } from "lodash" import cloneDeep from "lodash/cloneDeep" import has from "lodash/has" import isEmpty from "lodash/isEmpty" -import isEqual from "lodash/isEqual" import unset from "lodash/unset" import { @@ -15,7 +13,6 @@ import { } from "./migrations" import { asBoolean } from "./utils/asBoolean" import log from "./utils/log" -import { majorMinorVersion } from "./utils/version" const populateIsWildcardEquivalent = async ({ strapi, @@ -48,8 +45,7 @@ export async function clearCacheForChangedSchemas(schemas: UID.Schema[]) { }, }) - // TODO: log.debug - log.info(`Deleted ${deleted.count} cached entries due to out of date schema '${schema}'`) + log.debug(`Deleted ${deleted.count} cached entries due to out of date schema '${schema}'`) }) } diff --git a/server/src/services/cache.ts b/server/src/services/cache.ts index 6c98ca2..67571be 100644 --- a/server/src/services/cache.ts +++ b/server/src/services/cache.ts @@ -6,6 +6,7 @@ import isEqual from "lodash/isEqual" import type { PopulateParams } from "./populate" +import { isUniqueConstraintError } from "../utils/isUniqueConstraintError" import log from "../utils/log" import { majorMinorVersion } from "../utils/version" import { getConfig } from "./deep-populate/utils" @@ -43,20 +44,23 @@ export default ({ strapi }: { strapi: Core.Strapi }) => ({ const documentService = strapi.documents("plugin::deep-populate.cache") const hash = getHash(params) - const entry = await documentService.findFirst({ filters: { hash: { $eq: hash } } }) - try { - return entry - ? await documentService.update({ + return await documentService.create({ data: { hash, params, populate, dependencies: dependencies.join(",") } }) + } catch (error: unknown) { + if (isUniqueConstraintError(error)) { + const entry = await documentService.findFirst({ filters: { hash: { $eq: hash } } }) + + if (entry) { + return await documentService.update({ documentId: entry.documentId, data: { populate, dependencies: dependencies.join(",") } as Partial< Modules.Documents.Params.Data.Input<"plugin::deep-populate.cache"> >, }) - : await documentService.create({ data: { hash, params, populate, dependencies: dependencies.join(",") } }) - } catch (error: unknown) { + } + } + log.error("Failed to save cached entry", error) - return } }, async clear(params: PopulateParams) { diff --git a/server/src/utils/isUniqueConstraintError.ts b/server/src/utils/isUniqueConstraintError.ts new file mode 100644 index 0000000..9029efb --- /dev/null +++ b/server/src/utils/isUniqueConstraintError.ts @@ -0,0 +1,29 @@ +const UniqueConstraintErrorCodes = { + // PostgreSQL + POSTGRES_UNIQUE_VIOLATION: "23505", + + // MySQL + MYSQL_DUPLICATE_ENTRY: 1062, + + // SQLite + SQLITE_CONSTRAINT: 19, + SQLITE_CONSTRAINT_UNIQUE: 2067, + + // SQL Server + SQLSERVER_DUPLICATE_KEY: 2601, + SQLSERVER_UNIQUE_KEY_VIOLATION: 2627, +} as const + +export const isUniqueConstraintError = (error: unknown): boolean => { + const err = error as { code?: string; errno?: number; number?: number } + + return ( + Object.keys(UniqueConstraintErrorCodes).includes(err.code) || + err.code === UniqueConstraintErrorCodes.POSTGRES_UNIQUE_VIOLATION || + err.errno === UniqueConstraintErrorCodes.MYSQL_DUPLICATE_ENTRY || + err.errno === UniqueConstraintErrorCodes.SQLITE_CONSTRAINT || + err.errno === UniqueConstraintErrorCodes.SQLITE_CONSTRAINT_UNIQUE || + err.number === UniqueConstraintErrorCodes.SQLSERVER_DUPLICATE_KEY || + err.number === UniqueConstraintErrorCodes.SQLSERVER_UNIQUE_KEY_VIOLATION + ) +}