Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package org.ole.planet.myplanet.repository

data class NotificationData(
val type: String,
val message: String,
val relatedId: String?
)

interface NotificationRepository {
suspend fun getUnreadCount(userId: String?): Int
suspend fun updateResourceNotification(userId: String?, resourceCount: Int)
Expand All @@ -11,4 +17,9 @@ interface NotificationRepository {
relatedId: String?,
userId: String?,
)
suspend fun createNotificationsBatch(
notifications: List<NotificationData>,
userId: String?
)
suspend fun cleanupDuplicateNotifications(userId: String?)
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,34 +50,82 @@ class NotificationRepositoryImpl @Inject constructor(
}.toInt()
}

override suspend fun createNotificationsBatch(
notifications: List<NotificationData>,
userId: String?
) {
if (notifications.isEmpty() || userId == null) return

val actualUserId = userId

// Pre-fetch all existing notifications for this user in a single query
val existingNotifications = withRealmAsync { realm ->
realm.where(RealmNotification::class.java)
.equalTo("userId", actualUserId)
.findAll()
.map { notif ->
// Create a unique key for fast lookup
val key = "${notif.type}:${notif.relatedId ?: "null"}"
key to notif
}
.toMap()
}

// Filter out notifications that already exist
val notificationsToCreate = notifications.filter { notif ->
val key = "${notif.type}:${notif.relatedId ?: "null"}"
!existingNotifications.containsKey(key)
}

// Create only the new notifications in a single transaction
if (notificationsToCreate.isNotEmpty()) {
executeTransaction { realm ->
notificationsToCreate.forEach { notif ->
realm.createObject(RealmNotification::class.java, UUID.randomUUID().toString()).apply {
this.userId = actualUserId
this.type = notif.type
this.message = notif.message
this.relatedId = notif.relatedId
this.createdAt = Date()
}
}
}
}
}

override suspend fun updateResourceNotification(userId: String?, resourceCount: Int) {
userId ?: return

val notificationId = "$userId:resource:count"
val existingNotification = findByField(RealmNotification::class.java, "id", notificationId)

if (resourceCount > 0) {
val previousCount = existingNotification?.message?.toIntOrNull() ?: 0
val countChanged = previousCount != resourceCount
executeTransaction { realm ->
val existingNotification = realm.where(RealmNotification::class.java)
.equalTo("id", notificationId)
.findFirst()

val notification = existingNotification?.apply {
message = "$resourceCount"
relatedId = "$resourceCount"
if (countChanged) {
this.isRead = false
this.createdAt = Date()
if (resourceCount > 0) {
val previousCount = existingNotification?.message?.toIntOrNull() ?: 0
val countChanged = previousCount != resourceCount

if (existingNotification != null) {
existingNotification.message = "$resourceCount"
existingNotification.relatedId = "$resourceCount"
if (countChanged) {
existingNotification.isRead = false
existingNotification.createdAt = Date()
}
} else {
realm.createObject(RealmNotification::class.java, notificationId).apply {
this.userId = userId
this.type = "resource"
this.message = "$resourceCount"
this.relatedId = "$resourceCount"
this.createdAt = Date()
}
}
} ?: RealmNotification().apply {
this.id = notificationId
this.userId = userId
this.type = "resource"
this.message = "$resourceCount"
this.relatedId = "$resourceCount"
this.createdAt = Date()
} else {
existingNotification?.deleteFromRealm()
}
save(notification)
} else {
existingNotification?.let { delete(RealmNotification::class.java, "id", it.id) }
}
}

Expand Down Expand Up @@ -115,5 +163,41 @@ class NotificationRepositoryImpl @Inject constructor(
}
return updatedIds
}

override suspend fun cleanupDuplicateNotifications(userId: String?) {
if (userId == null) return

// Get all notifications for this user
val allNotifications = withRealmAsync { realm ->
realm.where(RealmNotification::class.java)
.equalTo("userId", userId)
.findAll()
.let { realm.copyFromRealm(it) }
}

// Group by type+relatedId, keep only the most recent one
val notificationsToKeep = allNotifications
.groupBy { "${it.type}:${it.relatedId ?: "null"}" }
.mapValues { (_, notifications) ->
// Keep the most recent one (latest createdAt)
notifications.maxByOrNull { it.createdAt?.time ?: 0L }
}
.values
.filterNotNull()

val idsToKeep = notificationsToKeep.map { it.id }.toSet()
val idsToDelete = allNotifications.map { it.id }.filter { !idsToKeep.contains(it) }

if (idsToDelete.isNotEmpty()) {
executeTransaction { realm ->
idsToDelete.forEach { idToDelete ->
realm.where(RealmNotification::class.java)
.equalTo("id", idToDelete)
.findFirst()
?.deleteFromRealm()
}
}
}
}
}

Loading