Commit 9d5451c
committed
fix(qwp): skip-and-self-ack the recovered orphaned deferred tail
Closes the resurrect-partial-transaction hole documented in the
deferred-ack series: a producer that crashes (or closes)
mid-transaction leaves FLAG_DEFER_COMMIT frames with no covering
commit frame at the top of its disk-recovered SF log. Replaying them
would let a commit-bearing frame from the NEW session commit them --
half a dead transaction resurrected, violating transaction=on
atomicity. Previously detected + WARN'd only.
Mechanism (CursorWebSocketSendLoop):
- The loop adopts the engine's recovered orphan range
[recoveredCommitBoundaryFsn+1 .. recoveredOrphanTipFsn] at
construction; the BackgroundDrainer path builds through the same
constructor and gets identical containment.
- trySendOne stops the cursor at the tail: orphan frames are never
transmitted.
- tryRetireOrphanTail retires the tail with a cumulative
self-acknowledge once every frame below it is server-acked (legal:
the tail was never sent, no wire sequence references it). Crash-safe
and idempotent -- dying before the self-ack re-detects the same
range at next recovery.
- Fast path (common crash profile: acks current, only the in-flight
transaction unacked; trivially when the whole log is the tail): the
tail retires in positionCursorForStart before any connection exists.
Zero wire cost, no reconnect.
- Slow path (unacked committed frames below the tail): they replay
first; on retirement the connection recycles exactly once so the
linear wireSeq<->FSN mapping re-anchors past the FSN gap. swapClient
also re-attempts retirement so a reconnect never replays into the
tail.
Positive-identification hardening (found by the drainer test suite):
the recovery walk classifies a frame as deferred ONLY when it parses
as a QWP message -- payload >= HEADER_SIZE and u32 'QWP1' magic at
offset 0 -- before reading the flags byte. Anything unidentifiable is
a retirement barrier, never trimmable: misclassifying an unknown
frame as deferred would silently discard data that should replay (the
drainer tests' filler payloads had bit 0 set at offset 5 and were
being trimmed wholesale).
Tests: CursorWebSocketSendLoopOrphanTailTest covers recovery
detection (orphan tail present/absent), the zero-send fast path, and
the slow path end-to-end (replay below tail, single recycle, correct
ack attribution across the FSN gap for new-session frames). Full
client suite: 2509 green.1 parent cd48ae3 commit 9d5451c
5 files changed
Lines changed: 491 additions & 15 deletions
File tree
- core/src
- main/java/io/questdb/client/cutlass/qwp/client/sf/cursor
- test/java/io/questdb/client/test/cutlass/qwp/client/sf/cursor
Lines changed: 24 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
96 | 96 | | |
97 | 97 | | |
98 | 98 | | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
99 | 107 | | |
100 | 108 | | |
101 | 109 | | |
| |||
279 | 287 | | |
280 | 288 | | |
281 | 289 | | |
282 | | - | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
283 | 293 | | |
284 | 294 | | |
| 295 | + | |
285 | 296 | | |
286 | | - | |
287 | | - | |
288 | | - | |
289 | | - | |
290 | | - | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
291 | 300 | | |
292 | 301 | | |
293 | 302 | | |
| |||
641 | 650 | | |
642 | 651 | | |
643 | 652 | | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
644 | 662 | | |
645 | 663 | | |
646 | 664 | | |
| |||
Lines changed: 95 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
275 | 275 | | |
276 | 276 | | |
277 | 277 | | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
278 | 290 | | |
279 | 291 | | |
280 | 292 | | |
| |||
478 | 490 | | |
479 | 491 | | |
480 | 492 | | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
481 | 502 | | |
482 | 503 | | |
483 | 504 | | |
| |||
1759 | 1780 | | |
1760 | 1781 | | |
1761 | 1782 | | |
| 1783 | + | |
| 1784 | + | |
| 1785 | + | |
| 1786 | + | |
| 1787 | + | |
1762 | 1788 | | |
1763 | 1789 | | |
1764 | 1790 | | |
| |||
1794 | 1820 | | |
1795 | 1821 | | |
1796 | 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 | + | |
1797 | 1851 | | |
1798 | 1852 | | |
1799 | 1853 | | |
| |||
1859 | 1913 | | |
1860 | 1914 | | |
1861 | 1915 | | |
| 1916 | + | |
| 1917 | + | |
| 1918 | + | |
| 1919 | + | |
| 1920 | + | |
| 1921 | + | |
| 1922 | + | |
1862 | 1923 | | |
1863 | 1924 | | |
1864 | 1925 | | |
1865 | 1926 | | |
1866 | 1927 | | |
1867 | 1928 | | |
| 1929 | + | |
| 1930 | + | |
| 1931 | + | |
| 1932 | + | |
| 1933 | + | |
| 1934 | + | |
| 1935 | + | |
| 1936 | + | |
| 1937 | + | |
| 1938 | + | |
| 1939 | + | |
| 1940 | + | |
| 1941 | + | |
| 1942 | + | |
| 1943 | + | |
| 1944 | + | |
| 1945 | + | |
| 1946 | + | |
| 1947 | + | |
| 1948 | + | |
| 1949 | + | |
| 1950 | + | |
| 1951 | + | |
| 1952 | + | |
| 1953 | + | |
| 1954 | + | |
| 1955 | + | |
| 1956 | + | |
| 1957 | + | |
| 1958 | + | |
| 1959 | + | |
| 1960 | + | |
| 1961 | + | |
| 1962 | + | |
1868 | 1963 | | |
1869 | 1964 | | |
1870 | 1965 | | |
| |||
Lines changed: 18 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
446 | 446 | | |
447 | 447 | | |
448 | 448 | | |
449 | | - | |
450 | | - | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
451 | 461 | | |
452 | 462 | | |
453 | 463 | | |
454 | 464 | | |
455 | 465 | | |
456 | 466 | | |
457 | 467 | | |
458 | | - | |
| 468 | + | |
459 | 469 | | |
460 | 470 | | |
461 | 471 | | |
462 | 472 | | |
463 | 473 | | |
464 | | - | |
465 | | - | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
466 | 479 | | |
467 | 480 | | |
468 | 481 | | |
| |||
Lines changed: 8 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
521 | 521 | | |
522 | 522 | | |
523 | 523 | | |
524 | | - | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
525 | 529 | | |
526 | | - | |
| 530 | + | |
527 | 531 | | |
528 | 532 | | |
529 | | - | |
| 533 | + | |
530 | 534 | | |
531 | 535 | | |
532 | 536 | | |
533 | 537 | | |
534 | | - | |
| 538 | + | |
535 | 539 | | |
536 | 540 | | |
537 | 541 | | |
| |||
0 commit comments