• 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 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}