Commit e93ef899baf19d38b72406b801454824ec19c38d

Authored by 权海
1 parent 5e4f526f

Revert "feat(ui):修复hr实时压力推送抛异常导致后续代码不执行"

This reverts commit 5e4f526f.
... ... @@ -404,87 +404,6 @@ class HealthRawDataCoreService {
result.sleepResults.isEmpty) {
return;
}
final record = await _readLocalNotificationRecord(result.userId);
final notifications = <HealthRawLocalNotification>[
..._buildSleepNotificationsSafely(result, record),
..._buildHrvNotificationsSafely(
result: result,
hasExistingHrv: hasExistingHrv,
record: record,
),
...await _buildRealtimeStressNotificationsSafely(result, record),
];
for (final notification in notifications) {
final sent = await _sendLocalNotificationSafely(
userId: result.userId,
notification: notification,
);
if (sent &&
notification.recordType ==
HealthRawLocalNotificationRecordType.realtimeStress) {
_scheduleRealtimeStressServerPush([notification]);
}
}
}
Future<HealthRawLocalNotificationRecord> _readLocalNotificationRecord(
int userId,
) async {
try {
return await _localNotificationDispatcher.readRecord(userId);
} catch (error, stackTrace) {
_logError(
'read local health notification record failed', error, stackTrace);
return const HealthRawLocalNotificationRecord();
}
}
List<HealthRawLocalNotification> _buildSleepNotificationsSafely(
HealthRawStressCalculationResult result,
HealthRawLocalNotificationRecord record,
) {
try {
return HealthRawLocalNotificationBuilder(l10n).build(
result: result.copyWith(
hrvStressPoints: const <HealthRawHrvStressPoint>[],
realtimeStressPoints: const <HealthRawRealtimeStressPoint>[],
),
hasExistingHrv: false,
realtimeWindow: const <HealthRawRealtimeStressPoint>[],
record: record,
);
} catch (error, stackTrace) {
_logError('build sleep local notification failed', error, stackTrace);
return const <HealthRawLocalNotification>[];
}
}
List<HealthRawLocalNotification> _buildHrvNotificationsSafely({
required HealthRawStressCalculationResult result,
required bool hasExistingHrv,
required HealthRawLocalNotificationRecord record,
}) {
try {
return HealthRawLocalNotificationBuilder(l10n).build(
result: result.copyWith(
realtimeStressPoints: const <HealthRawRealtimeStressPoint>[],
sleepResults: const <HealthRawSleepResult>[],
),
hasExistingHrv: hasExistingHrv,
realtimeWindow: const <HealthRawRealtimeStressPoint>[],
record: record,
);
} catch (error, stackTrace) {
_logError('build hrv local notification failed', error, stackTrace);
return const <HealthRawLocalNotification>[];
}
}
Future<List<HealthRawLocalNotification>>
_buildRealtimeStressNotificationsSafely(
HealthRawStressCalculationResult result,
HealthRawLocalNotificationRecord record,
) async {
try {
final latestRealtimeStressPoint = result.realtimeStressPoints.isEmpty
? null
... ... @@ -500,41 +419,23 @@ class HealthRawDataCoreService {
1,
endTime: latestRealtimeStressPoint.rawEndTime,
);
return HealthRawLocalNotificationBuilder(l10n).build(
result: result.copyWith(
hrvStressPoints: const <HealthRawHrvStressPoint>[],
sleepResults: const <HealthRawSleepResult>[],
),
hasExistingHrv: false,
final record = await _localNotificationDispatcher.readRecord(
result.userId,
);
final notifications = HealthRawLocalNotificationBuilder(l10n).build(
result: result,
hasExistingHrv: hasExistingHrv,
realtimeWindow: realtimeWindow,
record: record,
);
} catch (error, stackTrace) {
_logError(
'build realtime stress local notification failed',
error,
stackTrace,
);
return const <HealthRawLocalNotification>[];
}
}
Future<bool> _sendLocalNotificationSafely({
required int userId,
required HealthRawLocalNotification notification,
}) async {
try {
return await _localNotificationDispatcher.sendOne(
userId: userId,
notification: notification,
if (notifications.isEmpty) return;
final sentNotifications = await _localNotificationDispatcher.sendAll(
userId: result.userId,
notifications: notifications,
);
_scheduleRealtimeStressServerPush(sentNotifications);
} catch (error, stackTrace) {
_logError(
'send ${notification.recordType.name} local notification failed',
error,
stackTrace,
);
return false;
_logError('send local health notifications failed', error, stackTrace);
}
}
... ...
... ... @@ -219,30 +219,22 @@ class HealthRawLocalNotificationDispatcher {
final PlatformHostApi _platformApi;
final HealthRawLocalNotificationRecordStore _recordStore;
Future<bool> sendOne({
required int userId,
required HealthRawLocalNotification notification,
}) async {
final sent = await _platformApi.sendLocalNotification(
notification.title,
notification.content,
notification.link,
);
if (!sent) return false;
final record = await _recordStore.read(userId);
await _recordStore.write(userId, record.withNotification(notification));
return true;
}
Future<List<HealthRawLocalNotification>> sendAll({
required int userId,
required Iterable<HealthRawLocalNotification> notifications,
}) async {
var record = await _recordStore.read(userId);
final sentNotifications = <HealthRawLocalNotification>[];
for (final notification in notifications) {
if (await sendOne(userId: userId, notification: notification)) {
sentNotifications.add(notification);
}
final sent = await _platformApi.sendLocalNotification(
notification.title,
notification.content,
notification.link,
);
if (!sent) continue;
sentNotifications.add(notification);
record = record.withNotification(notification);
await _recordStore.write(userId, record);
}
return sentNotifications;
}
... ...
... ... @@ -2,7 +2,6 @@ import 'dart:async';
import 'package:doublefeel_flutter/core/result/app_result.dart';
import 'package:doublefeel_flutter/core/services/health_raw_data_core_service.dart';
import 'package:doublefeel_flutter/core/services/health_raw_local_notification.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_local_data_convert.dart';
import 'package:doublefeel_flutter/data/datasource/health/health_local_datasource.dart';
import 'package:doublefeel_flutter/data/models/enums/app_enums.dart';
... ... @@ -643,108 +642,6 @@ void main() {
expect(rows.realtimeRows.single['uploaded'], 1);
});
test('hrv notification still sends when realtime window query fails',
() async {
final base =
DateTime.now().millisecondsSinceEpoch ~/ 1000 - Duration.secondsPerDay;
final api = _FakeHealthKitRawDataHostApi();
api.setPoints(HealthDataUploadType.hrv.type, [
_point(base + 60, 30),
_point(base + 360, 34),
]);
api.setPoints(HealthDataUploadType.heartRate.type, [
for (var i = 0; i < 12; i++) _point(base + 60 + i * 60, 70),
]);
api.setPoints(HealthDataUploadType.restingHeartRate.type, [
_point(base + 30, 60),
]);
final store = _MemoryHealthRawStressLocalStore()
..throwOnRealtimeNotificationWindowQuery = true;
await store.upsertResult(
HealthRawStressCalculationResult(
userId: 42,
hrvStressPoints: [_hrvStressPoint(base + 60)],
realtimeStressPoints: const <HealthRawRealtimeStressPoint>[],
dailyStressPoints: const <HealthRawDailyStressPoint>[],
),
);
final notificationDispatcher = _FakeLocalNotificationDispatcher();
final service = HealthRawDataCoreService(
healthApi: _FakeHealthKitHostApi(),
rawDataApi: api,
localStore: store,
userIdProvider: () => 42,
uploadResultsAfterCalculation: false,
localNotificationDispatcher: notificationDispatcher,
);
await service.syncAndStore(
startTime: base,
endTime: base + 900,
readChunkDays: 1,
);
expect(
notificationDispatcher.sentRecordTypes,
contains(HealthRawLocalNotificationRecordType.hrv),
);
});
test('sleep notification still sends after hrv send fails', () async {
final base =
DateTime.now().millisecondsSinceEpoch ~/ 1000 - Duration.secondsPerDay;
final sleepStart = base + 60;
final sleepEnd = sleepStart + const Duration(hours: 7).inSeconds;
final api = _FakeHealthKitRawDataHostApi();
api.setPoints(HealthDataUploadType.hrv.type, [
_point(base + 60, 30),
_point(base + 360, 34),
]);
api.setPoints(HealthDataUploadType.heartRate.type, [
for (var i = 0; i < 12; i++) _point(base + 60 + i * 60, 70),
]);
api.setPoints(HealthDataUploadType.restingHeartRate.type, [
_point(base + 30, 60),
]);
api.setSleepPoints([
HealthKitRawDataPoint(
dataType: 3,
startTime: sleepStart,
endTime: sleepEnd,
),
]);
final store = _MemoryHealthRawStressLocalStore();
await store.upsertResult(
HealthRawStressCalculationResult(
userId: 42,
hrvStressPoints: [_hrvStressPoint(base + 60)],
realtimeStressPoints: const <HealthRawRealtimeStressPoint>[],
dailyStressPoints: const <HealthRawDailyStressPoint>[],
),
);
final notificationDispatcher = _FakeLocalNotificationDispatcher()
..throwOnRecordTypes.add(HealthRawLocalNotificationRecordType.hrv);
final service = HealthRawDataCoreService(
healthApi: _FakeHealthKitHostApi(),
rawDataApi: api,
localStore: store,
userIdProvider: () => 42,
uploadResultsAfterCalculation: false,
localNotificationDispatcher: notificationDispatcher,
);
await service.syncAndStore(
startTime: base,
endTime: sleepEnd + 60,
readChunkDays: 1,
);
expect(
notificationDispatcher.sentRecordTypes,
contains(HealthRawLocalNotificationRecordType.sleep),
);
});
test('local data source returns earliest local hr start time', () async {
const base = 1800000000;
final api = _FakeHealthKitRawDataHostApi();
... ... @@ -955,31 +852,6 @@ class _FakeHealthKitHostApi extends HealthKitHostApi {
}
}
class _FakeLocalNotificationDispatcher
extends HealthRawLocalNotificationDispatcher {
final sentRecordTypes = <HealthRawLocalNotificationRecordType>[];
final throwOnRecordTypes = <HealthRawLocalNotificationRecordType>{};
var record = const HealthRawLocalNotificationRecord();
@override
Future<HealthRawLocalNotificationRecord> readRecord(int userId) async {
return record;
}
@override
Future<bool> sendOne({
required int userId,
required HealthRawLocalNotification notification,
}) async {
if (throwOnRecordTypes.contains(notification.recordType)) {
throw StateError('send ${notification.recordType.name} failed');
}
sentRecordTypes.add(notification.recordType);
record = record.withNotification(notification);
return true;
}
}
class _ReadCall {
const _ReadCall(this.dataType, this.startTime, this.endTime);
... ... @@ -997,7 +869,6 @@ class _MemoryHealthRawStressLocalStore extends HealthRawStressLocalStore {
final Map<int, List<HealthRawDailyStressPoint>> _daily = {};
final Map<int, List<HealthRawSleepResult>> _sleep = {};
final List<String> operationLog;
var throwOnRealtimeNotificationWindowQuery = false;
void insertDailyStress(HealthRawDailyStressPoint point) {
final byDate = <int, HealthRawDailyStressPoint>{
... ... @@ -1168,10 +1039,6 @@ class _MemoryHealthRawStressLocalStore extends HealthRawStressLocalStore {
required int endTime,
}) async {
operationLog.add('queryRealtimeStressPoints');
if (throwOnRealtimeNotificationWindowQuery &&
endTime - startTime <= Duration.secondsPerHour) {
throw StateError('realtime notification window query failed');
}
return (_realtime[userId] ?? <HealthRawRealtimeStressPoint>[])
.where((e) => e.rawEndTime >= startTime && e.rawEndTime <= endTime)
.toList();
... ...