Skip to content

Commit a4eeead

Browse files
feat: enhance schedule job for agentflows
- Refactor ScheduleQueue to utilize executeScheduleJob for job execution. - Add new endpoints for schedule status retrieval and enabling/disabling schedules in chatflows. - Update chatflow service to handle schedule creation, updates, and deletions more effectively. - Introduce DatePicker component for date input in UI. - Enhance CanvasHeader to manage schedule state and toggle functionality. - Integrate schedule validation logic to ensure proper configuration before enabling schedules. - Update dependencies to include node-cron for improved scheduling capabilities.
2 parents d13799f + 1ab2dc9 commit a4eeead

20 files changed

Lines changed: 994 additions & 406 deletions

File tree

packages/components/nodes/agentflow/Start/Start.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,16 @@ class Start_Agentflow implements INode {
236236
scheduleFrequency: 'monthly'
237237
}
238238
},
239+
{
240+
label: 'End Date',
241+
name: 'scheduleEndDate',
242+
type: 'datePicker',
243+
description: 'Optional date after which the schedule will stop firing.',
244+
optional: true,
245+
show: {
246+
startInputType: 'scheduleInput'
247+
}
248+
},
239249
{
240250
label: 'Timezone',
241251
name: 'scheduleTimezone',
@@ -253,7 +263,6 @@ class Start_Agentflow implements INode {
253263
type: 'string',
254264
placeholder: 'Run the daily report',
255265
description: 'Default question/input passed to the flow when it is triggered by the scheduler.',
256-
acceptVariable: true,
257266
rows: 4,
258267
show: {
259268
startInputType: 'scheduleInput'
@@ -352,7 +361,6 @@ class Start_Agentflow implements INode {
352361
const effectiveInput = (typeof input === 'string' && input) || defaultInput || ''
353362
inputData.question = effectiveInput
354363
outputData.question = effectiveInput
355-
outputData.scheduledAt = options.agentflowRuntime?.scheduledAt ?? new Date().toISOString()
356364
}
357365

358366
if (startEphemeralMemory) {

packages/server/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
"multer-s3": "^3.0.1",
127127
"mysql2": "^3.11.3",
128128
"nanoid": "3",
129+
"node-cron": "^4.2.1",
129130
"nodemailer": "^7.0.7",
130131
"openai": "6.19.0",
131132
"passport": "^0.7.0",

packages/server/src/controllers/chatflows/index.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { WorkspaceUserErrorMessage, WorkspaceUserService } from '../../enterpris
1313
import { QueryRunner } from 'typeorm'
1414
import { GeneralErrorMessage } from '../../utils/constants'
1515
import { sanitizeFlowDataForPublicEndpoint } from '../../utils/sanitizeFlowData'
16+
import scheduleService from '../../services/schedule'
17+
import { ScheduleBeat } from '../../queue/ScheduleBeat'
1618

1719
const checkIfChatflowIsValidForStreaming = async (req: Request, res: Response, next: NextFunction) => {
1820
try {
@@ -273,6 +275,54 @@ const checkIfChatflowHasChanged = async (req: Request, res: Response, next: Next
273275
}
274276
}
275277

278+
const getScheduleStatus = async (req: Request, res: Response, next: NextFunction) => {
279+
try {
280+
if (!req.params?.id) {
281+
throw new InternalFlowiseError(
282+
StatusCodes.PRECONDITION_FAILED,
283+
'Error: chatflowsController.getScheduleStatus - id not provided!'
284+
)
285+
}
286+
const workspaceId = req.user?.activeWorkspaceId
287+
if (!workspaceId) {
288+
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, 'Error: chatflowsController.getScheduleStatus - workspace not found!')
289+
}
290+
const status = await scheduleService.getScheduleStatus(req.params.id, workspaceId)
291+
return res.json({
292+
enabled: status.record?.enabled ?? false,
293+
canEnable: status.canEnable,
294+
reason: status.reason,
295+
record: status.record
296+
})
297+
} catch (error) {
298+
next(error)
299+
}
300+
}
301+
302+
const toggleScheduleEnabled = async (req: Request, res: Response, next: NextFunction) => {
303+
try {
304+
if (!req.params?.id) {
305+
throw new InternalFlowiseError(
306+
StatusCodes.PRECONDITION_FAILED,
307+
'Error: chatflowsController.toggleScheduleEnabled - id not provided!'
308+
)
309+
}
310+
const workspaceId = req.user?.activeWorkspaceId
311+
if (!workspaceId) {
312+
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, 'Error: chatflowsController.toggleScheduleEnabled - workspace not found!')
313+
}
314+
const { enabled } = req.body
315+
if (typeof enabled !== 'boolean') {
316+
throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, '"enabled" must be a boolean')
317+
}
318+
const record = await scheduleService.toggleScheduleEnabled(req.params.id, workspaceId, enabled)
319+
await ScheduleBeat.getInstance().onScheduleChanged(record.id, enabled ? 'upsert' : 'delete')
320+
return res.json(record)
321+
} catch (error) {
322+
next(error)
323+
}
324+
}
325+
276326
export default {
277327
checkIfChatflowIsValidForStreaming,
278328
checkIfChatflowIsValidForUploads,
@@ -284,5 +334,7 @@ export default {
284334
updateChatflow,
285335
getSinglePublicChatflow,
286336
getSinglePublicChatbotConfig,
287-
checkIfChatflowHasChanged
337+
checkIfChatflowHasChanged,
338+
getScheduleStatus,
339+
toggleScheduleEnabled
288340
}

packages/server/src/database/entities/ScheduleRecord.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,14 @@ export class ScheduleRecord {
4040
defaultInput?: string
4141

4242
@Column({ nullable: true, type: 'timestamp' })
43-
lastRunAt?: Date
43+
lastRunAt?: Date | null
4444

4545
@Column({ nullable: true, type: 'timestamp' })
46-
nextRunAt?: Date
46+
nextRunAt?: Date | null
47+
48+
/** Optional date/time after which the schedule will no longer fire */
49+
@Column({ nullable: true, type: 'timestamp' })
50+
endDate?: Date | null
4751

4852
@Column({ type: 'varchar' })
4953
workspaceId: string

packages/server/src/database/migrations/mariadb/1772000000000-AddScheduleEntities.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export class AddScheduleEntities1772000000000 implements MigrationInterface {
1414
\`defaultInput\` text,
1515
\`lastRunAt\` datetime(6),
1616
\`nextRunAt\` datetime(6),
17+
\`endDate\` datetime(6),
1718
\`workspaceId\` varchar(255) NOT NULL,
1819
\`createdDate\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
1920
\`updatedDate\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),

packages/server/src/database/migrations/mysql/1772000000000-AddScheduleEntities.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export class AddScheduleEntities1772000000000 implements MigrationInterface {
1414
\`defaultInput\` text,
1515
\`lastRunAt\` datetime(6),
1616
\`nextRunAt\` datetime(6),
17+
\`endDate\` datetime(6),
1718
\`workspaceId\` varchar(255) NOT NULL,
1819
\`createdDate\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
1920
\`updatedDate\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),

packages/server/src/database/migrations/postgres/1772000000000-AddScheduleEntities.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export class AddScheduleEntities1772000000000 implements MigrationInterface {
1414
"defaultInput" text,
1515
"lastRunAt" timestamp,
1616
"nextRunAt" timestamp,
17+
"endDate" timestamp,
1718
"workspaceId" varchar NOT NULL,
1819
"createdDate" timestamp NOT NULL DEFAULT now(),
1920
"updatedDate" timestamp NOT NULL DEFAULT now(),

packages/server/src/database/migrations/sqlite/1772000000000-AddScheduleEntities.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export class AddScheduleEntities1772000000000 implements MigrationInterface {
1414
"defaultInput" text,
1515
"lastRunAt" datetime,
1616
"nextRunAt" datetime,
17+
"endDate" datetime,
1718
"workspaceId" varchar NOT NULL,
1819
"createdDate" datetime NOT NULL DEFAULT (datetime('now')),
1920
"updatedDate" datetime NOT NULL DEFAULT (datetime('now'))

0 commit comments

Comments
 (0)