Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

.trigger
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"trigger:dev": "npx [email protected] dev",
"dev:embedded": "node scripts/dev.js",
"build": "next build",
"start": "next start",
Expand All @@ -20,6 +21,7 @@
"dependencies": {
"@sentry/nextjs": "^9.13.0",
"@supabase/supabase-js": "^2.49.4",
"@trigger.dev/sdk": "4.3.0",
"bottleneck": "^2.19.5",
"copilot-design-system": "^2.0.10",
"copilot-node-sdk": "^3.11.1",
Expand Down Expand Up @@ -51,7 +53,9 @@
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.24.0",
"@ngrok/ngrok": "^1.4.1",
"@sentry/esbuild-plugin": "^4.6.1",
"@tailwindcss/postcss": "^4.1.5",
"@trigger.dev/build": "4.3.0",
"@types/deep-equal": "^1.0.4",
"@types/html-to-text": "^9",
"@types/node": "^22.14.1",
Expand Down Expand Up @@ -84,4 +88,4 @@
"yarn prettier:fix"
]
}
}
}
7 changes: 3 additions & 4 deletions src/app/api/quickbooks/cron/cron.controller.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import APIError from '@/app/api/core/exceptions/api'
import { cronSecret } from '@/config'
import { NextRequest, NextResponse } from 'next/server'
import CronService from '@/app/api/quickbooks/cron/cron.service'
import { processResyncForFailedRecords } from '@/trigger/resyncFailedRecords'

export const processFailedSync = async (request: NextRequest) => {
const authHeader = request.headers.get('authorization')
if (authHeader !== `Bearer ${cronSecret}`) {
throw new APIError(401, 'Unauthorized')
}
const cronService = new CronService()
await cronService.rerunFailedSync()
processResyncForFailedRecords.trigger()
return NextResponse.json({
success: true,
message: 'Failed logs are re-synced successfully.',
message: 'Logs are successfully added to resync queue.',
})
}
14 changes: 14 additions & 0 deletions src/trigger/resyncFailedRecords.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import CronService from '@/app/api/quickbooks/cron/cron.service'
import { task } from '@trigger.dev/sdk'

export const processResyncForFailedRecords = task({
id: 'process-resync-for-failed-records',
machine: 'small-2x',
run: async () => {
console.log(
'resyncFailedRecords#processResyncForFailedRecords :: Trigger resync task',
)
const cronService = new CronService()
await cronService.rerunFailedSync()
},
})
85 changes: 85 additions & 0 deletions trigger.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { sentryEsbuildPlugin } from '@sentry/esbuild-plugin'
import { defineConfig } from '@trigger.dev/sdk/v3'
import { z } from 'zod'
import dotenv from 'dotenv'
import * as Sentry from '@sentry/nextjs'
import { esbuildPlugin } from '@trigger.dev/build/extensions'

dotenv.config()

const vercelEnv = process.env.VERCEL_ENV
const isProd = vercelEnv === 'production'
const project = z.string().min(1).parse(process.env.TRIGGER_PROJECT_ID)
const org = isProd ? z.string().min(1).parse(process.env.SENTRY_ORG) : ''
const sentryProject = isProd
? z.string().min(1).parse(process.env.SENTRY_PROJECT)
: ''
const sentryAuthToken = isProd
? z.string().min(1).parse(process.env.SENTRY_AUTH_TOKEN)
: ''
const dsn = isProd
? z.string().min(1).parse(process.env.NEXT_PUBLIC_SENTRY_DSN)
: ''

export default defineConfig({
project,
runtime: 'node',
logLevel: 'log',
// The max compute seconds a task is allowed to run. If the task run exceeds this duration, it will be stopped.
// You can override this on an individual task.
// See https://trigger.dev/docs/runs/max-duration
maxDuration: 3600,
retries: {
enabledInDev: true,
default: {
maxAttempts: 3,
minTimeoutInMs: 1000,
maxTimeoutInMs: 10000,
factor: 2,
randomize: true,
},
},
dirs: ['./src/trigger'],
build: {
extensions: [
esbuildPlugin(
sentryEsbuildPlugin({
org,
project: sentryProject,
// Find this auth token in settings -> developer settings -> auth tokens
authToken: sentryAuthToken,
}),
{ placement: 'last', target: 'deploy' },
),
],
},
init: () => {
Sentry.init({
defaultIntegrations: false,
// The Data Source Name (DSN) is a unique identifier for your Sentry project.
dsn,
// Update this to match the environment you want to track errors for
environment: vercelEnv,
beforeSend(event) {
if (
event.request?.headers?.['user-agent']?.includes(
'vercel-screenshot', // using 'vercel-screenshot' specifically as cron jobs have 'vercel-cron' user-agent in the header.
) ||
event.request?.headers?.['x-vercel-firewall-bypass']
) {
return null
}
return event
},
})
},
onFailure: ({ payload, error, ctx }) => {
console.error({ payload, error, ctx })
Sentry.captureException(error, {
extra: {
payload,
ctx,
},
})
},
})
8 changes: 7 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
"trigger.config.ts"
],
"exclude": ["node_modules"]
}
Loading
Loading