Commit 0bd04e9
committed
fix(sqs): assign FIFO seq on FIFO->FIFO redrive + reject mixed attribute values
Two findings from the latest Codex review on `cdb3c87` that the
prior "Ready to merge" verdicts had not addressed.
P1 — FIFO->FIFO redrive committed `SequenceNumber=0` and never
advanced the DLQ's sqsQueueSeqKey (`sqs_redrive.go:265-272, 213`).
Once `cdb3c87` enabled FIFO->FIFO redrives by enforcing type
equality, the SequenceNumber path became reachable and showed:
- the DLQ record carried the zero-value `SequenceNumber` (AWS
surfaces this verbatim; AWS sequences start at 1, never 0),
- the DLQ's per-queue sequence counter was never incremented, so a
subsequent normal FIFO send to the DLQ assigned a number lower
than the redriven message — non-monotonic to consumers, breaking
the FIFO contract,
- two concurrent FIFO->FIFO redrives both wrote `SequenceNumber=0`
with no OCC conflict because `sqsQueueSeqKey(policy.DLQName)` was
not on `ReadKeys`.
Fix: when `dlqMeta.IsFIFO`, `redriveCandidateToDLQ` now loads the
DLQ's seq counter at `readTS`, computes `nextSeq = prev+1`, threads
the value through `buildDLQRecord` (where it is stamped onto the
record before encoding) and `buildRedriveOps` (where the seq Put is
added to `Elems` and `sqsQueueSeqKey(policy.DLQName)` is added to
`ReadKeys`). Standard DLQs are unchanged: `dlqSeq=0` flows through
unused.
P2 — `validateOneMessageAttribute` accepted Binary attributes that
also carried a non-empty `StringValue` (`sqs_messages.go:1523-1527`).
AWS requires each MessageAttributeValue to populate exactly one of
{StringValue, BinaryValue}; submitting both is an
`InvalidParameterValue`. The previous validator only checked the
type-required field was non-empty and silently let the foreign
field through, where it would be persisted into the record and
round-tripped on ReceiveMessage with mismatched MD5 hashes.
Fix: extracted the type-specific value-pair check into
`validateMessageAttributeValuePair` and added the symmetric guards
— Binary rejects `StringValue != ""`, String/Number rejects
`len(BinaryValue) > 0`. The split also keeps
`validateOneMessageAttribute` under the cyclop budget.
Tests:
- `TestSQSServer_FifoFifoRedriveAssignsSequenceNumber`
(`sqs_extra_test.go`): create FIFO source + FIFO DLQ, send poison,
redrive on the second receive, assert the DLQ message's
SequenceNumber > 0, then send a fresh FIFO message to the DLQ and
assert its SequenceNumber == redrivenSeq + 1 (monotonic
continuation, the invariant the fix guarantees).
- `TestSQSServer_SendMessageRejectsBinaryWithStringValue`
(`sqs_extra_test.go`): table-driven over the three illegal
combinations (Binary + non-empty StringValue, String + non-empty
BinaryValue, Number + non-empty BinaryValue); each must return
HTTP 400 / InvalidAttributeValue.
Per CLAUDE.md self-review:
1. Data loss — None. The poison message body / attributes flow
unchanged; only the SequenceNumber field and DLQ counter change.
2. Concurrency — `sqsQueueSeqKey(policy.DLQName)` is now on
ReadKeys, so two concurrent FIFO->FIFO redrives serialise on
write-write-conflict, same as concurrent FIFO sends.
3. Performance — One extra `loadFifoSequence` per FIFO redrive;
negligible vs. the existing `validateRedriveTargets` reads.
4. Data consistency — DLQ SequenceNumber now monotonic across both
redrive and normal-send paths; no two messages can share a
sequence number on the same FIFO queue.
5. Test coverage — Both fixes ship with co-located regression
tests; the existing FIFO-related tests
(`TestSQSServer_FifoSequenceNumberMonotonic`,
`TestSQSServer_DLQRedriveOnMaxReceiveCount`,
`TestSQSServer_RedrivePolicy*`) remain green.1 parent cdb3c87 commit 0bd04e9
3 files changed
Lines changed: 230 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1746 | 1746 | | |
1747 | 1747 | | |
1748 | 1748 | | |
| 1749 | + | |
| 1750 | + | |
| 1751 | + | |
| 1752 | + | |
| 1753 | + | |
| 1754 | + | |
| 1755 | + | |
| 1756 | + | |
| 1757 | + | |
| 1758 | + | |
| 1759 | + | |
| 1760 | + | |
| 1761 | + | |
| 1762 | + | |
| 1763 | + | |
| 1764 | + | |
| 1765 | + | |
| 1766 | + | |
| 1767 | + | |
| 1768 | + | |
| 1769 | + | |
| 1770 | + | |
| 1771 | + | |
| 1772 | + | |
| 1773 | + | |
| 1774 | + | |
| 1775 | + | |
| 1776 | + | |
| 1777 | + | |
| 1778 | + | |
| 1779 | + | |
| 1780 | + | |
| 1781 | + | |
| 1782 | + | |
| 1783 | + | |
| 1784 | + | |
| 1785 | + | |
| 1786 | + | |
| 1787 | + | |
| 1788 | + | |
| 1789 | + | |
| 1790 | + | |
| 1791 | + | |
| 1792 | + | |
| 1793 | + | |
| 1794 | + | |
| 1795 | + | |
| 1796 | + | |
| 1797 | + | |
| 1798 | + | |
| 1799 | + | |
| 1800 | + | |
| 1801 | + | |
| 1802 | + | |
| 1803 | + | |
| 1804 | + | |
| 1805 | + | |
| 1806 | + | |
| 1807 | + | |
| 1808 | + | |
| 1809 | + | |
| 1810 | + | |
| 1811 | + | |
| 1812 | + | |
| 1813 | + | |
| 1814 | + | |
| 1815 | + | |
| 1816 | + | |
| 1817 | + | |
| 1818 | + | |
| 1819 | + | |
| 1820 | + | |
| 1821 | + | |
| 1822 | + | |
| 1823 | + | |
| 1824 | + | |
| 1825 | + | |
| 1826 | + | |
| 1827 | + | |
| 1828 | + | |
| 1829 | + | |
| 1830 | + | |
| 1831 | + | |
| 1832 | + | |
| 1833 | + | |
| 1834 | + | |
| 1835 | + | |
| 1836 | + | |
| 1837 | + | |
| 1838 | + | |
| 1839 | + | |
| 1840 | + | |
| 1841 | + | |
| 1842 | + | |
| 1843 | + | |
| 1844 | + | |
| 1845 | + | |
| 1846 | + | |
| 1847 | + | |
| 1848 | + | |
| 1849 | + | |
| 1850 | + | |
| 1851 | + | |
| 1852 | + | |
| 1853 | + | |
| 1854 | + | |
| 1855 | + | |
| 1856 | + | |
| 1857 | + | |
| 1858 | + | |
| 1859 | + | |
| 1860 | + | |
| 1861 | + | |
| 1862 | + | |
| 1863 | + | |
| 1864 | + | |
| 1865 | + | |
| 1866 | + | |
| 1867 | + | |
| 1868 | + | |
| 1869 | + | |
| 1870 | + | |
| 1871 | + | |
| 1872 | + | |
| 1873 | + | |
| 1874 | + | |
| 1875 | + | |
| 1876 | + | |
| 1877 | + | |
| 1878 | + | |
| 1879 | + | |
| 1880 | + | |
| 1881 | + | |
| 1882 | + | |
| 1883 | + | |
| 1884 | + | |
| 1885 | + | |
| 1886 | + | |
| 1887 | + | |
| 1888 | + | |
| 1889 | + | |
| 1890 | + | |
| 1891 | + | |
| 1892 | + | |
| 1893 | + | |
| 1894 | + | |
| 1895 | + | |
| 1896 | + | |
| 1897 | + | |
| 1898 | + | |
| 1899 | + | |
| 1900 | + | |
| 1901 | + | |
| 1902 | + | |
| 1903 | + | |
| 1904 | + | |
| 1905 | + | |
| 1906 | + | |
| 1907 | + | |
| 1908 | + | |
| 1909 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1514 | 1514 | | |
1515 | 1515 | | |
1516 | 1516 | | |
| 1517 | + | |
| 1518 | + | |
| 1519 | + | |
| 1520 | + | |
| 1521 | + | |
| 1522 | + | |
| 1523 | + | |
| 1524 | + | |
| 1525 | + | |
| 1526 | + | |
| 1527 | + | |
| 1528 | + | |
1517 | 1529 | | |
1518 | 1530 | | |
1519 | 1531 | | |
1520 | 1532 | | |
1521 | 1533 | | |
1522 | 1534 | | |
| 1535 | + | |
| 1536 | + | |
| 1537 | + | |
| 1538 | + | |
1523 | 1539 | | |
1524 | 1540 | | |
1525 | 1541 | | |
1526 | 1542 | | |
1527 | 1543 | | |
| 1544 | + | |
| 1545 | + | |
| 1546 | + | |
| 1547 | + | |
1528 | 1548 | | |
1529 | 1549 | | |
1530 | 1550 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
| |||
125 | 126 | | |
126 | 127 | | |
127 | 128 | | |
128 | | - | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
129 | 147 | | |
130 | 148 | | |
131 | 149 | | |
132 | | - | |
| 150 | + | |
133 | 151 | | |
134 | 152 | | |
135 | 153 | | |
| |||
200 | 218 | | |
201 | 219 | | |
202 | 220 | | |
203 | | - | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
204 | 231 | | |
205 | 232 | | |
206 | 233 | | |
| |||
227 | 254 | | |
228 | 255 | | |
229 | 256 | | |
| 257 | + | |
230 | 258 | | |
231 | 259 | | |
232 | 260 | | |
| |||
239 | 267 | | |
240 | 268 | | |
241 | 269 | | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
242 | 278 | | |
243 | 279 | | |
244 | 280 | | |
| |||
250 | 286 | | |
251 | 287 | | |
252 | 288 | | |
| 289 | + | |
253 | 290 | | |
254 | 291 | | |
255 | 292 | | |
| |||
270 | 307 | | |
271 | 308 | | |
272 | 309 | | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
273 | 319 | | |
274 | 320 | | |
275 | 321 | | |
| |||
0 commit comments