Compare commits
No commits in common. "63e60fe2bc0fe18b620f2410078fe667e53156f0" and "6e1d67b3c0b880774940f33b3d0a8b1597448767" have entirely different histories.
63e60fe2bc
...
6e1d67b3c0
@ -1,6 +1,3 @@
|
|||||||
PRISMA_SLOW_LOGS_MS=
|
|
||||||
GRAPHQL_SLOW_LOGS_MS=
|
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
# OPTIONAL SECRETS #
|
# OPTIONAL SECRETS #
|
||||||
# put these in .env.local, and don't commit them to git #
|
# put these in .env.local, and don't commit them to git #
|
||||||
|
@ -17,5 +17,3 @@ NEXT_PUBLIC_LONG_POLL_INTERVAL=60000
|
|||||||
NEXT_PUBLIC_EXTRA_LONG_POLL_INTERVAL=300000
|
NEXT_PUBLIC_EXTRA_LONG_POLL_INTERVAL=300000
|
||||||
NEXT_PUBLIC_URL=https://stacker.news
|
NEXT_PUBLIC_URL=https://stacker.news
|
||||||
TOR_PROXY=http://127.0.0.1:7050/
|
TOR_PROXY=http://127.0.0.1:7050/
|
||||||
PRISMA_SLOW_LOGS_MS=50
|
|
||||||
GRAPHQL_SLOW_LOGS_MS=50
|
|
@ -6,7 +6,7 @@ const prisma = global.prisma || (() => {
|
|||||||
log: [{ level: 'query', emit: 'event' }, 'warn', 'error']
|
log: [{ level: 'query', emit: 'event' }, 'warn', 'error']
|
||||||
})
|
})
|
||||||
prisma.$on('query', (e) => {
|
prisma.$on('query', (e) => {
|
||||||
if (process.env.PRISMA_SLOW_LOGS_MS && e.duration > process.env.PRISMA_SLOW_LOGS_MS) {
|
if (e.duration > 50) {
|
||||||
console.log('Query: ' + e.query)
|
console.log('Query: ' + e.query)
|
||||||
console.log('Params: ' + e.params)
|
console.log('Params: ' + e.params)
|
||||||
console.log('Duration: ' + e.duration + 'ms')
|
console.log('Duration: ' + e.duration + 'ms')
|
||||||
|
@ -130,11 +130,9 @@ async function performOptimisticAction (actionType, args, context) {
|
|||||||
const { models } = context
|
const { models } = context
|
||||||
const action = paidActions[actionType]
|
const action = paidActions[actionType]
|
||||||
|
|
||||||
context.optimistic = true
|
|
||||||
context.lndInvoice = await createLndInvoice(actionType, args, context)
|
|
||||||
|
|
||||||
return await models.$transaction(async tx => {
|
return await models.$transaction(async tx => {
|
||||||
context.tx = tx
|
context.tx = tx
|
||||||
|
context.optimistic = true
|
||||||
|
|
||||||
const invoice = await createDbInvoice(actionType, args, context)
|
const invoice = await createDbInvoice(actionType, args, context)
|
||||||
|
|
||||||
@ -162,20 +160,15 @@ async function performPessimisticAction (actionType, args, context) {
|
|||||||
const invoice = await verifyPayment(context)
|
const invoice = await verifyPayment(context)
|
||||||
args.invoiceId = invoice.id
|
args.invoiceId = invoice.id
|
||||||
|
|
||||||
// make sure to perform before settling so we don't race with worker to onPaid
|
|
||||||
const result = await action.perform(args, context)
|
|
||||||
|
|
||||||
// XXX this might cause the interactive tx to time out
|
|
||||||
await settleHodlInvoice({ secret: invoice.preimage, lnd })
|
await settleHodlInvoice({ secret: invoice.preimage, lnd })
|
||||||
|
|
||||||
return {
|
return {
|
||||||
result,
|
result: await action.perform(args, context),
|
||||||
paymentMethod: 'PESSIMISTIC'
|
paymentMethod: 'PESSIMISTIC'
|
||||||
}
|
}
|
||||||
}, { isolationLevel: Prisma.TransactionIsolationLevel.ReadCommitted })
|
}, { isolationLevel: Prisma.TransactionIsolationLevel.ReadCommitted })
|
||||||
} else {
|
} else {
|
||||||
// just create the invoice and complete action when it's paid
|
// just create the invoice and complete action when it's paid
|
||||||
context.lndInvoice = await createLndInvoice(actionType, args, context)
|
|
||||||
return {
|
return {
|
||||||
invoice: await createDbInvoice(actionType, args, context),
|
invoice: await createDbInvoice(actionType, args, context),
|
||||||
paymentMethod: 'PESSIMISTIC'
|
paymentMethod: 'PESSIMISTIC'
|
||||||
@ -208,18 +201,13 @@ export async function retryPaidAction (actionType, args, context) {
|
|||||||
throw new Error(`retryPaidAction - missing invoiceId ${actionType}`)
|
throw new Error(`retryPaidAction - missing invoiceId ${actionType}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
context.optimistic = true
|
|
||||||
context.user = await models.user.findUnique({ where: { id: me.id } })
|
context.user = await models.user.findUnique({ where: { id: me.id } })
|
||||||
|
|
||||||
const { msatsRequested } = await models.invoice.findUnique({ where: { id: invoiceId, actionState: 'FAILED' } })
|
|
||||||
context.cost = BigInt(msatsRequested)
|
|
||||||
context.lndInvoice = await createLndInvoice(actionType, args, context)
|
|
||||||
|
|
||||||
return await models.$transaction(async tx => {
|
return await models.$transaction(async tx => {
|
||||||
context.tx = tx
|
context.tx = tx
|
||||||
|
context.optimistic = true
|
||||||
|
|
||||||
// update the old invoice to RETRYING, so that it's not confused with FAILED
|
// update the old invoice to RETRYING, so that it's not confused with FAILED
|
||||||
const { actionId } = await tx.invoice.update({
|
const { msatsRequested, actionId } = await tx.invoice.update({
|
||||||
where: {
|
where: {
|
||||||
id: invoiceId,
|
id: invoiceId,
|
||||||
actionState: 'FAILED'
|
actionState: 'FAILED'
|
||||||
@ -229,6 +217,7 @@ export async function retryPaidAction (actionType, args, context) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
context.cost = BigInt(msatsRequested)
|
||||||
context.actionId = actionId
|
context.actionId = actionId
|
||||||
|
|
||||||
// create a new invoice
|
// create a new invoice
|
||||||
@ -245,14 +234,13 @@ export async function retryPaidAction (actionType, args, context) {
|
|||||||
const OPTIMISTIC_INVOICE_EXPIRE = { minutes: 10 }
|
const OPTIMISTIC_INVOICE_EXPIRE = { minutes: 10 }
|
||||||
const PESSIMISTIC_INVOICE_EXPIRE = { minutes: 10 }
|
const PESSIMISTIC_INVOICE_EXPIRE = { minutes: 10 }
|
||||||
|
|
||||||
// we seperate the invoice creation into two functions because
|
async function createDbInvoice (actionType, args, context) {
|
||||||
// because if lnd is slow, it'll timeout the interactive tx
|
const { user, models, tx, lnd, cost, optimistic, actionId } = context
|
||||||
async function createLndInvoice (actionType, args, context) {
|
|
||||||
const { user, lnd, cost, optimistic } = context
|
|
||||||
const action = paidActions[actionType]
|
const action = paidActions[actionType]
|
||||||
const [createLNDInvoice, expirePivot] = optimistic
|
const db = tx ?? models
|
||||||
? [createInvoice, OPTIMISTIC_INVOICE_EXPIRE]
|
const [createLNDInvoice, expirePivot, actionState] = optimistic
|
||||||
: [createHodlInvoice, PESSIMISTIC_INVOICE_EXPIRE]
|
? [createInvoice, OPTIMISTIC_INVOICE_EXPIRE, 'PENDING']
|
||||||
|
: [createHodlInvoice, PESSIMISTIC_INVOICE_EXPIRE, 'PENDING_HELD']
|
||||||
|
|
||||||
if (cost < 1000n) {
|
if (cost < 1000n) {
|
||||||
// sanity check
|
// sanity check
|
||||||
@ -260,33 +248,19 @@ async function createLndInvoice (actionType, args, context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const expiresAt = datePivot(new Date(), expirePivot)
|
const expiresAt = datePivot(new Date(), expirePivot)
|
||||||
return await createLNDInvoice({
|
const lndInv = await createLNDInvoice({
|
||||||
description: user?.hideInvoiceDesc ? undefined : await action.describe(args, context),
|
description: user?.hideInvoiceDesc ? undefined : await action.describe(args, context),
|
||||||
lnd,
|
lnd,
|
||||||
mtokens: String(cost),
|
mtokens: String(cost),
|
||||||
expires_at: expiresAt
|
expires_at: expiresAt
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
async function createDbInvoice (actionType, args, context) {
|
|
||||||
const { user, models, tx, lndInvoice, cost, optimistic, actionId } = context
|
|
||||||
const db = tx ?? models
|
|
||||||
const [expirePivot, actionState] = optimistic
|
|
||||||
? [OPTIMISTIC_INVOICE_EXPIRE, 'PENDING']
|
|
||||||
: [PESSIMISTIC_INVOICE_EXPIRE, 'PENDING_HELD']
|
|
||||||
|
|
||||||
if (cost < 1000n) {
|
|
||||||
// sanity check
|
|
||||||
throw new Error('The cost of the action must be at least 1 sat')
|
|
||||||
}
|
|
||||||
|
|
||||||
const expiresAt = datePivot(new Date(), expirePivot)
|
|
||||||
const invoice = await db.invoice.create({
|
const invoice = await db.invoice.create({
|
||||||
data: {
|
data: {
|
||||||
hash: lndInvoice.id,
|
hash: lndInv.id,
|
||||||
msatsRequested: cost,
|
msatsRequested: cost,
|
||||||
preimage: optimistic ? undefined : lndInvoice.secret,
|
preimage: optimistic ? undefined : lndInv.secret,
|
||||||
bolt11: lndInvoice.request,
|
bolt11: lndInv.request,
|
||||||
userId: user?.id || USER_ID.anon,
|
userId: user?.id || USER_ID.anon,
|
||||||
actionType,
|
actionType,
|
||||||
actionState,
|
actionState,
|
||||||
@ -299,7 +273,7 @@ async function createDbInvoice (actionType, args, context) {
|
|||||||
await db.$executeRaw`
|
await db.$executeRaw`
|
||||||
INSERT INTO pgboss.job (name, data, retrylimit, retrybackoff, startafter, expirein, priority)
|
INSERT INTO pgboss.job (name, data, retrylimit, retrybackoff, startafter, expirein, priority)
|
||||||
VALUES ('checkInvoice',
|
VALUES ('checkInvoice',
|
||||||
jsonb_build_object('hash', ${lndInvoice.id}::TEXT), 21, true,
|
jsonb_build_object('hash', ${lndInv.id}::TEXT), 21, true,
|
||||||
${expiresAt}::TIMESTAMP WITH TIME ZONE,
|
${expiresAt}::TIMESTAMP WITH TIME ZONE,
|
||||||
${expiresAt}::TIMESTAMP WITH TIME ZONE - now() + interval '10m', 100)`
|
${expiresAt}::TIMESTAMP WITH TIME ZONE - now() + interval '10m', 100)`
|
||||||
|
|
||||||
|
@ -218,14 +218,14 @@ export async function onPaid ({ invoice, id }, context) {
|
|||||||
FROM ancestors, comment
|
FROM ancestors, comment
|
||||||
WHERE ancestors."userId" <> comment."userId"`
|
WHERE ancestors."userId" <> comment."userId"`
|
||||||
|
|
||||||
notifyItemParents({ item, models }).catch(console.error)
|
notifyItemParents({ item, me: item.userId, models }).catch(console.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const { userId } of item.mentions) {
|
for (const { userId } of item.mentions) {
|
||||||
notifyMention({ models, item, userId }).catch(console.error)
|
notifyMention({ models, item, userId }).catch(console.error)
|
||||||
}
|
}
|
||||||
for (const { refereeItem } of item.itemReferrers) {
|
for (const { referee } of item.itemReferrers) {
|
||||||
notifyItemMention({ models, referrerItem: item, refereeItem }).catch(console.error)
|
notifyItemMention({ models, referrerItem: item, refereeItem: referee }).catch(console.error)
|
||||||
}
|
}
|
||||||
notifyUserSubscribers({ models, item }).catch(console.error)
|
notifyUserSubscribers({ models, item }).catch(console.error)
|
||||||
notifyTerritorySubscribers({ models, item }).catch(console.error)
|
notifyTerritorySubscribers({ models, item }).catch(console.error)
|
||||||
|
@ -133,13 +133,13 @@ export async function perform (args, context) {
|
|||||||
|
|
||||||
// TODO: referals for boost
|
// TODO: referals for boost
|
||||||
|
|
||||||
// compare timestamps to only notify if mention or item referral was just created to avoid duplicates on edits
|
// notify all the mentions if the mention is new
|
||||||
for (const { userId, createdAt } of item.mentions) {
|
for (const { userId, createdAt } of item.mentions) {
|
||||||
if (item.updatedAt.getTime() !== createdAt.getTime()) continue
|
if (item.updatedAt.getTime() === createdAt.getTime()) continue
|
||||||
notifyMention({ models, item, userId }).catch(console.error)
|
notifyMention({ models, item, userId }).catch(console.error)
|
||||||
}
|
}
|
||||||
for (const { refereeItem, createdAt } of item.itemReferrers) {
|
for (const { refereeItem, createdAt } of item.itemReferrers) {
|
||||||
if (item.updatedAt.getTime() !== createdAt.getTime()) continue
|
if (item.updatedAt.getTime() === createdAt.getTime()) continue
|
||||||
notifyItemMention({ models, referrerItem: item, refereeItem }).catch(console.error)
|
notifyItemMention({ models, referrerItem: item, refereeItem }).catch(console.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ export async function onPaid ({ invoice, actIds }, { models, tx }) {
|
|||||||
|
|
||||||
// perform denomormalized aggregates: weighted votes, upvotes, msats, lastZapAt
|
// perform denomormalized aggregates: weighted votes, upvotes, msats, lastZapAt
|
||||||
// NOTE: for the rows that might be updated by a concurrent zap, we use UPDATE for implicit locking
|
// NOTE: for the rows that might be updated by a concurrent zap, we use UPDATE for implicit locking
|
||||||
const [item] = await tx.$queryRaw`
|
await tx.$executeRaw`
|
||||||
WITH zapper AS (
|
WITH zapper AS (
|
||||||
SELECT trust FROM users WHERE id = ${itemAct.userId}::INTEGER
|
SELECT trust FROM users WHERE id = ${itemAct.userId}::INTEGER
|
||||||
), zap AS (
|
), zap AS (
|
||||||
@ -107,8 +107,7 @@ export async function onPaid ({ invoice, actIds }, { models, tx }) {
|
|||||||
msats = "Item".msats + ${msats}::BIGINT,
|
msats = "Item".msats + ${msats}::BIGINT,
|
||||||
"lastZapAt" = now()
|
"lastZapAt" = now()
|
||||||
FROM zap, zapper
|
FROM zap, zapper
|
||||||
WHERE "Item".id = ${itemAct.itemId}::INTEGER
|
WHERE "Item".id = ${itemAct.itemId}::INTEGER`
|
||||||
RETURNING "Item".*`
|
|
||||||
|
|
||||||
// record potential bounty payment
|
// record potential bounty payment
|
||||||
// NOTE: we are at least guaranteed that we see the update "ItemUserAgg" from our tx so we can trust
|
// NOTE: we are at least guaranteed that we see the update "ItemUserAgg" from our tx so we can trust
|
||||||
@ -140,7 +139,7 @@ export async function onPaid ({ invoice, actIds }, { models, tx }) {
|
|||||||
WHERE "Item".path @> zapped.path AND "Item".id <> zapped.id`
|
WHERE "Item".path @> zapped.path AND "Item".id <> zapped.id`
|
||||||
|
|
||||||
// TODO: referrals
|
// TODO: referrals
|
||||||
notifyZapped({ models, item }).catch(console.error)
|
notifyZapped({ models, id: itemAct.itemId }).catch(console.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function onFail ({ invoice }, { tx }) {
|
export async function onFail ({ invoice }, { tx }) {
|
||||||
|
@ -88,11 +88,11 @@ export function usePaidMutation (mutation,
|
|||||||
hash: invoice.hash
|
hash: invoice.hash
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
ourOnCompleted?.(data)
|
|
||||||
onPaid?.(client.cache, { data })
|
|
||||||
// block until the invoice to be marked as paid
|
// block until the invoice to be marked as paid
|
||||||
// for pessimisitic actions, they won't show up on navigation until they are marked as paid
|
// for pessimisitic actions, they won't show up on navigation until they are marked as paid
|
||||||
await invoiceWaiter.waitUntilPaid(invoice, inv => inv?.actionState === 'PAID')
|
await invoiceWaiter.waitUntilPaid(invoice, inv => inv?.actionState === 'PAID')
|
||||||
|
ourOnCompleted?.(data)
|
||||||
|
onPaid?.(client.cache, { data })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('usePaidMutation: failed to pay invoice', e)
|
console.error('usePaidMutation: failed to pay invoice', e)
|
||||||
onPayError?.(e, client.cache, { data })
|
onPayError?.(e, client.cache, { data })
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import webPush from 'web-push'
|
import webPush from 'web-push'
|
||||||
import removeMd from 'remove-markdown'
|
import removeMd from 'remove-markdown'
|
||||||
import { COMMENT_DEPTH_LIMIT, FOUND_BLURBS, LOST_BLURBS } from './constants'
|
import { USER_ID, COMMENT_DEPTH_LIMIT, FOUND_BLURBS, LOST_BLURBS } from './constants'
|
||||||
import { msatsToSats, numWithUnits } from './format'
|
import { msatsToSats, numWithUnits } from './format'
|
||||||
import models from '@/api/models'
|
import models from '@/api/models'
|
||||||
import { isMuted } from '@/lib/user'
|
import { isMuted } from '@/lib/user'
|
||||||
@ -178,9 +178,9 @@ export const notifyTerritorySubscribers = async ({ models, item }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const notifyItemParents = async ({ models, item }) => {
|
export const notifyItemParents = async ({ models, item, me }) => {
|
||||||
try {
|
try {
|
||||||
const user = await models.user.findUnique({ where: { id: item.userId } })
|
const user = await models.user.findUnique({ where: { id: me?.id || USER_ID.anon } })
|
||||||
const parents = await models.$queryRawUnsafe(
|
const parents = await models.$queryRawUnsafe(
|
||||||
'SELECT DISTINCT p."userId" FROM "Item" i JOIN "Item" p ON p.path @> i.path WHERE i.id = $1 and p."userId" <> $2 ' +
|
'SELECT DISTINCT p."userId" FROM "Item" i JOIN "Item" p ON p.path @> i.path WHERE i.id = $1 and p."userId" <> $2 ' +
|
||||||
'AND NOT EXISTS (SELECT 1 FROM "Mute" m WHERE m."muterId" = p."userId" AND m."mutedId" = $2)',
|
'AND NOT EXISTS (SELECT 1 FROM "Mute" m WHERE m."muterId" = p."userId" AND m."mutedId" = $2)',
|
||||||
@ -198,48 +198,48 @@ export const notifyItemParents = async ({ models, item }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const notifyZapped = async ({ models, item }) => {
|
export const notifyZapped = async ({ models, id }) => {
|
||||||
try {
|
try {
|
||||||
const forwards = await models.itemForward.findMany({ where: { itemId: item.id } })
|
const updatedItem = await models.item.findUnique({ where: { id: Number(id) } })
|
||||||
|
const forwards = await models.itemForward.findMany({ where: { itemId: Number(id) } })
|
||||||
const userPromises = forwards.map(fwd => models.user.findUnique({ where: { id: fwd.userId } }))
|
const userPromises = forwards.map(fwd => models.user.findUnique({ where: { id: fwd.userId } }))
|
||||||
const userResults = await Promise.allSettled(userPromises)
|
const userResults = await Promise.allSettled(userPromises)
|
||||||
const mappedForwards = forwards.map((fwd, index) => ({ ...fwd, user: userResults[index].value ?? null }))
|
const mappedForwards = forwards.map((fwd, index) => ({ ...fwd, user: userResults[index].value ?? null }))
|
||||||
let forwardedSats = 0
|
let forwardedSats = 0
|
||||||
let forwardedUsers = ''
|
let forwardedUsers = ''
|
||||||
if (mappedForwards.length) {
|
if (mappedForwards.length) {
|
||||||
forwardedSats = Math.floor(msatsToSats(item.msats) * mappedForwards.map(fwd => fwd.pct).reduce((sum, cur) => sum + cur) / 100)
|
forwardedSats = Math.floor(msatsToSats(updatedItem.msats) * mappedForwards.map(fwd => fwd.pct).reduce((sum, cur) => sum + cur) / 100)
|
||||||
forwardedUsers = mappedForwards.map(fwd => `@${fwd.user.name}`).join(', ')
|
forwardedUsers = mappedForwards.map(fwd => `@${fwd.user.name}`).join(', ')
|
||||||
}
|
}
|
||||||
let notificationTitle
|
let notificationTitle
|
||||||
if (item.title) {
|
if (updatedItem.title) {
|
||||||
if (forwards.length > 0) {
|
if (forwards.length > 0) {
|
||||||
notificationTitle = `your post forwarded ${numWithUnits(forwardedSats)} to ${forwardedUsers}`
|
notificationTitle = `your post forwarded ${numWithUnits(forwardedSats)} to ${forwardedUsers}`
|
||||||
} else {
|
} else {
|
||||||
notificationTitle = `your post stacked ${numWithUnits(msatsToSats(item.msats))}`
|
notificationTitle = `your post stacked ${numWithUnits(msatsToSats(updatedItem.msats))}`
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (forwards.length > 0) {
|
if (forwards.length > 0) {
|
||||||
// I don't think this case is possible
|
// I don't think this case is possible
|
||||||
notificationTitle = `your reply forwarded ${numWithUnits(forwardedSats)} to ${forwardedUsers}`
|
notificationTitle = `your reply forwarded ${numWithUnits(forwardedSats)} to ${forwardedUsers}`
|
||||||
} else {
|
} else {
|
||||||
notificationTitle = `your reply stacked ${numWithUnits(msatsToSats(item.msats))}`
|
notificationTitle = `your reply stacked ${numWithUnits(msatsToSats(updatedItem.msats))}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await sendUserNotification(updatedItem.userId, {
|
||||||
await sendUserNotification(item.userId, {
|
|
||||||
title: notificationTitle,
|
title: notificationTitle,
|
||||||
body: item.title ? item.title : item.text,
|
body: updatedItem.title ? updatedItem.title : updatedItem.text,
|
||||||
item,
|
item: updatedItem,
|
||||||
tag: `TIP-${item.id}`
|
tag: `TIP-${updatedItem.id}`
|
||||||
})
|
})
|
||||||
|
|
||||||
// send push notifications to forwarded recipients
|
// send push notifications to forwarded recipients
|
||||||
if (mappedForwards.length) {
|
if (mappedForwards.length) {
|
||||||
await Promise.allSettled(mappedForwards.map(forward => sendUserNotification(forward.user.id, {
|
await Promise.allSettled(mappedForwards.map(forward => sendUserNotification(forward.user.id, {
|
||||||
title: `you were forwarded ${numWithUnits(Math.round(msatsToSats(item.msats) * forward.pct / 100))}`,
|
title: `you were forwarded ${numWithUnits(Math.round(msatsToSats(updatedItem.msats) * forward.pct / 100))}`,
|
||||||
body: item.title ?? item.text,
|
body: updatedItem.title ?? updatedItem.text,
|
||||||
item,
|
item: updatedItem,
|
||||||
tag: `FORWARDEDTIP-${item.id}`
|
tag: `FORWARDEDTIP-${updatedItem.id}`
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -26,7 +26,7 @@ const apolloServer = new ApolloServer({
|
|||||||
return (error, result) => {
|
return (error, result) => {
|
||||||
const end = process.hrtime.bigint()
|
const end = process.hrtime.bigint()
|
||||||
const ms = (end - start) / 1000000n
|
const ms = (end - start) / 1000000n
|
||||||
if (process.env.GRAPHQL_SLOW_LOGS_MS && ms > process.env.GRAPHQL_SLOW_LOGS_MS) {
|
if (ms > 50) {
|
||||||
console.log(`Field ${info.parentType.name}.${info.fieldName} took ${ms}ms`)
|
console.log(`Field ${info.parentType.name}.${info.fieldName} took ${ms}ms`)
|
||||||
}
|
}
|
||||||
if (error) {
|
if (error) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user