fix(sync): filter logId=Int64.max placeholder to prevent cursor wedge - #17
Open
wootom wants to merge 1 commit into
Open
fix(sync): filter logId=Int64.max placeholder to prevent cursor wedge#17wootom wants to merge 1 commit into
wootom wants to merge 1 commit into
Conversation
KakaoTalk Mac persists in-flight (server-ack pending) outgoing messages in NTChatMessage with logId = Int64.max as a temporary placeholder. If DatabaseWatcher updates its lastLogId cursor from such a row, every subsequent messagesSince(logId > ?) query becomes WHERE logId > Int64.max, which is always empty — sync enters a silent wedge state until the process restarts, even though the polling loop keeps running and no error is raised. Repro ----- Send two messages via kakaocli send in quick succession (~1s apart) while kakaocli sync --follow runs. The second send's echo is picked up before KakaoTalk receives server ack, sync emits a SyncMessage with log_id: 9223372036854775807, and from that point onwards no new messages reach the webhook. Field-observed on a bot integrating kakaocli sync via webhook (vaaxbot, ~10h runtime). Fix --- - DatabaseWatcher: filter rows with logId == Int64.max out of both the emission batch and the cursor-max calculation. The same message is re-read on the next poll once KakaoTalk updates the row with the real server-assigned logId, so no events are lost. - DatabaseReader.maxLogId(): exclude Int64.max rows from the MAX(logId) query so that startup cursor seed cannot be poisoned if a placeholder is already in the table when sync starts. Tests ----- Existing swift test 4/4 still passes. No new unit test added: the failure requires a live KakaoTalk Mac UI in a specific timing window; a deterministic test would need a recorded SQLite fixture with a placeholder row, which is left as follow-up.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
KakaoTalk Mac persists in-flight (server-ack pending) outgoing messages in NTChatMessage with logId = Int64.max as a temporary placeholder. If DatabaseWatcher updates its lastLogId cursor from such a row, every subsequent messagesSince(logId > ?) query becomes WHERE logId > Int64.max, which is always empty — sync enters a silent wedge state until the process restarts, even though the polling loop keeps running and no error is raised.
Repro
Send two messages via kakaocli send in quick succession (~1s apart) while kakaocli sync --follow runs. The second send's echo is picked up before KakaoTalk receives server ack, sync emits a SyncMessage with log_id: 9223372036854775807, and from that point onwards no new messages reach the webhook. Field-observed on a bot integrating kakaocli sync via webhook (vaaxbot, ~10h runtime).
Fix
Tests
Existing swift test 4/4 still passes. No new unit test added: the failure requires a live KakaoTalk Mac UI in a specific timing window; a deterministic test would need a recorded SQLite fixture with a placeholder row, which is left as follow-up.