1+ /**
2+ * Copyright (c) 2023 Hengyang Zhang
3+ *
4+ * This software is released under the MIT License.
5+ * https://opensource.org/licenses/MIT
6+ */
7+
8+ import optionDatabase from '@db/option-database'
9+ import backupProcessor from "@service/backup/processor"
10+ import notificationProcessor from "@service/notification/processor"
11+ import { MILL_PER_MINUTE } from "@util/time"
12+ import alarmManager from "./alarm-manager"
13+ import type MessageDispatcher from './message-dispatcher'
14+
15+ const BACKUP_ALARM_NAME = 'auto-backup-data'
16+ const NOTIFICATION_ALARM_NAME = 'notification-data'
17+
18+ export async function initScheduler ( dispatcher : MessageDispatcher ) : Promise < void > {
19+ dispatcher . register ( 'resetBackupScheduler' , resetBackup )
20+ . register ( 'resetNotificationScheduler' , resetNotification )
21+
22+ const existBackup = await alarmManager . getAlarm ( BACKUP_ALARM_NAME )
23+ ! existBackup && await resetBackup ( )
24+
25+ const existNotification = await alarmManager . getAlarm ( NOTIFICATION_ALARM_NAME )
26+ ! existNotification && await resetNotification ( )
27+ }
28+
29+ async function resetBackup ( ) : Promise < void > {
30+ // MUST read latest option from database
31+ const option = await optionDatabase . getOption ( )
32+
33+ await alarmManager . remove ( BACKUP_ALARM_NAME )
34+
35+ const { autoBackUp, backupType, autoBackUpInterval = 0 } = option
36+ if ( backupType === 'none' || ! autoBackUp || ! autoBackUpInterval ) {
37+ return
38+ }
39+
40+ const interval = autoBackUpInterval * MILL_PER_MINUTE
41+ await alarmManager . setInterval ( BACKUP_ALARM_NAME , interval , async ( ) => {
42+ const result = await backupProcessor . syncData ( )
43+ if ( ! result . success ) {
44+ console . warn ( `Failed to backup ts=${ Date . now ( ) } , msg=${ result . errorMsg } ` )
45+ }
46+ } )
47+ }
48+
49+ type OffsetHandler = ( offsetMin : number ) => number
50+ const OFFSET_HANDLERS : Record < Exclude < timer . notification . Cycle , 'none' > , OffsetHandler > = {
51+ daily : offset => {
52+ const next = new Date ( )
53+ next . setHours ( 0 , offset , 0 , 0 )
54+ const now = new Date ( )
55+ while ( next . getTime ( ) < now . getTime ( ) ) {
56+ next . setDate ( next . getDate ( ) + 1 )
57+ }
58+ return next . getTime ( )
59+ } ,
60+ weekly : offset => {
61+ const next = new Date ( )
62+ const weekday = next . getDay ( )
63+ next . setDate ( next . getDate ( ) - weekday )
64+ next . setHours ( 0 , offset , 0 , 0 )
65+ const now = new Date ( )
66+ while ( next . getTime ( ) < now . getTime ( ) ) {
67+ next . setDate ( next . getDate ( ) + 7 )
68+ }
69+ return next . getTime ( )
70+ }
71+ }
72+
73+ async function resetNotification ( ) : Promise < void > {
74+ await alarmManager . remove ( NOTIFICATION_ALARM_NAME )
75+
76+ const option = await optionDatabase . getOption ( )
77+ const { notificationCycle : cycle , notificationOffset : offset } = option
78+
79+ if ( cycle === 'none' ) return
80+
81+ await alarmManager . setWhen (
82+ NOTIFICATION_ALARM_NAME ,
83+ ( ) => OFFSET_HANDLERS [ cycle ] ( offset ) ,
84+ async ( ) => {
85+ const result = await notificationProcessor . doSend ( )
86+ if ( ! result . success ) {
87+ console . warn ( `Failed to send notification ts=${ Date . now ( ) } , msg=${ result . errorMsg } ` )
88+ }
89+ }
90+ )
91+ }
0 commit comments