mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Better debugging
This commit is contained in:
parent
84edde273d
commit
b2ccc1b61e
@ -1,9 +1,9 @@
|
||||
import { getNeode } from '../../../bootstrap/neo4j'
|
||||
import log from './databaseLogger'
|
||||
|
||||
export const undefinedToNullResolver = list => {
|
||||
const resolvers = {}
|
||||
list.forEach(key => {
|
||||
resolvers[key] = async (parent, params, context, resolveInfo) => {
|
||||
resolvers[key] = async parent => {
|
||||
return typeof parent[key] === 'undefined' ? null : parent[key]
|
||||
}
|
||||
})
|
||||
@ -11,7 +11,6 @@ export const undefinedToNullResolver = list => {
|
||||
}
|
||||
|
||||
export default function Resolver(type, options = {}) {
|
||||
const instance = getNeode()
|
||||
const {
|
||||
idAttribute = 'id',
|
||||
undefinedToNull = [],
|
||||
@ -22,32 +21,49 @@ export default function Resolver(type, options = {}) {
|
||||
} = options
|
||||
|
||||
const _hasResolver = (resolvers, { key, connection }, { returnType }) => {
|
||||
return async (parent, params, context, resolveInfo) => {
|
||||
return async (parent, params, { driver, cypherParams }, resolveInfo) => {
|
||||
if (typeof parent[key] !== 'undefined') return parent[key]
|
||||
const id = parent[idAttribute]
|
||||
const statement = `MATCH(:${type} {${idAttribute}: {id}})${connection} RETURN related`
|
||||
const result = await instance.cypher(statement, { id })
|
||||
let response = result.records.map(r => r.get('related').properties)
|
||||
if (returnType === 'object') response = response[0] || null
|
||||
return response
|
||||
const session = driver.session()
|
||||
const readTxResultPromise = session.readTransaction(async txc => {
|
||||
const cypher = `
|
||||
MATCH(:${type} {${idAttribute}: $id})${connection}
|
||||
RETURN related {.*} as related
|
||||
`
|
||||
const result = await txc.run(cypher, { id, cypherParams })
|
||||
log(result)
|
||||
return result.records.map(r => r.get('related'))
|
||||
})
|
||||
try {
|
||||
let response = await readTxResultPromise
|
||||
if (returnType === 'object') response = response[0] || null
|
||||
return response
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const booleanResolver = obj => {
|
||||
const resolvers = {}
|
||||
for (const [key, condition] of Object.entries(obj)) {
|
||||
resolvers[key] = async (parent, params, { cypherParams }, resolveInfo) => {
|
||||
resolvers[key] = async (parent, params, { cypherParams, driver }, resolveInfo) => {
|
||||
if (typeof parent[key] !== 'undefined') return parent[key]
|
||||
const result = await instance.cypher(
|
||||
`
|
||||
${condition.replace('this', 'this {id: $parent.id}')} as ${key}`,
|
||||
{
|
||||
parent,
|
||||
cypherParams,
|
||||
},
|
||||
)
|
||||
const [record] = result.records
|
||||
return record.get(key)
|
||||
const id = parent[idAttribute]
|
||||
const session = driver.session()
|
||||
const readTxResultPromise = session.readTransaction(async txc => {
|
||||
const nodeCondition = condition.replace('this', 'this {id: $id}')
|
||||
const cypher = `${nodeCondition} as ${key}`
|
||||
const result = await txc.run(cypher, { id, cypherParams })
|
||||
log(result)
|
||||
const [response] = result.records.map(r => r.get(key))
|
||||
return response
|
||||
})
|
||||
try {
|
||||
return await readTxResultPromise
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
return resolvers
|
||||
@ -56,16 +72,25 @@ export default function Resolver(type, options = {}) {
|
||||
const countResolver = obj => {
|
||||
const resolvers = {}
|
||||
for (const [key, connection] of Object.entries(obj)) {
|
||||
resolvers[key] = async (parent, params, context, resolveInfo) => {
|
||||
resolvers[key] = async (parent, params, { driver, cypherParams }, resolveInfo) => {
|
||||
if (typeof parent[key] !== 'undefined') return parent[key]
|
||||
const id = parent[idAttribute]
|
||||
const statement = `
|
||||
MATCH(u:${type} {${idAttribute}: {id}})${connection}
|
||||
RETURN COUNT(DISTINCT(related)) as count
|
||||
`
|
||||
const result = await instance.cypher(statement, { id })
|
||||
const [response] = result.records.map(r => r.get('count').toNumber())
|
||||
return response
|
||||
const session = driver.session()
|
||||
const readTxResultPromise = session.readTransaction(async txc => {
|
||||
const id = parent[idAttribute]
|
||||
const cypher = `
|
||||
MATCH(u:${type} {${idAttribute}: $id})${connection}
|
||||
RETURN COUNT(DISTINCT(related)) as count
|
||||
`
|
||||
const result = await txc.run(cypher, { id, cypherParams })
|
||||
log(result)
|
||||
const [response] = result.records.map(r => r.get('count').toNumber())
|
||||
return response
|
||||
})
|
||||
try {
|
||||
return await readTxResultPromise
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
return resolvers
|
||||
|
||||
15
backend/src/schema/resolvers/helpers/databaseLogger.js
Normal file
15
backend/src/schema/resolvers/helpers/databaseLogger.js
Normal file
@ -0,0 +1,15 @@
|
||||
import Debug from 'debug'
|
||||
const debugCypher = Debug('human-connection:neo4j:cypher')
|
||||
const debugStats = Debug('human-connection:neo4j:stats')
|
||||
|
||||
export default function log(response) {
|
||||
const { statement, counters, resultConsumedAfter, resultAvailableAfter } = response.summary
|
||||
const { text, parameters } = statement
|
||||
debugCypher('%s', text)
|
||||
debugCypher('%o', parameters)
|
||||
debugStats('%o', counters)
|
||||
debugStats('%o', {
|
||||
resultConsumedAfter: resultConsumedAfter.toNumber(),
|
||||
resultAvailableAfter: resultAvailableAfter.toNumber(),
|
||||
})
|
||||
}
|
||||
@ -1,3 +1,5 @@
|
||||
import log from './helpers/databaseLogger'
|
||||
|
||||
const transformReturnType = record => {
|
||||
return {
|
||||
...record.get('report').properties,
|
||||
@ -16,8 +18,7 @@ export default {
|
||||
const { driver, user } = context
|
||||
const session = driver.session()
|
||||
const reportWriteTxResultPromise = session.writeTransaction(async txc => {
|
||||
const reportTransactionResponse = await txc.run(
|
||||
`
|
||||
const cypher = `
|
||||
MATCH (submitter:User {id: $submitterId})
|
||||
MATCH (resource {id: $resourceId})
|
||||
WHERE resource:User OR resource:Post OR resource:Comment
|
||||
@ -27,15 +28,16 @@ export default {
|
||||
CREATE (report)<-[filed:FILED {createdAt: $createdAt, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription}]-(submitter)
|
||||
|
||||
RETURN report, resource, labels(resource)[0] AS type
|
||||
`,
|
||||
{
|
||||
resourceId,
|
||||
submitterId: user.id,
|
||||
createdAt: new Date().toISOString(),
|
||||
reasonCategory,
|
||||
reasonDescription,
|
||||
},
|
||||
)
|
||||
`
|
||||
const params = {
|
||||
resourceId,
|
||||
submitterId: user.id,
|
||||
createdAt: new Date().toISOString(),
|
||||
reasonCategory,
|
||||
reasonDescription,
|
||||
}
|
||||
const reportTransactionResponse = await txc.run(cypher, params)
|
||||
log(reportTransactionResponse)
|
||||
return reportTransactionResponse.records.map(transformReturnType)
|
||||
})
|
||||
try {
|
||||
@ -82,24 +84,24 @@ export default {
|
||||
const limit = params.first && typeof params.first === 'number' ? `LIMIT ${params.first}` : ''
|
||||
|
||||
const reportReadTxPromise = session.readTransaction(async tx => {
|
||||
const allReportsTransactionResponse = await tx.run(
|
||||
`
|
||||
MATCH (report:Report)-[:BELONGS_TO]->(resource)
|
||||
WHERE (resource:User OR resource:Post OR resource:Comment)
|
||||
${filterClause}
|
||||
WITH report, resource,
|
||||
[(submitter:User)-[filed:FILED]->(report) | filed {.*, submitter: properties(submitter)} ] as filed,
|
||||
[(moderator:User)-[reviewed:REVIEWED]->(report) | reviewed {.*, moderator: properties(moderator)} ] as reviewed,
|
||||
[(resource)<-[:WROTE]-(author:User) | author {.*} ] as optionalAuthors,
|
||||
[(resource)-[:COMMENTS]->(post:Post) | post {.*} ] as optionalCommentedPosts,
|
||||
resource {.*, __typename: labels(resource)[0] } as resourceWithType
|
||||
WITH report, optionalAuthors, optionalCommentedPosts, reviewed, filed,
|
||||
resourceWithType {.*, post: optionalCommentedPosts[0], author: optionalAuthors[0] } as finalResource
|
||||
RETURN report {.*, resource: finalResource, filed: filed, reviewed: reviewed }
|
||||
${orderByClause}
|
||||
${offset} ${limit}
|
||||
`,
|
||||
)
|
||||
const cypher = `
|
||||
MATCH (report:Report)-[:BELONGS_TO]->(resource)
|
||||
WHERE (resource:User OR resource:Post OR resource:Comment)
|
||||
${filterClause}
|
||||
WITH report, resource,
|
||||
[(submitter:User)-[filed:FILED]->(report) | filed {.*, submitter: properties(submitter)} ] as filed,
|
||||
[(moderator:User)-[reviewed:REVIEWED]->(report) | reviewed {.*, moderator: properties(moderator)} ] as reviewed,
|
||||
[(resource)<-[:WROTE]-(author:User) | author {.*} ] as optionalAuthors,
|
||||
[(resource)-[:COMMENTS]->(post:Post) | post {.*} ] as optionalCommentedPosts,
|
||||
resource {.*, __typename: labels(resource)[0] } as resourceWithType
|
||||
WITH report, optionalAuthors, optionalCommentedPosts, reviewed, filed,
|
||||
resourceWithType {.*, post: optionalCommentedPosts[0], author: optionalAuthors[0] } as finalResource
|
||||
RETURN report {.*, resource: finalResource, filed: filed, reviewed: reviewed }
|
||||
${orderByClause}
|
||||
${offset} ${limit}
|
||||
`
|
||||
const allReportsTransactionResponse = await tx.run(cypher)
|
||||
log(allReportsTransactionResponse)
|
||||
return allReportsTransactionResponse.records.map(record => record.get('report'))
|
||||
})
|
||||
try {
|
||||
@ -119,13 +121,13 @@ export default {
|
||||
const { id } = parent
|
||||
let filed
|
||||
const readTxPromise = session.readTransaction(async tx => {
|
||||
const allReportsTransactionResponse = await tx.run(
|
||||
`
|
||||
const cypher = `
|
||||
MATCH (submitter:User)-[filed:FILED]->(report:Report {id: $id})
|
||||
RETURN filed, submitter
|
||||
`,
|
||||
{ id },
|
||||
)
|
||||
`
|
||||
const params = { id }
|
||||
const allReportsTransactionResponse = await tx.run(cypher, params)
|
||||
log(allReportsTransactionResponse)
|
||||
return allReportsTransactionResponse.records.map(record => ({
|
||||
submitter: record.get('submitter').properties,
|
||||
filed: record.get('filed').properties,
|
||||
@ -153,14 +155,14 @@ export default {
|
||||
const { id } = parent
|
||||
let reviewed
|
||||
const readTxPromise = session.readTransaction(async tx => {
|
||||
const allReportsTransactionResponse = await tx.run(
|
||||
`
|
||||
MATCH (resource)<-[:BELONGS_TO]-(report:Report {id: $id})<-[review:REVIEWED]-(moderator:User)
|
||||
RETURN moderator, review
|
||||
ORDER BY report.updatedAt DESC, review.updatedAt DESC
|
||||
`,
|
||||
{ id },
|
||||
)
|
||||
const cypher = `
|
||||
MATCH (resource)<-[:BELONGS_TO]-(report:Report {id: $id})<-[review:REVIEWED]-(moderator:User)
|
||||
RETURN moderator, review
|
||||
ORDER BY report.updatedAt DESC, review.updatedAt DESC
|
||||
`
|
||||
const params = { id }
|
||||
const allReportsTransactionResponse = await tx.run(cypher, params)
|
||||
log(allReportsTransactionResponse)
|
||||
return allReportsTransactionResponse.records.map(record => ({
|
||||
review: record.get('review').properties,
|
||||
moderator: record.get('moderator').properties,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user