Skip to content

Commit 4e18a88

Browse files
authored
Merge pull request #103 from flutter-news-app-full-source-code/perf/parallelize-in-app-notification-creation
refactor(push notifications): improve efficiency and readability
2 parents b7557ef + 3587199 commit 4e18a88

File tree

3 files changed

+53
-53
lines changed

3 files changed

+53
-53
lines changed

lib/src/services/push_notification_service.dart

Lines changed: 51 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -201,62 +201,61 @@ class DefaultPushNotificationService implements IPushNotificationService {
201201

202202
// 7. Iterate through each subscribed user to create and send a
203203
// personalized notification.
204-
final sendFutures = <Future<void>>[];
205-
for (final userId in userIds) {
206-
// Create the InAppNotification record first to get its unique ID.
207-
final notificationId = ObjectId();
208-
final notification = InAppNotification(
209-
id: notificationId.oid,
210-
userId: userId,
211-
payload: PushNotificationPayload(
212-
title: headline.title,
213-
body: headline.excerpt,
214-
imageUrl: headline.imageUrl,
215-
data: {
216-
'notificationType':
217-
PushNotificationSubscriptionDeliveryType.breakingOnly.name,
218-
'contentType': 'headline',
219-
'headlineId': headline.id,
220-
'notificationId': notificationId.oid,
221-
},
222-
),
223-
createdAt: DateTime.now(),
224-
);
204+
final notificationsToCreate = <InAppNotification>[];
225205

226-
try {
227-
await _inAppNotificationRepository.create(item: notification);
228-
229-
// Efficiently retrieve the tokens for the current user from the map.
230-
final userDeviceTokens = userDeviceTokensMap[userId] ?? [];
231-
232-
if (userDeviceTokens.isNotEmpty) {
233-
// Add the send operation to the list of futures.
234-
// The result of this future will contain information about which
235-
// tokens succeeded and which failed.
236-
sendFutures.add(
237-
client
238-
.sendBulkNotifications(
239-
deviceTokens: userDeviceTokens,
240-
payload: notification.payload,
241-
)
242-
.then((result) {
243-
// After the send completes, trigger the cleanup process for
244-
// any failed tokens. This is a fire-and-forget operation.
245-
unawaited(
246-
_cleanupInvalidDevices(
247-
result.failedTokens,
248-
primaryProvider,
249-
),
250-
);
251-
}),
252-
);
253-
}
254-
} catch (e, s) {
255-
_log.severe('Failed to process notification for user $userId.', e, s);
206+
for (final userId in userIds) {
207+
final userDeviceTokens = userDeviceTokensMap[userId];
208+
if (userDeviceTokens != null && userDeviceTokens.isNotEmpty) {
209+
final notificationId = ObjectId();
210+
final notification = InAppNotification(
211+
id: notificationId.oid,
212+
userId: userId,
213+
payload: PushNotificationPayload(
214+
title: headline.title,
215+
body: headline.excerpt,
216+
imageUrl: headline.imageUrl,
217+
data: {
218+
'notificationType':
219+
PushNotificationSubscriptionDeliveryType.breakingOnly.name,
220+
'contentType': 'headline',
221+
'headlineId': headline.id,
222+
'notificationId': notificationId.oid,
223+
},
224+
),
225+
createdAt: DateTime.now(),
226+
);
227+
notificationsToCreate.add(notification);
256228
}
257229
}
258230

259-
// Await all the send operations to complete in parallel.
231+
// 8. Create all InAppNotification documents in parallel.
232+
final createFutures = notificationsToCreate.map(
233+
(notification) =>
234+
_inAppNotificationRepository.create(item: notification),
235+
);
236+
await Future.wait(createFutures);
237+
_log.info(
238+
'Successfully created ${notificationsToCreate.length} in-app notifications.',
239+
);
240+
241+
// 9. Dispatch all push notifications in parallel.
242+
final sendFutures = notificationsToCreate.map((notification) {
243+
final userDeviceTokens = userDeviceTokensMap[notification.userId] ?? [];
244+
return client!
245+
.sendBulkNotifications(
246+
deviceTokens: userDeviceTokens,
247+
payload: notification.payload,
248+
)
249+
.then((result) {
250+
// After the send completes, trigger the cleanup process for
251+
// any failed tokens. This is a fire-and-forget operation.
252+
unawaited(
253+
_cleanupInvalidDevices(result.failedTokens, primaryProvider),
254+
);
255+
});
256+
});
257+
258+
// Await all the send operations to complete.
260259
await Future.wait(sendFutures);
261260

262261
_log.info(

pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ packages:
249249
source: git
250250
version: "1.0.1"
251251
equatable:
252-
dependency: transitive
252+
dependency: "direct main"
253253
description:
254254
name: equatable
255255
sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7"

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ dependencies:
4040
git:
4141
url: https://github.com/flutter-news-app-full-source-code/email-sendgrid.git
4242
ref: v1.0.1
43+
equatable: ^2.0.7
4344
http_client:
4445
git:
4546
url: https://github.com/flutter-news-app-full-source-code/http-client.git

0 commit comments

Comments
 (0)