A validated push message: what Gamend.Push.send_to_user/3 accepts and
what the delivery workers carry through job args.
Fields:
title– required, capped bymax_push_titlebytesbody– optional, capped bymax_push_bodybytesdata– optional custom key/value map, serialized size capped bymax_push_data_sizebytes. FCM requires string values on the wire, so non-string values are JSON-encoded by the FCM provider; clients decode them back.
Caps are bytes, not characters, because the provider limits are bytes (FCM and APNs both cap the payload at 4096) — a character cap would let multibyte text through validation only to fail on the wire.
image– optional image URLsound– optional sound namebadge– optional iOS badge countcollapse_key– optional dedupe key (apns-collapse-id/ FCMcollapse_key), which is what makes an at-least-once redelivery invisible on-device
Summary
Functions
Rebuild from job args. Args were validated at enqueue time.
Build and validate a message from a map (string or atom keys).
Serialize for Oban job args (string keys, nils dropped).
Truncate a UTF-8 string to at most max_bytes without splitting a
character. For callers bridging longer content (notification bodies,
personalized titles) into the push byte caps.
Types
Functions
Rebuild from job args. Args were validated at enqueue time.
Build and validate a message from a map (string or atom keys).
Returns {:ok, %Message{}} or {:error, errors} where errors maps a
field to its problem, e.g. %{title: "can't be blank"}.
Serialize for Oban job args (string keys, nils dropped).
@spec truncate(String.t(), non_neg_integer()) :: String.t()
Truncate a UTF-8 string to at most max_bytes without splitting a
character. For callers bridging longer content (notification bodies,
personalized titles) into the push byte caps.