Commit e93ef899baf19d38b72406b801454824ec19c38d
1 parent
5e4f526f
Revert "feat(ui):修复hr实时压力推送抛异常导致后续代码不执行"
This reverts commit 5e4f526f.
Showing
3 changed files
with
22 additions
and
262 deletions
| @@ -404,87 +404,6 @@ class HealthRawDataCoreService { | @@ -404,87 +404,6 @@ class HealthRawDataCoreService { | ||
| 404 | result.sleepResults.isEmpty) { | 404 | result.sleepResults.isEmpty) { |
| 405 | return; | 405 | return; |
| 406 | } | 406 | } |
| 407 | - final record = await _readLocalNotificationRecord(result.userId); | ||
| 408 | - final notifications = <HealthRawLocalNotification>[ | ||
| 409 | - ..._buildSleepNotificationsSafely(result, record), | ||
| 410 | - ..._buildHrvNotificationsSafely( | ||
| 411 | - result: result, | ||
| 412 | - hasExistingHrv: hasExistingHrv, | ||
| 413 | - record: record, | ||
| 414 | - ), | ||
| 415 | - ...await _buildRealtimeStressNotificationsSafely(result, record), | ||
| 416 | - ]; | ||
| 417 | - for (final notification in notifications) { | ||
| 418 | - final sent = await _sendLocalNotificationSafely( | ||
| 419 | - userId: result.userId, | ||
| 420 | - notification: notification, | ||
| 421 | - ); | ||
| 422 | - if (sent && | ||
| 423 | - notification.recordType == | ||
| 424 | - HealthRawLocalNotificationRecordType.realtimeStress) { | ||
| 425 | - _scheduleRealtimeStressServerPush([notification]); | ||
| 426 | - } | ||
| 427 | - } | ||
| 428 | - } | ||
| 429 | - | ||
| 430 | - Future<HealthRawLocalNotificationRecord> _readLocalNotificationRecord( | ||
| 431 | - int userId, | ||
| 432 | - ) async { | ||
| 433 | - try { | ||
| 434 | - return await _localNotificationDispatcher.readRecord(userId); | ||
| 435 | - } catch (error, stackTrace) { | ||
| 436 | - _logError( | ||
| 437 | - 'read local health notification record failed', error, stackTrace); | ||
| 438 | - return const HealthRawLocalNotificationRecord(); | ||
| 439 | - } | ||
| 440 | - } | ||
| 441 | - | ||
| 442 | - List<HealthRawLocalNotification> _buildSleepNotificationsSafely( | ||
| 443 | - HealthRawStressCalculationResult result, | ||
| 444 | - HealthRawLocalNotificationRecord record, | ||
| 445 | - ) { | ||
| 446 | - try { | ||
| 447 | - return HealthRawLocalNotificationBuilder(l10n).build( | ||
| 448 | - result: result.copyWith( | ||
| 449 | - hrvStressPoints: const <HealthRawHrvStressPoint>[], | ||
| 450 | - realtimeStressPoints: const <HealthRawRealtimeStressPoint>[], | ||
| 451 | - ), | ||
| 452 | - hasExistingHrv: false, | ||
| 453 | - realtimeWindow: const <HealthRawRealtimeStressPoint>[], | ||
| 454 | - record: record, | ||
| 455 | - ); | ||
| 456 | - } catch (error, stackTrace) { | ||
| 457 | - _logError('build sleep local notification failed', error, stackTrace); | ||
| 458 | - return const <HealthRawLocalNotification>[]; | ||
| 459 | - } | ||
| 460 | - } | ||
| 461 | - | ||
| 462 | - List<HealthRawLocalNotification> _buildHrvNotificationsSafely({ | ||
| 463 | - required HealthRawStressCalculationResult result, | ||
| 464 | - required bool hasExistingHrv, | ||
| 465 | - required HealthRawLocalNotificationRecord record, | ||
| 466 | - }) { | ||
| 467 | - try { | ||
| 468 | - return HealthRawLocalNotificationBuilder(l10n).build( | ||
| 469 | - result: result.copyWith( | ||
| 470 | - realtimeStressPoints: const <HealthRawRealtimeStressPoint>[], | ||
| 471 | - sleepResults: const <HealthRawSleepResult>[], | ||
| 472 | - ), | ||
| 473 | - hasExistingHrv: hasExistingHrv, | ||
| 474 | - realtimeWindow: const <HealthRawRealtimeStressPoint>[], | ||
| 475 | - record: record, | ||
| 476 | - ); | ||
| 477 | - } catch (error, stackTrace) { | ||
| 478 | - _logError('build hrv local notification failed', error, stackTrace); | ||
| 479 | - return const <HealthRawLocalNotification>[]; | ||
| 480 | - } | ||
| 481 | - } | ||
| 482 | - | ||
| 483 | - Future<List<HealthRawLocalNotification>> | ||
| 484 | - _buildRealtimeStressNotificationsSafely( | ||
| 485 | - HealthRawStressCalculationResult result, | ||
| 486 | - HealthRawLocalNotificationRecord record, | ||
| 487 | - ) async { | ||
| 488 | try { | 407 | try { |
| 489 | final latestRealtimeStressPoint = result.realtimeStressPoints.isEmpty | 408 | final latestRealtimeStressPoint = result.realtimeStressPoints.isEmpty |
| 490 | ? null | 409 | ? null |
| @@ -500,41 +419,23 @@ class HealthRawDataCoreService { | @@ -500,41 +419,23 @@ class HealthRawDataCoreService { | ||
| 500 | 1, | 419 | 1, |
| 501 | endTime: latestRealtimeStressPoint.rawEndTime, | 420 | endTime: latestRealtimeStressPoint.rawEndTime, |
| 502 | ); | 421 | ); |
| 503 | - return HealthRawLocalNotificationBuilder(l10n).build( | ||
| 504 | - result: result.copyWith( | ||
| 505 | - hrvStressPoints: const <HealthRawHrvStressPoint>[], | ||
| 506 | - sleepResults: const <HealthRawSleepResult>[], | ||
| 507 | - ), | ||
| 508 | - hasExistingHrv: false, | 422 | + final record = await _localNotificationDispatcher.readRecord( |
| 423 | + result.userId, | ||
| 424 | + ); | ||
| 425 | + final notifications = HealthRawLocalNotificationBuilder(l10n).build( | ||
| 426 | + result: result, | ||
| 427 | + hasExistingHrv: hasExistingHrv, | ||
| 509 | realtimeWindow: realtimeWindow, | 428 | realtimeWindow: realtimeWindow, |
| 510 | record: record, | 429 | record: record, |
| 511 | ); | 430 | ); |
| 512 | - } catch (error, stackTrace) { | ||
| 513 | - _logError( | ||
| 514 | - 'build realtime stress local notification failed', | ||
| 515 | - error, | ||
| 516 | - stackTrace, | ||
| 517 | - ); | ||
| 518 | - return const <HealthRawLocalNotification>[]; | ||
| 519 | - } | ||
| 520 | - } | ||
| 521 | - | ||
| 522 | - Future<bool> _sendLocalNotificationSafely({ | ||
| 523 | - required int userId, | ||
| 524 | - required HealthRawLocalNotification notification, | ||
| 525 | - }) async { | ||
| 526 | - try { | ||
| 527 | - return await _localNotificationDispatcher.sendOne( | ||
| 528 | - userId: userId, | ||
| 529 | - notification: notification, | 431 | + if (notifications.isEmpty) return; |
| 432 | + final sentNotifications = await _localNotificationDispatcher.sendAll( | ||
| 433 | + userId: result.userId, | ||
| 434 | + notifications: notifications, | ||
| 530 | ); | 435 | ); |
| 436 | + _scheduleRealtimeStressServerPush(sentNotifications); | ||
| 531 | } catch (error, stackTrace) { | 437 | } catch (error, stackTrace) { |
| 532 | - _logError( | ||
| 533 | - 'send ${notification.recordType.name} local notification failed', | ||
| 534 | - error, | ||
| 535 | - stackTrace, | ||
| 536 | - ); | ||
| 537 | - return false; | 438 | + _logError('send local health notifications failed', error, stackTrace); |
| 538 | } | 439 | } |
| 539 | } | 440 | } |
| 540 | 441 |
| @@ -219,30 +219,22 @@ class HealthRawLocalNotificationDispatcher { | @@ -219,30 +219,22 @@ class HealthRawLocalNotificationDispatcher { | ||
| 219 | final PlatformHostApi _platformApi; | 219 | final PlatformHostApi _platformApi; |
| 220 | final HealthRawLocalNotificationRecordStore _recordStore; | 220 | final HealthRawLocalNotificationRecordStore _recordStore; |
| 221 | 221 | ||
| 222 | - Future<bool> sendOne({ | ||
| 223 | - required int userId, | ||
| 224 | - required HealthRawLocalNotification notification, | ||
| 225 | - }) async { | ||
| 226 | - final sent = await _platformApi.sendLocalNotification( | ||
| 227 | - notification.title, | ||
| 228 | - notification.content, | ||
| 229 | - notification.link, | ||
| 230 | - ); | ||
| 231 | - if (!sent) return false; | ||
| 232 | - final record = await _recordStore.read(userId); | ||
| 233 | - await _recordStore.write(userId, record.withNotification(notification)); | ||
| 234 | - return true; | ||
| 235 | - } | ||
| 236 | - | ||
| 237 | Future<List<HealthRawLocalNotification>> sendAll({ | 222 | Future<List<HealthRawLocalNotification>> sendAll({ |
| 238 | required int userId, | 223 | required int userId, |
| 239 | required Iterable<HealthRawLocalNotification> notifications, | 224 | required Iterable<HealthRawLocalNotification> notifications, |
| 240 | }) async { | 225 | }) async { |
| 226 | + var record = await _recordStore.read(userId); | ||
| 241 | final sentNotifications = <HealthRawLocalNotification>[]; | 227 | final sentNotifications = <HealthRawLocalNotification>[]; |
| 242 | for (final notification in notifications) { | 228 | for (final notification in notifications) { |
| 243 | - if (await sendOne(userId: userId, notification: notification)) { | ||
| 244 | - sentNotifications.add(notification); | ||
| 245 | - } | 229 | + final sent = await _platformApi.sendLocalNotification( |
| 230 | + notification.title, | ||
| 231 | + notification.content, | ||
| 232 | + notification.link, | ||
| 233 | + ); | ||
| 234 | + if (!sent) continue; | ||
| 235 | + sentNotifications.add(notification); | ||
| 236 | + record = record.withNotification(notification); | ||
| 237 | + await _recordStore.write(userId, record); | ||
| 246 | } | 238 | } |
| 247 | return sentNotifications; | 239 | return sentNotifications; |
| 248 | } | 240 | } |
| @@ -2,7 +2,6 @@ import 'dart:async'; | @@ -2,7 +2,6 @@ import 'dart:async'; | ||
| 2 | 2 | ||
| 3 | import 'package:doublefeel_flutter/core/result/app_result.dart'; | 3 | import 'package:doublefeel_flutter/core/result/app_result.dart'; |
| 4 | import 'package:doublefeel_flutter/core/services/health_raw_data_core_service.dart'; | 4 | import 'package:doublefeel_flutter/core/services/health_raw_data_core_service.dart'; |
| 5 | -import 'package:doublefeel_flutter/core/services/health_raw_local_notification.dart'; | ||
| 6 | import 'package:doublefeel_flutter/data/datasource/health/health_local_data_convert.dart'; | 5 | import 'package:doublefeel_flutter/data/datasource/health/health_local_data_convert.dart'; |
| 7 | import 'package:doublefeel_flutter/data/datasource/health/health_local_datasource.dart'; | 6 | import 'package:doublefeel_flutter/data/datasource/health/health_local_datasource.dart'; |
| 8 | import 'package:doublefeel_flutter/data/models/enums/app_enums.dart'; | 7 | import 'package:doublefeel_flutter/data/models/enums/app_enums.dart'; |
| @@ -643,108 +642,6 @@ void main() { | @@ -643,108 +642,6 @@ void main() { | ||
| 643 | expect(rows.realtimeRows.single['uploaded'], 1); | 642 | expect(rows.realtimeRows.single['uploaded'], 1); |
| 644 | }); | 643 | }); |
| 645 | 644 | ||
| 646 | - test('hrv notification still sends when realtime window query fails', | ||
| 647 | - () async { | ||
| 648 | - final base = | ||
| 649 | - DateTime.now().millisecondsSinceEpoch ~/ 1000 - Duration.secondsPerDay; | ||
| 650 | - final api = _FakeHealthKitRawDataHostApi(); | ||
| 651 | - api.setPoints(HealthDataUploadType.hrv.type, [ | ||
| 652 | - _point(base + 60, 30), | ||
| 653 | - _point(base + 360, 34), | ||
| 654 | - ]); | ||
| 655 | - api.setPoints(HealthDataUploadType.heartRate.type, [ | ||
| 656 | - for (var i = 0; i < 12; i++) _point(base + 60 + i * 60, 70), | ||
| 657 | - ]); | ||
| 658 | - api.setPoints(HealthDataUploadType.restingHeartRate.type, [ | ||
| 659 | - _point(base + 30, 60), | ||
| 660 | - ]); | ||
| 661 | - final store = _MemoryHealthRawStressLocalStore() | ||
| 662 | - ..throwOnRealtimeNotificationWindowQuery = true; | ||
| 663 | - await store.upsertResult( | ||
| 664 | - HealthRawStressCalculationResult( | ||
| 665 | - userId: 42, | ||
| 666 | - hrvStressPoints: [_hrvStressPoint(base + 60)], | ||
| 667 | - realtimeStressPoints: const <HealthRawRealtimeStressPoint>[], | ||
| 668 | - dailyStressPoints: const <HealthRawDailyStressPoint>[], | ||
| 669 | - ), | ||
| 670 | - ); | ||
| 671 | - final notificationDispatcher = _FakeLocalNotificationDispatcher(); | ||
| 672 | - final service = HealthRawDataCoreService( | ||
| 673 | - healthApi: _FakeHealthKitHostApi(), | ||
| 674 | - rawDataApi: api, | ||
| 675 | - localStore: store, | ||
| 676 | - userIdProvider: () => 42, | ||
| 677 | - uploadResultsAfterCalculation: false, | ||
| 678 | - localNotificationDispatcher: notificationDispatcher, | ||
| 679 | - ); | ||
| 680 | - | ||
| 681 | - await service.syncAndStore( | ||
| 682 | - startTime: base, | ||
| 683 | - endTime: base + 900, | ||
| 684 | - readChunkDays: 1, | ||
| 685 | - ); | ||
| 686 | - | ||
| 687 | - expect( | ||
| 688 | - notificationDispatcher.sentRecordTypes, | ||
| 689 | - contains(HealthRawLocalNotificationRecordType.hrv), | ||
| 690 | - ); | ||
| 691 | - }); | ||
| 692 | - | ||
| 693 | - test('sleep notification still sends after hrv send fails', () async { | ||
| 694 | - final base = | ||
| 695 | - DateTime.now().millisecondsSinceEpoch ~/ 1000 - Duration.secondsPerDay; | ||
| 696 | - final sleepStart = base + 60; | ||
| 697 | - final sleepEnd = sleepStart + const Duration(hours: 7).inSeconds; | ||
| 698 | - final api = _FakeHealthKitRawDataHostApi(); | ||
| 699 | - api.setPoints(HealthDataUploadType.hrv.type, [ | ||
| 700 | - _point(base + 60, 30), | ||
| 701 | - _point(base + 360, 34), | ||
| 702 | - ]); | ||
| 703 | - api.setPoints(HealthDataUploadType.heartRate.type, [ | ||
| 704 | - for (var i = 0; i < 12; i++) _point(base + 60 + i * 60, 70), | ||
| 705 | - ]); | ||
| 706 | - api.setPoints(HealthDataUploadType.restingHeartRate.type, [ | ||
| 707 | - _point(base + 30, 60), | ||
| 708 | - ]); | ||
| 709 | - api.setSleepPoints([ | ||
| 710 | - HealthKitRawDataPoint( | ||
| 711 | - dataType: 3, | ||
| 712 | - startTime: sleepStart, | ||
| 713 | - endTime: sleepEnd, | ||
| 714 | - ), | ||
| 715 | - ]); | ||
| 716 | - final store = _MemoryHealthRawStressLocalStore(); | ||
| 717 | - await store.upsertResult( | ||
| 718 | - HealthRawStressCalculationResult( | ||
| 719 | - userId: 42, | ||
| 720 | - hrvStressPoints: [_hrvStressPoint(base + 60)], | ||
| 721 | - realtimeStressPoints: const <HealthRawRealtimeStressPoint>[], | ||
| 722 | - dailyStressPoints: const <HealthRawDailyStressPoint>[], | ||
| 723 | - ), | ||
| 724 | - ); | ||
| 725 | - final notificationDispatcher = _FakeLocalNotificationDispatcher() | ||
| 726 | - ..throwOnRecordTypes.add(HealthRawLocalNotificationRecordType.hrv); | ||
| 727 | - final service = HealthRawDataCoreService( | ||
| 728 | - healthApi: _FakeHealthKitHostApi(), | ||
| 729 | - rawDataApi: api, | ||
| 730 | - localStore: store, | ||
| 731 | - userIdProvider: () => 42, | ||
| 732 | - uploadResultsAfterCalculation: false, | ||
| 733 | - localNotificationDispatcher: notificationDispatcher, | ||
| 734 | - ); | ||
| 735 | - | ||
| 736 | - await service.syncAndStore( | ||
| 737 | - startTime: base, | ||
| 738 | - endTime: sleepEnd + 60, | ||
| 739 | - readChunkDays: 1, | ||
| 740 | - ); | ||
| 741 | - | ||
| 742 | - expect( | ||
| 743 | - notificationDispatcher.sentRecordTypes, | ||
| 744 | - contains(HealthRawLocalNotificationRecordType.sleep), | ||
| 745 | - ); | ||
| 746 | - }); | ||
| 747 | - | ||
| 748 | test('local data source returns earliest local hr start time', () async { | 645 | test('local data source returns earliest local hr start time', () async { |
| 749 | const base = 1800000000; | 646 | const base = 1800000000; |
| 750 | final api = _FakeHealthKitRawDataHostApi(); | 647 | final api = _FakeHealthKitRawDataHostApi(); |
| @@ -955,31 +852,6 @@ class _FakeHealthKitHostApi extends HealthKitHostApi { | @@ -955,31 +852,6 @@ class _FakeHealthKitHostApi extends HealthKitHostApi { | ||
| 955 | } | 852 | } |
| 956 | } | 853 | } |
| 957 | 854 | ||
| 958 | -class _FakeLocalNotificationDispatcher | ||
| 959 | - extends HealthRawLocalNotificationDispatcher { | ||
| 960 | - final sentRecordTypes = <HealthRawLocalNotificationRecordType>[]; | ||
| 961 | - final throwOnRecordTypes = <HealthRawLocalNotificationRecordType>{}; | ||
| 962 | - var record = const HealthRawLocalNotificationRecord(); | ||
| 963 | - | ||
| 964 | - @override | ||
| 965 | - Future<HealthRawLocalNotificationRecord> readRecord(int userId) async { | ||
| 966 | - return record; | ||
| 967 | - } | ||
| 968 | - | ||
| 969 | - @override | ||
| 970 | - Future<bool> sendOne({ | ||
| 971 | - required int userId, | ||
| 972 | - required HealthRawLocalNotification notification, | ||
| 973 | - }) async { | ||
| 974 | - if (throwOnRecordTypes.contains(notification.recordType)) { | ||
| 975 | - throw StateError('send ${notification.recordType.name} failed'); | ||
| 976 | - } | ||
| 977 | - sentRecordTypes.add(notification.recordType); | ||
| 978 | - record = record.withNotification(notification); | ||
| 979 | - return true; | ||
| 980 | - } | ||
| 981 | -} | ||
| 982 | - | ||
| 983 | class _ReadCall { | 855 | class _ReadCall { |
| 984 | const _ReadCall(this.dataType, this.startTime, this.endTime); | 856 | const _ReadCall(this.dataType, this.startTime, this.endTime); |
| 985 | 857 | ||
| @@ -997,7 +869,6 @@ class _MemoryHealthRawStressLocalStore extends HealthRawStressLocalStore { | @@ -997,7 +869,6 @@ class _MemoryHealthRawStressLocalStore extends HealthRawStressLocalStore { | ||
| 997 | final Map<int, List<HealthRawDailyStressPoint>> _daily = {}; | 869 | final Map<int, List<HealthRawDailyStressPoint>> _daily = {}; |
| 998 | final Map<int, List<HealthRawSleepResult>> _sleep = {}; | 870 | final Map<int, List<HealthRawSleepResult>> _sleep = {}; |
| 999 | final List<String> operationLog; | 871 | final List<String> operationLog; |
| 1000 | - var throwOnRealtimeNotificationWindowQuery = false; | ||
| 1001 | 872 | ||
| 1002 | void insertDailyStress(HealthRawDailyStressPoint point) { | 873 | void insertDailyStress(HealthRawDailyStressPoint point) { |
| 1003 | final byDate = <int, HealthRawDailyStressPoint>{ | 874 | final byDate = <int, HealthRawDailyStressPoint>{ |
| @@ -1168,10 +1039,6 @@ class _MemoryHealthRawStressLocalStore extends HealthRawStressLocalStore { | @@ -1168,10 +1039,6 @@ class _MemoryHealthRawStressLocalStore extends HealthRawStressLocalStore { | ||
| 1168 | required int endTime, | 1039 | required int endTime, |
| 1169 | }) async { | 1040 | }) async { |
| 1170 | operationLog.add('queryRealtimeStressPoints'); | 1041 | operationLog.add('queryRealtimeStressPoints'); |
| 1171 | - if (throwOnRealtimeNotificationWindowQuery && | ||
| 1172 | - endTime - startTime <= Duration.secondsPerHour) { | ||
| 1173 | - throw StateError('realtime notification window query failed'); | ||
| 1174 | - } | ||
| 1175 | return (_realtime[userId] ?? <HealthRawRealtimeStressPoint>[]) | 1042 | return (_realtime[userId] ?? <HealthRawRealtimeStressPoint>[]) |
| 1176 | .where((e) => e.rawEndTime >= startTime && e.rawEndTime <= endTime) | 1043 | .where((e) => e.rawEndTime >= startTime && e.rawEndTime <= endTime) |
| 1177 | .toList(); | 1044 | .toList(); |
-
Please register or login to post a comment