Fix new connection requests coming back as not being there when they are and perf problems with notification processing

codemagic-setup
Hank Grabowski 2023-05-08 14:24:45 -04:00
rodzic ed41a97db0
commit 1ff41be6e8
3 zmienionych plików z 131 dodań i 86 usunięć

Wyświetl plik

@ -41,9 +41,6 @@ import '../services/network_status_service.dart';
import '../utils/network_utils.dart';
import 'paging_data.dart';
const _maxProcessingMillis = 3;
const _processingSleep = Duration(milliseconds: 1);
class DirectMessagingClient extends FriendicaClient {
static final _logger = Logger('$DirectMessagingClient');
@ -435,8 +432,8 @@ class NotificationsClient extends FriendicaClient {
final st = Stopwatch()..start();
for (final json in response.data) {
if (st.elapsedMilliseconds > _maxProcessingMillis) {
await Future.delayed(_processingSleep, () => st.reset());
if (st.elapsedMilliseconds > maxProcessingMillis) {
await Future.delayed(processingSleep, () => st.reset());
}
notifications.add(NotificationMastodonExtension.fromJson(json));
}
@ -483,8 +480,8 @@ class RelationshipsClient extends FriendicaClient {
final st = Stopwatch()..start();
for (final json in response.data) {
if (st.elapsedMilliseconds > _maxProcessingMillis) {
await Future.delayed(_processingSleep, () => st.reset());
if (st.elapsedMilliseconds > maxProcessingMillis) {
await Future.delayed(processingSleep, () => st.reset());
}
blocks.add(
ConnectionMastodonExtensions.fromJson(json)
@ -1029,8 +1026,8 @@ class TimelineClient extends FriendicaClient {
final finalResult = <TimelineEntry>[];
final st = Stopwatch()..start();
for (final json in postsJson) {
if (st.elapsedMilliseconds > _maxProcessingMillis) {
await Future.delayed(_processingSleep, () => st.reset());
if (st.elapsedMilliseconds > maxProcessingMillis) {
await Future.delayed(processingSleep, () => st.reset());
}
finalResult.add(TimelineEntryMastodonExtensions.fromJson(json));
}

Wyświetl plik

@ -20,6 +20,9 @@ const usePhpDebugging = true;
const maxViewPortalHeight = 750.0;
const maxViewPortalWidth = 750.0;
const maxProcessingMillis = 3;
const processingSleep = Duration(milliseconds: 1);
Future<bool?> showConfirmDialog(BuildContext context, String caption) {
return showDialog<bool>(
context: context,

Wyświetl plik

@ -1,7 +1,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:result_monad/result_monad.dart';
import 'package:uuid/uuid.dart';
import '../friendica_client/friendica_client.dart';
import '../friendica_client/paged_response.dart';
@ -57,7 +57,7 @@ class NotificationsManager extends ChangeNotifier {
}
FutureResult<List<UserNotification>, ExecError> updateNotifications() async {
const initialPull = 100;
const initialPull = 25;
final notificationsFromRefresh = <UserNotification>[];
if (_pm.pages.isEmpty) {
final result = await _pm.initialize(initialPull);
@ -151,75 +151,31 @@ class NotificationsManager extends ChangeNotifier {
}
}
getIt<NetworkStatusService>().startNotificationUpdate();
await getIt<ActiveProfileSelector<DirectMessageService>>()
.getForProfile(profile)
.transformAsync((dms) async => await dms.updateThreads());
final useActualRequests = getIt<FriendicaVersionChecker>()
.canUseFeature(RelaticaFeatures.usingActualFollowRequests);
if (useActualRequests) {
await getIt<ActiveProfileSelector<FollowRequestsManager>>()
.getForProfile(profile)
.transformAsync((fm) async => fm.update());
}
final notifications = <String, UserNotification>{};
notificationsFromRefresh.removeWhere((n) =>
n.type == NotificationType.direct_message ||
(useActualRequests && n.type == NotificationType.follow_request));
for (final n in notificationsFromRefresh) {
notifications[n.id] = n;
}
getIt<NetworkStatusService>().finishNotificationUpdate();
for (final n in buildUnreadMessageNotifications(useActualRequests)) {
notifications[n.id] = n;
}
_processNewNotifications(notifications.values, clearAtStart: true);
notifyListeners();
return Result.ok(notifications.values.toList());
return await _postFetchOperations(notificationsFromRefresh, true);
}
FutureResult<List<UserNotification>, ExecError>
loadNewerNotifications() async {
final notifications = <String, UserNotification>{};
final result = await _pm.previousFromBeginning();
result.match(onSuccess: (response) {
if (response.data.isEmpty) {
return;
}
for (final n in response.data) {
notifications[n.id] = n;
}
_processNewNotifications(notifications.values);
notifyListeners();
}, onError: (error) {
_logger.info('Error getting more updates: $error');
});
return result.mapValue((response) => response.data);
final result = await _pm
.previousFromBeginning()
.andThenAsync(
(page) async => await _postFetchOperations(page.data, false),
)
.withError(
(error) => _logger.info('Error getting more updates: $error'));
return result.execErrorCast();
}
FutureResult<List<UserNotification>, ExecError>
loadOlderNotifications() async {
final notifications = <String, UserNotification>{};
final result = await _pm.nextFromEnd();
result.match(onSuccess: (response) {
for (final n in response.data) {
notifications[n.id] = n;
}
notifyListeners();
}, onError: (error) {
_logger.info('Error getting more updates: $error');
});
_processNewNotifications(notifications.values);
return result.mapValue((response) => response.data);
final result = await _pm
.nextFromEnd()
.andThenAsync(
(page) async => await _postFetchOperations(page.data, false),
)
.withError(
(error) => _logger.info('Error getting more updates: $error'));
return result.execErrorCast();
}
FutureResult<bool, ExecError> markSeen(UserNotification notification) async {
@ -255,7 +211,10 @@ class NotificationsManager extends ChangeNotifier {
final latestMessage = t.messages
.reduce((s, m) => s.createdAt > m.createdAt ? s : m);
return UserNotification(
id: const Uuid().v4(),
id: (fromAccount.hashCode ^
t.parentUri.hashCode ^
t.title.hashCode)
.toString(),
type: NotificationType.direct_message,
fromId: fromAccount.id,
fromName: fromAccount.name,
@ -279,40 +238,126 @@ class NotificationsManager extends ChangeNotifier {
return [...dmsResult, ...followRequestResult];
}
FutureResult<List<UserNotification>, ExecError> _postFetchOperations(
List<UserNotification> notificationsFromRefresh,
bool clearAtStart,
) async {
getIt<NetworkStatusService>().startNotificationUpdate();
await getIt<ActiveProfileSelector<DirectMessageService>>()
.getForProfile(profile)
.transformAsync((dms) async => await dms.updateThreads());
final useActualRequests = getIt<FriendicaVersionChecker>()
.canUseFeature(RelaticaFeatures.usingActualFollowRequests);
if (useActualRequests) {
await getIt<ActiveProfileSelector<FollowRequestsManager>>()
.getForProfile(profile)
.transformAsync((fm) async => fm.update());
}
final notifications = <String, UserNotification>{};
notificationsFromRefresh.removeWhere((n) =>
n.type == NotificationType.direct_message ||
(useActualRequests && n.type == NotificationType.follow_request));
for (final n in notificationsFromRefresh) {
notifications[n.id] = n;
}
getIt<NetworkStatusService>().finishNotificationUpdate();
for (final n in buildUnreadMessageNotifications(useActualRequests)) {
notifications[n.id] = n;
}
_processNewNotifications(notifications.values, clearAtStart: clearAtStart);
notifyListeners();
return Result.ok(notifications.values.toList());
}
Future<void> _processNewNotifications(
Iterable<UserNotification> notifications, {
bool clearAtStart = false,
}) async {
if (clearAtStart) {
dms.clear();
connectionRequests.clear();
unread.clear();
read.clear();
final dmsMap = <String, UserNotification>{};
final crMap = <String, UserNotification>{};
final unreadMap = <String, UserNotification>{};
final readMap = <String, UserNotification>{};
final st = Stopwatch()..start();
if (!clearAtStart) {
for (int i = 0; i < dms.length; i++) {
dmsMap[dms[i].id] = dms[i];
}
if (st.elapsedMilliseconds > maxProcessingMillis) {
await Future.delayed(processingSleep, () => st.reset());
}
for (int i = 0; i < connectionRequests.length; i++) {
crMap[connectionRequests[i].id] = connectionRequests[i];
}
if (st.elapsedMilliseconds > maxProcessingMillis) {
await Future.delayed(processingSleep, () => st.reset());
}
for (int i = 0; i < unread.length; i++) {
unreadMap[unread[i].id] = unread[i];
}
if (st.elapsedMilliseconds > maxProcessingMillis) {
await Future.delayed(processingSleep, () => st.reset());
}
for (int i = 0; i < read.length; i++) {
readMap[read[i].id] = read[i];
}
}
dms.clear();
connectionRequests.clear();
unread.clear();
read.clear();
for (final n in notifications) {
if (st.elapsedMilliseconds > maxProcessingMillis) {
await Future.delayed(processingSleep, () => st.reset());
}
dmsMap.remove(n.id);
crMap.remove(n.id);
unreadMap.remove(n.id);
readMap.remove(n.id);
if (n.dismissed) {
read.add(n);
readMap[n.id] = n;
continue;
}
switch (n.type) {
case NotificationType.direct_message:
dms.add(n);
dmsMap[n.id] = n;
break;
case NotificationType.follow:
case NotificationType.follow_request:
connectionRequests.add(n);
crMap[n.id] = n;
break;
default:
unread.add(n);
unreadMap[n.id] = n;
}
}
dms.sort();
connectionRequests.sort();
unread.sort();
read.sort();
dms
..addAll(dmsMap.values)
..sort();
connectionRequests
..addAll(crMap.values)
..sort();
unread
..addAll(unreadMap.values)
..sort();
read
..addAll(readMap.values)
..sort();
}
static FutureResult<PagedResponse<List<UserNotification>>, ExecError>