Skip to content

Commit

Permalink
Drop p-limit internally (#8809)
Browse files Browse the repository at this point in the history
  • Loading branch information
dcousens authored Feb 14, 2024
1 parent 1ed8e2e commit c0dacbf
Show file tree
Hide file tree
Showing 32 changed files with 387 additions and 17,295 deletions.
5 changes: 5 additions & 0 deletions .changeset/boolean-not-false.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
----
'@keystone-6/auth': core
----

Fix `defaultIsFilterable` and `defaultIsOrderable` types blocking `true` values
5 changes: 5 additions & 0 deletions .changeset/less-plimit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
----
'@keystone-6/core': patch
----

Fix global locking by dropping global `p-limit` on `context.query`/`context.db`
5 changes: 1 addition & 4 deletions .github/workflows/tests_api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ jobs:
- name: Unit tests
run: pnpm jest --ci --runInBand --shard=${{ matrix.index }}/9 api-tests --testPathIgnorePatterns=tests/api-tests/fields/crud
env:
TEST_ADAPTER: postgresql
DATABASE_URL: postgres://testuser:testpass@localhost:5432/test_db

graphql_api_tests_sqlite:
Expand All @@ -55,15 +54,14 @@ jobs:
- name: Unit tests
run: pnpm jest --ci --runInBand --shard=${{ matrix.index }}/9 api-tests --testPathIgnorePatterns=tests/api-tests/fields/crud
env:
TEST_ADAPTER: sqlite
DATABASE_URL: file:./file.db

graphql_api_tests_mysql:
name: API Tests MySQL
runs-on: ubuntu-latest
services:
mysql:
image: mariadb:11.2
# we use the root user because our tests create databases
env:
MYSQL_ROOT_PASSWORD: testpass
ports:
Expand All @@ -79,7 +77,6 @@ jobs:
- name: Unit tests
run: pnpm jest --ci --runInBand --shard=${{ matrix.index }}/9 api-tests --testPathIgnorePatterns=tests/api-tests/fields/crud
env:
TEST_ADAPTER: mysql
DATABASE_URL: mysql://root:testpass@localhost:3306/test_db

field_crud_tests_postgresql:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ jobs:
- uses: ./.github/actions/ci-setup

- name: Unit tests
run: pnpm jest --ci --runInBand --testPathIgnorePatterns=admin-ui-tests --testPathIgnorePatterns=api-tests --testPathIgnorePatterns=examples-smoke-tests --testPathIgnorePatterns=examples/testing
run: DATABASE_URL=file:./test.db pnpm jest --ci --runInBand --testPathIgnorePatterns=admin-ui-tests --testPathIgnorePatterns=api-tests --testPathIgnorePatterns=examples-smoke-tests --testPathIgnorePatterns=examples/testing
1 change: 0 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@
"intersection-observer": "^0.12.0",
"meow": "^9.0.0",
"next": "^13.3.0",
"p-limit": "^2.3.0",
"pluralize": "^8.0.0",
"prisma": "4.16.2",
"prompts": "^2.4.2",
Expand Down
19 changes: 0 additions & 19 deletions packages/core/src/lib/core/graphql-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,6 @@ export const userInputError = (msg: string) =>
export const accessDeniedError = (msg: string) =>
new GraphQLError(`Access denied: ${msg}`, { extensions: { code: 'KS_ACCESS_DENIED' } })

export const prismaError = (err: Error) => {
if ((err as any).code === undefined) {
return new GraphQLError(`Prisma error`, {
extensions: {
code: 'KS_PRISMA_ERROR',
debug: {
message: err.message,
},
},
})
}
return new GraphQLError(`Prisma error: ${err.message.split('\n').slice(-1)[0].trim()}`, {
extensions: {
code: 'KS_PRISMA_ERROR',
prisma: { ...err },
},
})
}

export const validationFailureError = (messages: string[]) => {
const s = messages.map(m => ` - ${m}`).join('\n')
return new GraphQLError(`You provided invalid data for this operation.\n${s}`, {
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/lib/core/mutations/access-control.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { BaseItem, KeystoneContext } from '../../../types'
import { accessDeniedError, accessReturnError, extensionError } from '../graphql-errors'
import { mapUniqueWhereToWhere } from '../queries/resolvers'
import type { InitialisedList } from '../initialise-lists'
import { runWithPrisma } from '../utils'
import { cannotForItem, cannotForItemFields } from '../access-control'
import {
type InputFilter,
Expand Down Expand Up @@ -30,7 +29,7 @@ async function getFilteredItem (
where = { AND: [where, await resolveWhereInput(accessFilters, list, context)] }
}

const item = await runWithPrisma(context, list, model => model.findFirst({ where }))
const item = await context.prisma[list.listKey].findFirst({ where })
if (item !== null) return item

throw accessDeniedError(cannotForItem(operation, list))
Expand Down
21 changes: 7 additions & 14 deletions packages/core/src/lib/core/mutations/create-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import {
promiseAllRejectWithAllErrors,
getDBFieldKeyForFieldOnMultiField,
type IdType,
runWithPrisma,
getWriteLimit,
getPrismaNamespace,
} from '../utils'
import { type InputFilter, resolveUniqueWhereInput, type UniqueInputFilter } from '../where-inputs'
Expand Down Expand Up @@ -46,13 +44,9 @@ async function createSingle (
undefined
)

const writeLimit = getWriteLimit(context)

const item = await writeLimit(() =>
runWithPrisma(context, list, model =>
model.create({ data: list.isSingleton ? { ...data, id: 1 } : data })
)
)
const item = await context.prisma[list.listKey].create({
data: list.isSingleton ? { ...data, id: 1 } : data
})

return { item, afterOperation }
}
Expand Down Expand Up @@ -143,11 +137,10 @@ async function updateSingle (
item
)

const writeLimit = getWriteLimit(context)

const updatedItem = await writeLimit(() =>
runWithPrisma(context, list, model => model.update({ where: { id: item.id }, data }))
)
const updatedItem = await context.prisma[list.listKey].update({
where: { id: item.id },
data,
})

// after operation
await afterOperation(updatedItem)
Expand Down
10 changes: 3 additions & 7 deletions packages/core/src/lib/core/mutations/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { cannotForItem, getOperationAccess, getAccessFilters } from '../access-c
import { checkFilterOrderAccess } from '../filter-order-access'
import { accessDeniedError } from '../graphql-errors'
import type { InitialisedList } from '../initialise-lists'
import { getWriteLimit, runWithPrisma } from '../utils'
import { type InputFilter, resolveUniqueWhereInput, type UniqueInputFilter } from '../where-inputs'
import { getAccessControlledItemForDelete } from './access-control'
import { runSideEffectOnlyHook } from './hooks'
Expand Down Expand Up @@ -40,11 +39,8 @@ async function deleteSingle (
// before operation
await runSideEffectOnlyHook(list, 'beforeOperation', hookArgs)

const writeLimit = getWriteLimit(context)

const newItem = await writeLimit(() =>
runWithPrisma(context, list, model => model.delete({ where: { id: item.id } }))
)
// operation
const result = await context.prisma[list.listKey].delete({ where: { id: item.id } })

// after operation
await runSideEffectOnlyHook(list, 'afterOperation', {
Expand All @@ -53,7 +49,7 @@ async function deleteSingle (
originalItem: item,
})

return newItem
return result
}

export async function deleteMany (
Expand Down
29 changes: 12 additions & 17 deletions packages/core/src/lib/core/prisma-schema-printer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function printIndex (fieldPath: string, index: undefined | 'index' | 'unique') {
none: '',
unique: '@unique',
index: `\n@@index([${fieldPath}])`,
}[index || ('none' as const)]
}[index ?? ('none' as const)]
}

function printNativeType (nativeType: string | undefined, datasourceName: string) {
Expand Down Expand Up @@ -59,16 +59,16 @@ function printField (
const defaultValue = field.default ? printScalarDefaultValue(field.default) : ''
const map = field.map ? ` @map(${JSON.stringify(field.map)})` : ''
const updatedAt = field.updatedAt ? ' @updatedAt' : ''
return `${fieldPath} ${field.scalar}${
modifiers[field.mode]
}${updatedAt}${nativeType}${defaultValue}${map}${index}`
return `${fieldPath} ${field.scalar}${modifiers[field.mode]}${updatedAt}${nativeType}${defaultValue}${map}${index}`
}

if (field.kind === 'enum') {
const index = printIndex(fieldPath, field.index)
const defaultValue = field.default ? ` @default(${field.default.value})` : ''
const map = field.map ? ` @map(${JSON.stringify(field.map)})` : ''
return `${fieldPath} ${field.name}${modifiers[field.mode]}${defaultValue}${map}${index}`
}

if (field.kind === 'multi') {
return Object.entries(field.fields)
.map(([subField, field]) =>
Expand All @@ -81,13 +81,11 @@ function printField (
)
.join('\n')
}

if (field.kind === 'relation') {
if (field.mode === 'many') {
return `${fieldPath} ${field.list}[] @relation("${field.relationName}")`
}
if (field.foreignIdField.kind === 'none') {
return `${fieldPath} ${field.list}? @relation("${field.relationName}")`
}
if (field.mode === 'many') return `${fieldPath} ${field.list}[] @relation("${field.relationName}")`
if (field.foreignIdField.kind === 'none') return `${fieldPath} ${field.list}? @relation("${field.relationName}")`

const relationIdFieldPath = `${fieldPath}Id`
const relationField = `${fieldPath} ${field.list}? @relation("${field.relationName}", fields: [${relationIdFieldPath}], references: [id])`

Expand All @@ -96,13 +94,10 @@ function printField (

assertDbFieldIsValidForIdField(foreignList.listKey, foreignList.isSingleton, foreignIdField)
const nativeType = printNativeType(foreignIdField.nativeType, datasourceName)
const index = printIndex(
relationIdFieldPath,
field.foreignIdField.kind === 'owned' ? 'index' : 'unique'
)
const relationIdField = `${relationIdFieldPath} ${foreignIdField.scalar}? @map(${JSON.stringify(
field.foreignIdField.map
)}) ${nativeType}${index}`

const foreignIndex = field.foreignIdField.kind === 'owned' ? 'index' : 'unique'
const index = printIndex(relationIdFieldPath, foreignIndex)
const relationIdField = `${relationIdFieldPath} ${foreignIdField.scalar}? @map(${JSON.stringify(field.foreignIdField.map)}) ${nativeType}${index}`
return `${relationField}\n${relationIdField}`
}
// TypeScript's control flow analysis doesn't understand that this will never happen without the assertNever
Expand Down
12 changes: 3 additions & 9 deletions packages/core/src/lib/core/queries/output-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { graphql } from '../../..'
import { getOperationAccess, getAccessFilters } from '../access-control'
import type { ResolvedDBField, ResolvedRelationDBField } from '../resolve-relationships'
import type { InitialisedList } from '../initialise-lists'
import { type IdType, getDBFieldKeyForFieldOnMultiField, runWithPrisma } from '../utils'
import { type IdType, getDBFieldKeyForFieldOnMultiField } from '../utils'
import { accessReturnError, extensionError } from '../graphql-errors'
import { accessControlledFilter } from './resolvers'
import * as queries from './resolvers'
Expand Down Expand Up @@ -117,14 +117,8 @@ async function fetchRelatedItems (
accessFilters
)

const results = await runWithPrisma(context, foreignList, model =>
model.findMany({
where: resolvedWhere,
})
)

const resultsById = new Map(results.map(x => [x[idFieldKey], x]))

const results = await context.prisma[foreignList.listKey].findMany({ where: resolvedWhere })
const resultsById = new Map(results.map((x: any) => [x[idFieldKey], x]))
return toFetch.map(id => resultsById.get(id))
}

Expand Down
44 changes: 23 additions & 21 deletions packages/core/src/lib/core/queries/resolvers.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import { maybeCacheControlFromInfo } from '@apollo/cache-control-types'
import type { GraphQLResolveInfo } from 'graphql'
import type { FindManyArgsValue, BaseItem, KeystoneContext, OrderDirection } from '../../../types'
import { GraphQLResolveInfo } from 'graphql'
import {
type BaseItem,
type FindManyArgsValue,
type KeystoneContext,
type OrderDirection
} from '../../../types'
import { getOperationAccess, getAccessFilters } from '../access-control'
import {
type PrismaFilter,
type UniquePrismaFilter,
resolveUniqueWhereInput,
resolveWhereInput,
type UniqueInputFilter,
type InputFilter,
resolveUniqueWhereInput,
resolveWhereInput,
} from '../where-inputs'
import { limitsExceededError, userInputError } from '../graphql-errors'
import type { InitialisedList } from '../initialise-lists'
import { getDBFieldKeyForFieldOnMultiField, runWithPrisma } from '../utils'
import { type InitialisedList } from '../initialise-lists'
import { getDBFieldKeyForFieldOnMultiField } from '../utils'
import { checkFilterOrderAccess } from '../filter-order-access'

// we want to put the value we get back from the field's unique where resolver into an equals
Expand Down Expand Up @@ -93,7 +98,7 @@ export async function findOne (
// apply access control
const filter = await accessControlledFilter(list, context, resolvedWhere, accessFilters)

return runWithPrisma(context, list, model => model.findFirst({ where: filter }))
return await context.prisma[list.listKey].findFirst({ where: filter })
}

export async function findMany (
Expand Down Expand Up @@ -124,15 +129,13 @@ export async function findMany (

const filter = await accessControlledFilter(list, context, resolvedWhere, accessFilters)

const results = await runWithPrisma(context, list, model =>
model.findMany({
where: extraFilter === undefined ? filter : { AND: [filter, extraFilter] },
orderBy,
take: take ?? undefined,
skip,
cursor: cursor ?? undefined,
})
)
const results = await context.prisma[list.listKey].findMany({
where: extraFilter === undefined ? filter : { AND: [filter, extraFilter] },
orderBy,
take: take ?? undefined,
skip,
cursor: cursor ?? undefined,
})

if (list.cacheHint) {
maybeCacheControlFromInfo(info)?.setCacheHint(
Expand Down Expand Up @@ -218,11 +221,10 @@ export async function count (

const filter = await accessControlledFilter(list, context, resolvedWhere, accessFilters)

const count = await runWithPrisma(context, list, model =>
model.count({
where: extraFilter === undefined ? filter : { AND: [filter, extraFilter] },
})
)
const count = await context.prisma[list.listKey].count({
where: extraFilter === undefined ? filter : { AND: [filter, extraFilter] },
})

if (list.cacheHint) {
maybeCacheControlFromInfo(info)?.setCacheHint(
list.cacheHint({
Expand Down
11 changes: 3 additions & 8 deletions packages/core/src/lib/core/resolve-relationships.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ type BaseResolvedRelationDBField = {
}

export type ResolvedRelationDBField =
| (BaseResolvedRelationDBField & {
mode: 'many'
})
| (BaseResolvedRelationDBField & { mode: 'many' })
| (BaseResolvedRelationDBField & {
mode: 'one'
foreignIdField: { kind: 'none' } | { kind: 'owned' | 'owned-unique', map: string }
Expand Down Expand Up @@ -181,8 +179,7 @@ export function resolveRelationships (
continue
}
if (leftRel.field.mode === 'many' && rightRel.field.mode === 'many') {
const relationName =
leftRel.field.relationName ?? `${leftRel.listKey}_${leftRel.fieldPath}`
const relationName = leftRel.field.relationName ?? `${leftRel.listKey}_${leftRel.fieldPath}`
resolvedLists[leftRel.listKey][leftRel.fieldPath] = {
kind: 'relation',
mode: 'many',
Expand Down Expand Up @@ -229,9 +226,7 @@ export function resolveRelationships (
}
const foreignFieldPath = `from_${listKey}_${fieldPath}`
if (foreignUnresolvedList.fields[foreignFieldPath]) {
throw new Error(
`The relationship field at ${listKey}.${fieldPath} points to the list ${field.list}, Keystone needs to a create a relationship field at ${field.list}.${foreignFieldPath} to support the relationship at ${listKey}.${fieldPath} but ${field.list} already has a field named ${foreignFieldPath}`
)
throw new Error(`The relationship field at ${listKey}.${fieldPath} points to the list ${field.list}, Keystone needs to a create a relationship field at ${field.list}.${foreignFieldPath} to support the relationship at ${listKey}.${fieldPath} but ${field.list} already has a field named ${foreignFieldPath}`)
}

if (field.mode === 'many') {
Expand Down
Loading

0 comments on commit c0dacbf

Please sign in to comment.