Skip to content

fix(notification): Paginate and bulk-insert follower fan-out in notifyFollowers()#64

Merged
gymynnym merged 3 commits intomasterfrom
copilot/improve-notify-followers-performance
Mar 29, 2026
Merged

fix(notification): Paginate and bulk-insert follower fan-out in notifyFollowers()#64
gymynnym merged 3 commits intomasterfrom
copilot/improve-notify-followers-performance

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 27, 2026

notifyFollowers() loaded the entire follower list into memory and issued one INSERT per follower inside a single async task — an O(n) memory and O(n) DB round-trip problem that degrades badly at scale.

Changes

  • PostNotificationEventListener: Replace unbounded findFollowersByFollowee() with a paginated do-while loop (FOLLOWER_BATCH_SIZE = 100); skip empty pages to avoid unnecessary DB calls
  • NotificationService: Add createNotifications(List<CreateNotificationDTO>) using saveAll() for a single bulk insert per page, with per-batch SSE event publishing
  • UserFollowRepository: Remove the non-paginated findFollowersByFollowee(): List<User> query (was the sole source of the unbounded load)
// Before: load all N followers, N individual INSERTs
val followers = userFollowRepository.findFollowersByFollowee(writer)
followers.forEach { notificationService.createNotification(createRequest(it)) }

// After: paginate in batches of 100, 1 bulk INSERT per page
do {
    val page = userFollowRepository.findFollowersByFolloweeOrderByIdDesc(writer, PageRequest.of(pageNumber, FOLLOWER_BATCH_SIZE))
    if (page.content.isNotEmpty()) {
        notificationService.createNotifications(page.content.map { createRequest(it) })
    }
    pageNumber++
} while (page.hasNext())

Tests

  • NotificationServiceTest: adds CreateNotificationsTest covering bulk save and event publishing
  • PostNotificationEventListenerTest: new test class covering single-page fan-out, multi-page pagination, entity-not-found early exit, and empty-follower no-op

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.foojay.io
    • Triggering command: /usr/lib/jvm/temurin-25-jdk-amd64/bin/java /usr/lib/jvm/temurin-25-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED --enable-native-access=ALL-UNNAMED -XX:MaxMetaspaceSize=384m -XX:&#43;HeapDumpOnOutOfMemoryError -Xms256m -Xmx512m (dns block)
    • Triggering command: /tmp/java24/bin/java /tmp/java24/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED --enable-native-access=ALL-UNNAMED -XX:MaxMetaspaceSize=384m -XX:&#43;HeapDumpOnOutOfMemoryError -Xms256m -Xmx512m (dns block)

If you need me to access, download, or install something from one of these locations, you can either:


⌨️ Start Copilot coding agent tasks without leaving your editor — available in VS Code, Visual Studio, JetBrains IDEs and Eclipse.

Copilot AI changed the title [WIP] Optimize notifyFollowers() for scalability and performance fix(notification): Paginate and bulk-insert follower fan-out in notifyFollowers() Mar 27, 2026
Copilot AI requested a review from gymynnym March 27, 2026 07:50
@gymynnym gymynnym force-pushed the copilot/improve-notify-followers-performance branch from 285431a to c896843 Compare March 29, 2026 08:52
@gymynnym gymynnym marked this pull request as ready for review March 29, 2026 08:54
@gymynnym gymynnym merged commit 58b75c4 into master Mar 29, 2026
1 check passed
@gymynnym gymynnym deleted the copilot/improve-notify-followers-performance branch March 29, 2026 09:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants