gancio-upstream/server/taskManager.js

173 lines
4.3 KiB
JavaScript
Raw Normal View History

2021-03-05 14:17:10 +01:00
const log = require('./log')
const placeHelpers = require('./helpers/place')
const tagHelpers = require('./helpers/tag')
const apHelpers = require('./helpers/ap.js')
2025-01-20 17:07:23 +01:00
const { Duration } = require('luxon')
// const notifier = require('./notifier')
const loopInterval = 10 // process.env.NODE_ENV === 'production' ? 1 : 1
2024-06-11 23:18:38 +02:00
const minute = 6 * loopInterval
2021-02-09 12:17:10 +01:00
const hour = minute * 60
const day = hour * 24
class Task {
2021-04-10 00:11:16 +02:00
constructor ({ name, repeat = false, repeatDelay = 1, callAtStart = false, method, args = [] }) {
this.name = name
2021-04-10 00:11:16 +02:00
this.repeat = repeat
this.repeatDelay = repeatDelay
this.processInNTick = callAtStart ? 0 : repeatDelay
this.method = method
this.args = args
}
process () {
2020-01-30 23:43:58 +01:00
this.processInNTick--
if (this.processInNTick > 0) {
return
}
2025-01-20 17:07:23 +01:00
log.debug(`[TASK] Process ${this.name}`)
2021-04-10 00:11:16 +02:00
this.processInNTick = this.repeatDelay
try {
const ret = this.method.apply(this, this.args)
2025-01-20 17:07:23 +01:00
if (ret && typeof ret.catch === 'function') {
2021-10-21 12:18:25 +02:00
ret.catch(e => log.error(`TASK ERROR [${this.name}]: ${e} ${e.stack}`))
2020-01-30 17:48:09 +01:00
return ret
}
2025-01-20 17:07:23 +01:00
return ret
} catch (e) {
2021-10-21 12:18:25 +02:00
log.error(`TASK ERROR [${this.name}]: ${e} ${e.stack}`)
}
}
}
/**
* Manage tasks:
* - Send emails
* - Send AP notifications
* - Create recurrent events
* - Sync AP federation profiles
* - Remove unused tags/places
2024-04-01 10:34:29 +02:00
* - Remove past federated events and related resources
* - Remove unused ap actors
*/
class TaskManager {
constructor () {
this.tasks = []
2021-03-05 14:17:10 +01:00
this.interval = 1
this.timeout = null
}
2021-02-09 12:17:10 +01:00
start (interval = loopInterval) {
2023-01-10 18:15:33 +01:00
const eventController = require('./api/controller/event')
// create and clean recurrent events
this.add(new Task({
name: 'CREATE_RECURRENT_EVENT',
method: eventController._createRecurrent,
repeatDelay: hour / 2, // check each half an hour
repeat: true
}))
// remove unrelated places
this.add(new Task({
name: 'CLEAN_UNUSED_PLACES',
method: placeHelpers._cleanUnused,
repeatDelay: day,
repeat: true,
callAtStart: true
}))
this.add(new Task({
name: 'CLEAN_UNUSED_TAGS',
method: tagHelpers._cleanUnused,
2024-04-01 10:34:29 +02:00
repeatDelay: day+minute,
repeat: true,
callAtStart: true
}))
this.add(new Task({
name: 'CLEAN_FEDIVERSE_PAST_EVENT',
method: apHelpers._cleanPastEvents,
2024-04-01 10:34:29 +02:00
repeatDelay: 6*hour+5*minute,
repeat: true,
callAtStart: true
}))
this.add(new Task({
name: 'CLEAN_FEDIVERSE_AP_USERS',
method: apHelpers._cleanUnusedAPUser,
repeatDelay: day+10*minute,
repeat: true,
callAtStart: true
}))
2021-02-09 12:17:10 +01:00
log.info(`START TASK MANAGER WITH LOOP INTERVAL OF ${interval} seconds`)
this.interval = interval
2021-02-09 12:17:10 +01:00
this.timeout = setTimeout(this.tick.bind(this), interval * 1000)
}
stop () {
if (this.timeout) {
2021-04-28 12:44:26 +02:00
log.info('STOP TASKMANAGER')
clearTimeout(this.timeout)
this.timeout = false
}
}
add (task) {
2025-01-20 17:07:23 +01:00
log.info(`[TASK] Add ${task.name} (${Duration.fromMillis(task.repeatDelay * this.interval * 1000).rescale().toHuman({ listStyle: "long" })})`)
this.tasks.push(task)
}
process () {
if (!this.tasks.length) {
return
}
2020-02-10 12:00:16 +01:00
// process all tasks
2020-01-30 17:48:09 +01:00
const tasks = this.tasks.map(t => t.process())
2020-02-10 12:00:16 +01:00
// remove removable tasks
2021-04-10 00:11:16 +02:00
this.tasks = this.tasks.filter(t => t.repeat)
2020-02-10 12:00:16 +01:00
return Promise.allSettled(tasks)
}
async tick () {
await this.process()
2021-02-09 12:17:10 +01:00
this.timeout = setTimeout(this.tick.bind(this), this.interval * 1000)
}
}
// daily morning notification
// TS.add(new Task({
// name: 'NOTIFICATION',
// method: notifier._daily,
// repeatEach: 1
// }))
// AP users profile sync
// TaskManager.add(new Task({
// name: 'AP_PROFILE_SYNC',
// method: federation._sync,
// repeatEach: 60 * 24
// }))
// Search for places position via nominatim
// TaskManager.add(new Task({
// name: 'NOMINATIM_QUERY',
// method: places._nominatimQuery,
// repeatEach: 60
// }))
2021-04-10 00:11:16 +02:00
//
// TS.start()
// TS.add(new Task({ name: 'removable #1', method: daje, args: ['removable #1'], removable: true }))
// TS.add(new Task({ name: 'non removable #2', method: daje, args: ['non removable #2'] }))
// TS.add(new Task({ name: 'non removable and repeat each #2', method: daje, args: ['nn rm and rpt #5'], repeatEach: 5 }))
module.exports = { Task, TaskManager: new TaskManager() }