• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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}