Skip to content

Commit 7eee784

Browse files
authored
Release v1.40.1 (#961)
Fix: * Too many sigterm listeners on process Hotfixes: * Slow GetFlows query due to inconsistent query plan * Check that Trigger step, app and event are valid
2 parents c270adc + 18837ca commit 7eee784

File tree

10 files changed

+85
-41
lines changed

10 files changed

+85
-41
lines changed

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,5 +106,5 @@
106106
"tsconfig-paths": "^4.2.0",
107107
"type-fest": "4.10.3"
108108
},
109-
"version": "1.40.0"
109+
"version": "1.40.1"
110110
}

packages/backend/src/controllers/webhooks/handler.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,30 +72,41 @@ export default async (request: IRequest, response: Response) => {
7272

7373
const testRun = !flow.active
7474
const triggerStep = await flow.getTriggerStep()
75-
const triggerCommand = await triggerStep.getTriggerCommand()
76-
const app = await triggerStep.getApp()
77-
const isWebhookApp = app.key === 'webhook' || app.key === 'formsg'
7875

79-
// Allow all webhook test runs to work
80-
if (testRun && !isWebhookApp) {
76+
const triggerApp = await triggerStep?.getApp()
77+
78+
if (!triggerApp) {
79+
logger.info(`Trigger app not set up for flow ${flowId}`)
80+
return response.sendStatus(404)
81+
}
82+
83+
const isWebhookApp =
84+
triggerApp.key === 'webhook' || triggerApp.key === 'formsg'
85+
86+
if (!isWebhookApp) {
87+
logger.info(`Invalid trigger app for flow${flowId}`)
8188
return response.sendStatus(404)
8289
}
8390

91+
const triggerCommand = await triggerStep?.getTriggerCommand()
8492
// If trigger event is not selected, this should also return 404
8593
if (triggerCommand?.type !== 'webhook') {
94+
logger.info(
95+
`Trigger command not found or is not webhook type for flow${flowId}`,
96+
)
8697
return response.sendStatus(404)
8798
}
8899

89-
if (app.auth?.verifyWebhook) {
100+
if (triggerApp.auth?.verifyWebhook) {
90101
const $ = await globalVariable({
91102
flow,
92103
connection: await triggerStep.$relatedQuery('connection'),
93-
app,
104+
app: triggerApp,
94105
step: triggerStep,
95106
request,
96107
})
97108

98-
const verified = await app.auth.verifyWebhook($)
109+
const verified = await triggerApp.auth.verifyWebhook($)
99110

100111
if (!verified) {
101112
return response.sendStatus(401)
@@ -131,7 +142,7 @@ export default async (request: IRequest, response: Response) => {
131142
flowId,
132143
executionId,
133144
stepId: triggerStep.id,
134-
appKey: app.key,
145+
appKey: triggerApp.key,
135146
testRun,
136147
})
137148

packages/backend/src/graphql/queries/get-flows.ts

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import paginate from '@/helpers/pagination'
2+
import Flow from '@/models/flow'
23

34
import type { QueryResolvers } from '../__generated__/types.generated'
45

@@ -7,31 +8,55 @@ const getFlows: QueryResolvers['getFlows'] = async (
78
params,
89
context,
910
) => {
10-
const flowsQuery = context.currentUser
11-
.$relatedQuery('flows')
12-
.joinRelated({
13-
steps: true,
11+
const filteredFlowIds = (
12+
await context.currentUser
13+
.$relatedQuery('flows')
14+
.distinct('id')
15+
.where((builder) => {
16+
if (params.name) {
17+
builder.where('name', 'ilike', `%${params.name}%`)
18+
}
19+
})
20+
).map((f) => f.id)
21+
22+
if (!filteredFlowIds.length) {
23+
return {
24+
pageInfo: {
25+
currentPage: 1,
26+
totalCount: 0,
27+
},
28+
edges: [],
29+
}
30+
}
31+
32+
const flowsQuery = Flow.query()
33+
.with('filtered_steps', (builder) => {
34+
builder
35+
.distinct('flow_id')
36+
.from('steps')
37+
.where((stepBuilder) => {
38+
if (params.connectionId) {
39+
stepBuilder.where('connection_id', params.connectionId)
40+
}
41+
42+
if (params.appKey) {
43+
stepBuilder.where('app_key', params.appKey)
44+
}
45+
46+
stepBuilder.withSoftDeleted()
47+
})
48+
.whereNull('deleted_at')
49+
.whereIn('flow_id', filteredFlowIds)
50+
.withSoftDeleted()
1451
})
52+
.innerJoin('filtered_steps', 'id', 'filtered_steps.flow_id')
1553
.withGraphFetched({
1654
steps: {
1755
connection: true,
1856
},
1957
pendingTransfer: true,
2058
})
21-
.where((builder) => {
22-
if (params.connectionId) {
23-
builder.where('steps.connection_id', params.connectionId)
24-
}
25-
26-
if (params.name) {
27-
builder.where('flows.name', 'ilike', `%${params.name}%`)
28-
}
29-
30-
if (params.appKey) {
31-
builder.where('steps.app_key', params.appKey)
32-
}
33-
})
34-
.groupBy('flows.id')
59+
.groupBy('id')
3560
.orderBy('active', 'desc')
3661
.orderBy('updated_at', 'desc')
3762

packages/backend/src/queues/action.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
} from '@taskforcesh/bullmq-pro'
88

99
import apps from '@/apps'
10+
import logger from '@/helpers/logger'
1011
import { makeActionQueue } from '@/queues/helpers/make-action-queue'
1112

1213
//
@@ -133,3 +134,10 @@ export async function getActionJob(
133134
const { queueName, bullMqJobId } = parseActionJobId(actionJobId)
134135
return await actionQueuesByName[queueName].getJob(bullMqJobId)
135136
}
137+
138+
process.on('SIGTERM', async () => {
139+
logger.info('SIGTERM: gracefully closing all action queues')
140+
const allQueues = [mainActionQueue, ...Object.values(actionQueuesByName)]
141+
await Promise.all(allQueues.map((q) => q?.close()))
142+
logger.info('SIGTERM: all action queues closed')
143+
})

packages/backend/src/queues/helpers/make-action-queue.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,5 @@ export function makeActionQueue(
3131
}
3232
})
3333

34-
process.on('SIGTERM', async () => {
35-
await queue.close()
36-
})
37-
3834
return queue
3935
}

packages/backend/src/workers/action.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import apps from '@/apps'
2+
import logger from '@/helpers/logger'
23
import {
34
appActionQueues,
45
MAIN_ACTION_QUEUE_NAME,
@@ -38,3 +39,10 @@ for (const [appKey, app] of Object.entries(apps)) {
3839
queueConfig: app.queue,
3940
})
4041
}
42+
43+
process.on('SIGTERM', async () => {
44+
logger.info('SIGTERM: gracefully closing all action workers')
45+
const allWorkers = [mainActionWorker, ...Object.values(appActionWorkers)]
46+
await Promise.all(allWorkers.map((w) => w?.close()))
47+
logger.info('SIGTERM: all action workers closed')
48+
})

packages/backend/src/workers/helpers/make-action-worker.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,9 +290,5 @@ export function makeActionWorker(
290290
})
291291
})
292292

293-
process.on('SIGTERM', async () => {
294-
await worker.close()
295-
})
296-
297293
return worker
298294
}

packages/frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "frontend",
3-
"version": "1.40.0",
3+
"version": "1.40.1",
44
"scripts": {
55
"dev": "wait-on tcp:3000 && vite --host --force",
66
"build": "tsc && vite build --mode=${VITE_MODE:-prod}",

packages/types/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"name": "@plumber/types",
33
"description": "Shared types for plumber",
44
"types": "./index.d.ts",
5-
"version": "1.40.0"
5+
"version": "1.40.1"
66
}

0 commit comments

Comments
 (0)