Skip to content

fix(scheduler): forward MessageAttributes in universal sns:publish target#1706

Open
ctnnguyen wants to merge 2 commits into
floci-io:mainfrom
ctnnguyen:fix/scheduler-sns-universal-target-message-attributes
Open

fix(scheduler): forward MessageAttributes in universal sns:publish target#1706
ctnnguyen wants to merge 2 commits into
floci-io:mainfrom
ctnnguyen:fix/scheduler-sns-universal-target-message-attributes

Conversation

@ctnnguyen

@ctnnguyen ctnnguyen commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #1669.

When a schedule fires with a universal arn:aws:scheduler:::aws-sdk:sns:publish target, MessageAttributes supplied in the target Input were silently dropped. The message was delivered with the correct Subject and Message, but subscribers received an empty attribute map — breaking any SQS subscription with a FilterPolicy that matches on MessageAttributes.

The root cause: invokeUniversalTarget parsed TopicArn, Message, Subject, and FIFO parameters from Input but never read MessageAttributes, hardcoding null when calling SnsService.publish. A direct sns:Publish API call preserved attributes correctly, confirming the loss was specific to the scheduler's universal-target path.

The fix reads MessageAttributes from Input using the same DataType/StringValue per-entry format that SnsJsonHandler uses for direct publish calls, then forwards them through to SnsService.publish.

Type of change

  • Bug fix (fix:)

AWS Compatibility

AWS EventBridge Scheduler universal targets pass MessageAttributes through to SNS on publish. Subscribers with FilterPolicy scoped to MessageAttributes receive messages as expected. This change aligns the emulator with that behavior.

Checklist

  • ./mvnw test passes locally
  • New or updated integration test added
  • Commit messages follow Conventional Commits

@ctnnguyen ctnnguyen force-pushed the fix/scheduler-sns-universal-target-message-attributes branch from 081a76b to 8aed396 Compare July 2, 2026 17:05
@ctnnguyen ctnnguyen changed the title fix(events): SNS universal target message attributes fix(scheduler): forward MessageAttributes in universal sns:publish target Jul 2, 2026
@ctnnguyen ctnnguyen marked this pull request as ready for review July 2, 2026 17:06
@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a bug where MessageAttributes supplied in the Input of a universal arn:aws:scheduler:::aws-sdk:sns:publish target were silently dropped, causing SNS subscribers with FilterPolicy on MessageAttributes to never receive matching messages.

  • Adds parseMessageAttributes(JsonNode) to ScheduleInvoker that reads both String and Binary (Base64-decoded) attributes from the target's Input JSON and forwards them to SnsService.publish.
  • Covers the fix with three new unit tests: string attributes, binary attributes, and the no-attributes case.

Confidence Score: 5/5

Safe to merge — the change is narrowly scoped to reading and forwarding MessageAttributes in the universal SNS scheduler path, with no effect on other delivery paths.

The fix is well-contained: one new private method, one call-site change, and three targeted tests covering string, binary, and absent attributes. The existing tests for the universal SNS path still pass, and the new tests exercise both branches of the new parsing logic. The only open edge case is an uncaught IllegalArgumentException on malformed Base64, which would surface as an undelivered message rather than silent data loss.

No files require special attention beyond the minor Base64 error-handling note in ScheduleInvoker.java.

Important Files Changed

Filename Overview
src/main/java/io/github/hectorvent/floci/services/scheduler/ScheduleInvoker.java Adds parseMessageAttributes helper that reads String and Binary MessageAttributes from the Input JSON and forwards them to snsService.publish, fixing the silent drop in the universal sns:publish path.
src/test/java/io/github/hectorvent/floci/services/scheduler/ScheduleInvokerTest.java Adds three new tests covering the String attribute forwarding path, the Binary (base64) attribute path, and the null-attributes pass-through case.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Scheduler
    participant ScheduleInvoker
    participant parseMessageAttributes
    participant SnsService

    Scheduler->>ScheduleInvoker: invoke(target, region)
    ScheduleInvoker->>ScheduleInvoker: detect universal target (aws-sdk:sns:publish)
    ScheduleInvoker->>ScheduleInvoker: invokeUniversalTarget(serviceAction, input, region)
    ScheduleInvoker->>parseMessageAttributes: parseMessageAttributes(params)
    parseMessageAttributes->>parseMessageAttributes: read params.path("MessageAttributes")
    alt BinaryValue present
        parseMessageAttributes->>parseMessageAttributes: Base64.decode(binaryValueBase64)
        parseMessageAttributes-->>ScheduleInvoker: "Map{key -> MessageAttributeValue(byte[], dataType)}"
    else StringValue present
        parseMessageAttributes-->>ScheduleInvoker: "Map{key -> MessageAttributeValue(string, dataType)}"
    else No MessageAttributes
        parseMessageAttributes-->>ScheduleInvoker: null
    end
    ScheduleInvoker->>SnsService: publish(topicArn, targetArn, null, message, subject, messageAttributes, ...)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Scheduler
    participant ScheduleInvoker
    participant parseMessageAttributes
    participant SnsService

    Scheduler->>ScheduleInvoker: invoke(target, region)
    ScheduleInvoker->>ScheduleInvoker: detect universal target (aws-sdk:sns:publish)
    ScheduleInvoker->>ScheduleInvoker: invokeUniversalTarget(serviceAction, input, region)
    ScheduleInvoker->>parseMessageAttributes: parseMessageAttributes(params)
    parseMessageAttributes->>parseMessageAttributes: read params.path("MessageAttributes")
    alt BinaryValue present
        parseMessageAttributes->>parseMessageAttributes: Base64.decode(binaryValueBase64)
        parseMessageAttributes-->>ScheduleInvoker: "Map{key -> MessageAttributeValue(byte[], dataType)}"
    else StringValue present
        parseMessageAttributes-->>ScheduleInvoker: "Map{key -> MessageAttributeValue(string, dataType)}"
    else No MessageAttributes
        parseMessageAttributes-->>ScheduleInvoker: null
    end
    ScheduleInvoker->>SnsService: publish(topicArn, targetArn, null, message, subject, messageAttributes, ...)
Loading

Reviews (2): Last reviewed commit: "fix(scheduler): handle Binary MessageAtt..." | Re-trigger Greptile

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.

[BUG] EventBridge Scheduler: universal aws-sdk:sns:publish target drops MessageAttributes

1 participant