Skip to content

Commit 9817e09

Browse files
chore: wip
1 parent e077d7e commit 9817e09

File tree

1 file changed

+46
-44
lines changed
  • storage/framework/core/scheduler/src

1 file changed

+46
-44
lines changed

storage/framework/core/scheduler/src/run.ts

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,39 @@ import { snakeCase } from '@stacksjs/strings'
66

77
interface JobSchedule {
88
jobName: string
9-
times: string[]
10-
rate: string,
11-
path: string,
9+
rate: string
10+
path: string
11+
nextRunTime: string | null
1212
}
1313

1414
const scheduleFile = path.storagePath('framework/core/scheduler/src/schedules/jobSchedule.json')
1515

16-
export async function runScheduler(threshold = 3, regenerationCount = 10): Promise<void> {
17-
const now = new Date().toISOString()
16+
export async function runScheduler(): Promise<void> {
17+
const now = new Date()
1818
let schedules = loadSchedule()
1919

2020
const jobFiles = globSync([path.appPath('Jobs/*.ts')], { absolute: true })
21+
22+
// Process job files and initialize schedules if missing
2123
for (const jobFile of jobFiles) {
2224
try {
2325
const jobModule = await import(jobFile)
2426
const job = jobModule.default as JobOptions
25-
26-
const jobName = snakeCase(job.name || 'UnkownJob')
27+
const jobName = snakeCase(job.name || 'UnknownJob')
2728

2829
if (job.rate) {
29-
if (!schedules.some(schedule => schedule.jobName === jobName)) {
30-
const initialSchedule = generateSchedule(jobName || '', getJobInterval(job.rate), regenerationCount)
30+
const existingSchedule = schedules.find(schedule => schedule.jobName === jobName)
31+
32+
if (!existingSchedule) {
33+
// Prefill: Set the initial nextRunTime based on job's rate and current time
34+
const intervalMinutes = getJobInterval(job.rate)
35+
const nextRunTime = new Date(now.getTime() + intervalMinutes * 60000).toISOString()
3136

3237
schedules.push({
33-
jobName: jobName || '',
38+
jobName,
3439
rate: job.rate,
35-
times: initialSchedule.times,
36-
path: jobFile
40+
nextRunTime, // Set nextRunTime here
41+
path: jobFile,
3742
})
3843
}
3944
}
@@ -42,31 +47,28 @@ export async function runScheduler(threshold = 3, regenerationCount = 10): Promi
4247
}
4348
}
4449

50+
// Process schedules and run jobs as needed
4551
for (const schedule of schedules) {
46-
const dueTimes = schedule.times.filter(time => time <= now)
52+
const nextRunTime = new Date(schedule.nextRunTime || now.toISOString())
53+
const intervalMinutes = getJobInterval(schedule.rate)
4754

48-
// Run due jobs
49-
for (const time of dueTimes) {
50-
console.log(`Running job: ${schedule.jobName} at scheduled time: ${time}`)
51-
await runJob(schedule.path)
52-
}
55+
const isDue = isDueToRun(nextRunTime, now)
5356

54-
// Remove executed times
55-
schedule.times = schedule.times.filter(time => time > now)
56-
57-
// Regenerate schedule if below threshold
58-
if (schedule.times.length < threshold) {
59-
console.log(`Regenerating schedule for job: ${schedule.jobName}`)
60-
const lastTime = new Date(schedule.times[schedule.times.length - 1] || now)
61-
const intervalMinutes = getJobInterval(schedule.rate)
62-
const newSchedule = generateSchedule(schedule.jobName, intervalMinutes, regenerationCount, lastTime)
63-
64-
schedule.times.push(...newSchedule.times)
57+
if (isDue) {
58+
console.log(`Running job: ${schedule.jobName} at ${now.toISOString()}`)
59+
await runJob(schedule.path)
60+
61+
// Refresh the next run time based on the interval
62+
schedule.nextRunTime = new Date(nextRunTime.getTime() + intervalMinutes * 60000).toISOString()
6563
}
6664
}
6765

68-
// Save updated schedule
69-
saveSchedule(schedules.filter(schedule => schedule.times.length > 0))
66+
// Save updated schedules
67+
saveSchedule(schedules)
68+
}
69+
70+
function isDueToRun(nextRunTime: Date, currentDate: Date): boolean {
71+
return currentDate >= nextRunTime
7072
}
7173

7274
export function getJobInterval(rate: string): number {
@@ -83,6 +85,18 @@ export function getJobInterval(rate: string): number {
8385
return 15
8486
case Every.ThirtyMinutes:
8587
return 30
88+
case Every.HalfHour:
89+
return 30
90+
case Every.Hour:
91+
return 60
92+
case Every.Day:
93+
return 60 * 24 // 1 day
94+
case Every.Week:
95+
return 60 * 24 * 7 // 1 week
96+
case Every.Month:
97+
return 60 * 24 * 30 // Approximate 1 month (30 days)
98+
case Every.Year:
99+
return 60 * 24 * 365 // Approximate 1 year (365 days)
86100
default:
87101
throw new Error(`Unsupported rate: ${rate}`)
88102
}
@@ -106,16 +120,4 @@ function saveSchedule(schedule: JobSchedule[]): void {
106120
function loadSchedule(): JobSchedule[] {
107121
if (!fs.existsSync(scheduleFile)) return []
108122
return JSON.parse(fs.readFileSync(scheduleFile, 'utf-8'))
109-
}
110-
111-
export function generateSchedule(jobName: string, intervalMinutes: number, count: number, startTime = new Date()): { jobName: string; times: string[] } {
112-
const times: string[] = []
113-
let nextTime = new Date(startTime)
114-
115-
for (let i = 0; i < count; i++) {
116-
nextTime.setMinutes(nextTime.getMinutes() + intervalMinutes)
117-
times.push(nextTime.toISOString())
118-
}
119-
120-
return { jobName, times }
121-
}
123+
}

0 commit comments

Comments
 (0)