@@ -201,62 +201,64 @@ 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 > [];
205+ final userDeviceTokensMapForSending = < String , List <String >> {};
225206
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);
207+ for (final userId in userIds) {
208+ final userDeviceTokens = userDeviceTokensMap[userId];
209+ if (userDeviceTokens != null && userDeviceTokens.isNotEmpty) {
210+ final notificationId = ObjectId ();
211+ final notification = InAppNotification (
212+ id: notificationId.oid,
213+ userId: userId,
214+ payload: PushNotificationPayload (
215+ title: headline.title,
216+ body: headline.excerpt,
217+ imageUrl: headline.imageUrl,
218+ data: {
219+ 'notificationType' :
220+ PushNotificationSubscriptionDeliveryType .breakingOnly.name,
221+ 'contentType' : 'headline' ,
222+ 'headlineId' : headline.id,
223+ 'notificationId' : notificationId.oid,
224+ },
225+ ),
226+ createdAt: DateTime .now (),
227+ );
228+ notificationsToCreate.add (notification);
229+ userDeviceTokensMapForSending[userId] = userDeviceTokens;
256230 }
257231 }
258232
259- // Await all the send operations to complete in parallel.
233+ // 8. Create all InAppNotification documents in parallel.
234+ final createFutures = notificationsToCreate.map (
235+ (notification) =>
236+ _inAppNotificationRepository.create (item: notification),
237+ );
238+ await Future .wait (createFutures);
239+ _log.info (
240+ 'Successfully created ${notificationsToCreate .length } in-app notifications.' ,
241+ );
242+
243+ // 9. Dispatch all push notifications in parallel.
244+ final sendFutures = notificationsToCreate.map ((notification) {
245+ final userDeviceTokens =
246+ userDeviceTokensMapForSending[notification.userId] ?? [];
247+ return client
248+ .sendBulkNotifications (
249+ deviceTokens: userDeviceTokens,
250+ payload: notification.payload,
251+ )
252+ .then ((result) {
253+ // After the send completes, trigger the cleanup process for
254+ // any failed tokens. This is a fire-and-forget operation.
255+ unawaited (
256+ _cleanupInvalidDevices (result.failedTokens, primaryProvider),
257+ );
258+ });
259+ });
260+
261+ // Await all the send operations to complete.
260262 await Future .wait (sendFutures);
261263
262264 _log.info (
0 commit comments