1/** 2 * @file Describe the file 3 * Copyright (c) 2023 Huawei Device Co., Ltd. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17import data_rdb from '@ohos.data.relationalStore'; 18import { Observer } from '@ohos/common/src/main/ets/observer/Observer'; 19import { Log } from '@ohos/common/src/main/ets/utils/Log'; 20import { startTimer, stopTimer } from '@ohos/common/src/main/ets/utils/SystemTimerUtils'; 21import { AlertsMessage } from './AlertsMessage'; 22import AlertsUpdateJudgerFactory from './AlertsUpdateJudgerFactory'; 23import { runScheduleNextAlarm } from './AlertsProcessor'; 24 25const TAG = 'AlertsObserver'; 26 27export const INSERT_OPERATION_NAME = 'insert'; 28export const UPDATE_OPERATION_NAME = 'update'; 29export const DELETE_OPERATION_NAME = 'delete'; 30export const WAITING_DELAY_TIME = 5000; 31 32/** 33 * the Alerts Observer 34 * 35 * @since 2022-09-09 36 */ 37export class AlertsObserver implements Observer { 38 // AlertsObserver的单例 39 private static sInstance: AlertsObserver; 40 41 // 用于判断 checkNextAlarm 是否正在创建定时器,防止短时间内多个进程同时访问 checkNextAlarm 方法并创建多个定时器 42 private isAlertTimerBeingCreated: boolean; 43 44 // 记录上一次需要执行刷新操作的时刻 45 private mLastUpdateAlertTime: number; 46 47 // 记录上一次定时器的ID 48 private mAlertTimerId: number; 49 50 /** 51 * 初始化变量 52 */ 53 private constructor() { 54 this.isAlertTimerBeingCreated = false; 55 this.mLastUpdateAlertTime = 0; 56 this.mAlertTimerId = 0; 57 } 58 59 /** 60 * 返回 创建线程方法屏蔽标志位,防止两次过近的调用创建多个定时器 61 */ 62 public getIsAlertTimerBeingCreated(): boolean { 63 return this.isAlertTimerBeingCreated; 64 } 65 66 /** 67 * 设置 创建线程方法屏蔽标志位,防止两次过近的调用创建多个定时器 68 */ 69 public setIsAlertTimerBeingCreated(isAlertTimerBeingCreated: boolean) { 70 this.isAlertTimerBeingCreated = isAlertTimerBeingCreated; 71 } 72 73 /** 74 * 返回上一次需要执行刷新操作的时刻 75 */ 76 public getLastUpdateAlertTime(): number { 77 return this.mLastUpdateAlertTime; 78 } 79 80 /** 81 * 返回上一次定时器的ID 82 */ 83 public getAlertTimerId(): number { 84 return this.mAlertTimerId; 85 } 86 87 /** 88 * 返回上一次需要执行刷新操作的时刻 89 */ 90 public setLastUpdateAlertTime(lastUpdateAlertTime: number) { 91 this.mLastUpdateAlertTime = lastUpdateAlertTime; 92 } 93 94 /** 95 * 返回上一次定时器的ID 96 */ 97 public setAlertTimerId(alertTimerId: number) { 98 this.mAlertTimerId = alertTimerId; 99 } 100 101 /** 102 * 获取 AlertsObserver 的单例 103 */ 104 public static getInstance() { 105 if (!AlertsObserver.sInstance) { 106 Log.log(TAG, 'call getInstance init'); 107 AlertsObserver.sInstance = new AlertsObserver(); 108 } 109 return AlertsObserver.sInstance; 110 } 111 112 onChange(message: AlertsMessage) { 113 Log.debug(TAG, "AlertsObserver enter"); 114 115 // 判断是否需要更新Alarm 116 if (isNeedToUpdateAlerts(message)) { 117 Log.debug(TAG, "AlertsObserver:Alarm is needed to update."); 118 checkNextAlarm(); 119 } 120 Log.debug(TAG, "AlertsObserver leave"); 121 } 122} 123 124/** 125 * 判断是否需要更新 Alerts 表 126 * 127 * @Param message 对数据表进行操作的信息 128 * @Return 是否需要更新 Alerts 表 129 */ 130function isNeedToUpdateAlerts(message: AlertsMessage): boolean { 131 // 通过message[operationName,[table,values,predicates]]判断增改删方法对不同表的字段操作判断是否需要刷新 132 if (message === null || message === undefined) { 133 return false; 134 } 135 136 // 传入的参数为操作名称和具体操作细节 137 let operationName: string = message.getOperationName(); 138 let tableName: string = message.getTableName(); 139 let values: data_rdb.ValuesBucket = message.getValues(); 140 141 // 策略模式+工厂模式:根据operationName使用不同的判断逻辑生产不同实例,扩展不同场景只需要额外增加多的AlarmNeedUpdateJudger类即可 142 let alarmNeedUpdateJudgerFactory = new AlertsUpdateJudgerFactory(); 143 let AlarmNeedUpdateJudger = alarmNeedUpdateJudgerFactory.getAlertsUpdateJudger(operationName); 144 if (AlarmNeedUpdateJudger !== null && AlarmNeedUpdateJudger != undefined) { 145 return AlarmNeedUpdateJudger.isNeedToUpdateAlerts(tableName, values); 146 } 147 Log.error(TAG, "AlarmNeedUpdateJudger:get Null, You need to confirm your operationName!"); 148 return false; 149} 150 151/** 152 * 检查下一个 alarm 的时间 并在恰当的时间进行 Alerts 表的更新 153 */ 154export function checkNextAlarm() { 155 Log.debug(TAG, "checkNextAlarm enter"); 156 let alertsObserver = AlertsObserver.getInstance(); 157 createAndStartTimerAfterFiveSeconds(alertsObserver); 158 Log.debug(TAG, "checkNextAlarm end"); 159 return; 160} 161 162/** 163 * 停止上一个定时器并重置该定时器,该定时器会在5s后到期 164 * 165 * @Param alertsObserver 表示 AlertsObserver 的实例 166 */ 167function stopLastTimerAndStartThisTimer(alertsObserver: AlertsObserver) { 168 let alertTimerId = alertsObserver.getAlertTimerId(); 169 Log.debug(TAG, `Clear Last AlertTimer, and AlertTimerId is` + JSON.stringify(alertTimerId)); 170 stopTimer(alertTimerId, (err) => { 171 if (err?.message !== undefined) { 172 Log.error(TAG, 'failed to stopTimer' + err?.message); 173 } 174 Log.debug(TAG, 'system.stopTimer successful' + err?.message); 175 startTimerAfterFiveSeconds(alertsObserver, alertTimerId); 176 }) 177 Log.debug(TAG, `Success to reStart Last AlertTimer, and alertTimerId is ` + JSON.stringify(alertTimerId)); 178} 179 180/** 181 * 创建并开启一个定时器,该定时器会在5s后到期 182 * 183 * @Param alertsObserver 表示 AlertsObserver 的实例 184 */ 185async function createAndStartTimerAfterFiveSeconds(alertsObserver: AlertsObserver) { 186 Log.debug(TAG, `create Timer begin`); 187 188 // 设置5s后的定时器,并发送 CHECK_NEXT_ALARM 广播 189 alertsObserver.setIsAlertTimerBeingCreated(false); 190 setTimeout(() => { 191 runScheduleNextAlarm(); 192 }, 5000); 193 Log.debug(TAG, `create Timer end`); 194} 195 196/** 197 * 开启一个定时器,并记录定时器ID和触发时间到 AlertsObserver 中去,该定时器会在5s后到期 198 * 199 * @Param alertsObserver 表示 AlertsObserver 的实例 200 */ 201function startTimerAfterFiveSeconds(alertsObserver: AlertsObserver, timerId: number) { 202 Log.debug(TAG, `start Timer begin`); 203 Log.debug(TAG, "A Timer has been created and Timer ID is:" + timerId); 204 let currentTime = new Date().getTime(); 205 let triggerTime = currentTime + WAITING_DELAY_TIME; 206 Log.debug(TAG, "timer start begin,and Timer will callback when: " + triggerTime); 207 startTimer(timerId, triggerTime, (err) => { 208 if (err !== undefined && err !== null) { 209 if (err?.message !== undefined && err?.message !== null) { 210 Log.error(TAG, 'failed to startTimer' + err?.message); 211 } 212 } 213 Log.debug(TAG, "timer start end,and Timer will callback when: " + triggerTime); 214 }) 215 216 // 记录新定时器的timerId 217 alertsObserver.setAlertTimerId(timerId); 218 Log.debug(TAG, `start Timer end`); 219}