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