Skip to content

fix:[NEXT-1916] Send all events, don't bail on errors#2384

Merged
arunpaladin merged 1 commit into
masterfrom
NEXT-1916-send-all-events
Jan 7, 2026
Merged

fix:[NEXT-1916] Send all events, don't bail on errors#2384
arunpaladin merged 1 commit into
masterfrom
NEXT-1916-send-all-events

Conversation

@kevin-paladin
Copy link
Copy Markdown
Collaborator

@kevin-paladin kevin-paladin commented Jan 6, 2026

Ensure each item in the list is processed standalone and won't have any impact on other items in the list. Ensure each record is processed, not only the first record

Summary by CodeRabbit

Release Notes

  • New Features

    • Added batch record processing support for notification delivery.
  • Bug Fixes

    • Improved error handling and robustness for notification publishing.
    • Enhanced logging for better visibility into notification operations.

✏️ Tip: You can customize this high-level summary in your review settings.

Ensure each item in the list is processed standalone and won't have any impact on other items in the list.
Ensure each record is processed, not only the first record
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 6, 2026

Walkthrough

The SendNotification Lambda class is refactored to support batch processing of SNS records with improved error handling, JSON parsing, and logging. Import statements are made explicit, method signatures normalized, and a new helper method introduced to centralize publishing logic for both single and batch payloads.

Changes

Cohort / File(s) Summary
Lambda Notification Service
lambda-functions/notification-invoke-service/src/main/java/com/paladincloud/SendNotification.java
Imports made explicit (removed wildcards); logging placeholders and string handling simplified; method signature spacing normalized; batch record handling added with nested SNS message iteration; new sendPayload helper method centralizes publish logic; JSON parsing enhanced with JsonParser.parseString; per-item error handling and logging improved for success/failure cases

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A batch of records hops our way,
Sorted through with nested SNS play,
Error handling springs with care,
Helper methods, logic fair,
Notifications bound for everywhere! 📨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is minimal and lacks required sections from the template including Problem, Solution, type of change checkbox, testing details, and checklist items. Expand the description to include Problem and Solution sections, select the type of change (Bug fix), describe testing approach, and complete the provided checklist items.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: improving error handling to process all events without stopping on errors, which aligns with the control flow overhaul and batch handling introduced in the code changes.
✨ Finishing touches
  • 📝 Generate docstrings

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • JIRA integration encountered authorization issues. Please disconnect and reconnect the integration in the CodeRabbit UI.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI Agents
In
@lambda-functions/notification-invoke-service/src/main/java/com/paladincloud/SendNotification.java:
- Around line 42-49: The code assumes policyParamsJson.getAsJsonArray("Records")
is non-null and uses forEach without per-record error handling; update the logic
in the method that builds and iterates Records (where policyParamsJson, records
and sendPayload are used) to first null-check the result of
policyParamsJson.getAsJsonArray("Records") and handle a missing key by logging
and returning/continuing as appropriate, and replace the current
records.forEach(...) with an explicit loop that wraps parsing of each record
(accessing "Sns" and "Message") and the call to sendPayload(payload, client,
snsTopicArn) in a try-catch so a failure for one record is logged (include
identifying context) and processing continues for remaining records.
🧹 Nitpick comments (3)
lambda-functions/notification-invoke-service/src/main/java/com/paladincloud/SendNotification.java (3)

34-34: Consider using try-with-resources or explicitly shutting down the SNS client.

The AmazonSNS client is created but never closed. While Lambda containers handle cleanup, explicitly calling client.shutdown() in a finally block is best practice to release resources promptly, especially for warmed containers processing many invocations.


59-73: Good per-item error handling; minor efficiency improvements possible.

The per-item try-catch correctly isolates failures, aligning with the PR objective. However:

  1. Double JSON parsing (lines 60, 62) is inefficient.
  2. .stream().forEach() is redundant—use forEach() directly on the list.
🔎 Optional optimization
     private void sendPayload(String payloadString, AmazonSNS client, String snsTopicArn) {
-        Object payloadObj = gson.fromJson(payloadString, Object.class);
-        if (payloadObj instanceof List) {
-            List<Object> notificationRequestList = gson.fromJson(payloadString, List.class);
-            notificationRequestList.stream().forEach(obj -> {
+        JsonElement payloadElement = JsonParser.parseString(payloadString);
+        if (payloadElement.isJsonArray()) {
+            JsonArray notificationRequestList = payloadElement.getAsJsonArray();
+            for (JsonElement obj : notificationRequestList) {
                 try {
-                    String notificationRequestStr = gson.toJson(obj);
+                    String notificationRequestStr = obj.toString();
                     LOGGER.info("notificationsrequeststr for list---{}", notificationRequestStr);
                     PublishRequest request = new PublishRequest(snsTopicArn, notificationRequestStr);
                     PublishResult result = client.publish(request);
                     LOGGER.info("message sent with id {}", result.getMessageId());
                 } catch (Exception ex) {
                     LOGGER.error("Failed sending message: {}", obj, ex);
                 }
-            });
+            }
         } else {

53-56: Inconsistent error handling: outer catch throws, inner catches log and continue.

The outer catch (line 53-55) wraps and rethrows as RuntimeException, while sendPayload catches and logs per-item failures silently. Consider whether the Lambda should:

  • Return a response indicating partial success/failure count, or
  • Log the exception and return gracefully instead of throwing (for better observability in partial failure cases).
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5ead44a and 0f17ed4.

📒 Files selected for processing (1)
  • lambda-functions/notification-invoke-service/src/main/java/com/paladincloud/SendNotification.java
🧰 Additional context used
🧬 Code graph analysis (1)
lambda-functions/notification-invoke-service/src/main/java/com/paladincloud/SendNotification.java (1)
subsystem/auth/services/svc-api-authorizer/service/logging/logger.go (1)
  • Logger (26-28)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: SonarCloud-Build
  • GitHub Check: Analyze (java)

Comment on lines +42 to 49
JsonArray records = policyParamsJson.getAsJsonArray("Records");

Object payloadObj = gson.fromJson(payloadString,Object.class);
if(payloadObj instanceof List){
List<Object> notificationRequestList = gson.fromJson(payloadString,List.class);
notificationRequestList.stream().forEach(obj -> {
String notificationRequestStr = gson.toJson(obj);
LOGGER.info("notificationsrequeststr for list---"+notificationRequestStr);
PublishRequest request = new PublishRequest(snsTopicArn,notificationRequestStr);
PublishResult result = client.publish(request);
LOGGER.info("message sent with id "+result.getMessageId());
records.forEach(body -> {
String payload = body.getAsJsonObject()
.get("Sns").getAsJsonObject()
.get("Message").getAsString();
sendPayload(payload, client, snsTopicArn);
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Missing null check and per-record error handling contradicts PR objective.

Two issues here:

  1. getAsJsonArray("Records") returns null if the key is absent, causing NPE on line 44.
  2. The forEach lacks try-catch around record parsing. If one record fails (e.g., missing Sns or Message), processing stops for all remaining records—directly contradicting the PR objective.
🔎 Proposed fix
-                JsonArray records = policyParamsJson.getAsJsonArray("Records");
-
-                records.forEach(body -> {
-                    String payload = body.getAsJsonObject()
-                        .get("Sns").getAsJsonObject()
-                        .get("Message").getAsString();
-                    sendPayload(payload, client, snsTopicArn);
-                });
+                JsonArray records = policyParamsJson.getAsJsonArray("Records");
+                if (records == null || records.isEmpty()) {
+                    LOGGER.warn("No Records found in event");
+                    return response;
+                }
+
+                for (JsonElement record : records) {
+                    try {
+                        String payload = record.getAsJsonObject()
+                            .get("Sns").getAsJsonObject()
+                            .get("Message").getAsString();
+                        sendPayload(payload, client, snsTopicArn);
+                    } catch (Exception ex) {
+                        LOGGER.error("Failed to process record: {}", record, ex);
+                    }
+                }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
JsonArray records = policyParamsJson.getAsJsonArray("Records");
Object payloadObj = gson.fromJson(payloadString,Object.class);
if(payloadObj instanceof List){
List<Object> notificationRequestList = gson.fromJson(payloadString,List.class);
notificationRequestList.stream().forEach(obj -> {
String notificationRequestStr = gson.toJson(obj);
LOGGER.info("notificationsrequeststr for list---"+notificationRequestStr);
PublishRequest request = new PublishRequest(snsTopicArn,notificationRequestStr);
PublishResult result = client.publish(request);
LOGGER.info("message sent with id "+result.getMessageId());
records.forEach(body -> {
String payload = body.getAsJsonObject()
.get("Sns").getAsJsonObject()
.get("Message").getAsString();
sendPayload(payload, client, snsTopicArn);
});
JsonArray records = policyParamsJson.getAsJsonArray("Records");
if (records == null || records.isEmpty()) {
LOGGER.warn("No Records found in event");
return response;
}
for (JsonElement record : records) {
try {
String payload = record.getAsJsonObject()
.get("Sns").getAsJsonObject()
.get("Message").getAsString();
sendPayload(payload, client, snsTopicArn);
} catch (Exception ex) {
LOGGER.error("Failed to process record: {}", record, ex);
}
}
🤖 Prompt for AI Agents
In
@lambda-functions/notification-invoke-service/src/main/java/com/paladincloud/SendNotification.java
around lines 42 - 49, The code assumes
policyParamsJson.getAsJsonArray("Records") is non-null and uses forEach without
per-record error handling; update the logic in the method that builds and
iterates Records (where policyParamsJson, records and sendPayload are used) to
first null-check the result of policyParamsJson.getAsJsonArray("Records") and
handle a missing key by logging and returning/continuing as appropriate, and
replace the current records.forEach(...) with an explicit loop that wraps
parsing of each record (accessing "Sns" and "Message") and the call to
sendPayload(payload, client, snsTopicArn) in a try-catch so a failure for one
record is logged (include identifying context) and processing continues for
remaining records.

@arunpaladin arunpaladin merged commit 583fec2 into master Jan 7, 2026
60 checks passed
@arunpaladin arunpaladin deleted the NEXT-1916-send-all-events branch January 7, 2026 01:00
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