Skip to content

Add optional Robotty missed-message recovery - #46

Closed
Alb11747 wants to merge 1 commit into
boring-nick:masterfrom
Alb11747:codex/robotty-missed-message-recovery
Closed

Add optional Robotty missed-message recovery#46
Alb11747 wants to merge 1 commit into
boring-nick:masterfrom
Alb11747:codex/robotty-missed-message-recovery

Conversation

@Alb11747

@Alb11747 Alb11747 commented Aug 11, 2026

Copy link
Copy Markdown

Summary

  • add disabled-by-default Robotty recovery after confirmed startup, reconnect, and runtime joins
  • configure recovery through the existing camelCase JSON model: recentMessagesEnabled, recentMessagesUrl, and recentMessagesLimit
  • normalize Robotty's valueless IRC tags while deliberately retaining crates.io tmi 0.7.3; the parser fix is being developed in tmi-rs PR #20
  • validate message timestamps, channel logins, and channel IDs before replay
  • order and deduplicate responses, bound recovery windows, and pace shared requests
  • share live/replay validation and storage without dispatching commands from replayed messages
  • prepare for twitch-irc 6 without changing this PR's released IRC dependencies
  • avoid vendored dependencies and database schema changes

Upstream parser issue

Robotty's recent-messages API changed how it serializes empty IRC tags: explicit empty values such as badges=;color=;room-id=42 can now arrive as valueless tags such as badges;color;room-id=42. This behavior is described in tmi-rs issue #18.

The tag parser in tmi 0.7.3 expects each tag to contain =. When it encounters the ; terminating a valueless tag while it is still parsing a key, that tag is not emitted correctly and subsequent tags can also become unavailable. In a representative Robotty message, this loses badges, color, and room-id, even though later tags such as tmi-sent-ts may still be found. Losing room-id and other metadata makes the response unsafe to validate and store as a complete Twitch message.

tmi-rs PR #20: Fix IRC tag parsing and message accessor edge cases fixes both the scalar and SIMD parsers so key, key=, and ordinary key=value tags are parsed consistently. Until that fix is accepted and released, this Rustlog PR performs a narrow conversion from key; to key=; only on Robotty responses before passing them to tmi. Live IRC messages are not rewritten.

The recovery path is best-effort and isolated from live IRC ingestion. A failed persisted-ID lookup aborts that channel's replay instead of risking duplicate inserts.

Upstream reconnect issue

Internet loss also exposed a separate bug in twitch-irc: its connection cooldown task was created only after transport initialization succeeded. A transport error or timeout returned early and dropped the semaphore permit immediately, so the pool could retry in a tight loop.

twitch-irc PR #231: Rate limit failed connection attempts moves the existing cooldown to permit acquisition, covering successful, failed, and timed-out attempts. In the same isolated 45-second route-loss test, unpatched v6.1.1 emitted 295,890 log lines / 60,243,055 bytes; the patched fork emitted 54 lines / 10,711 bytes. Both recovered, stored the fixture exactly once, and completed clean SIGTERM stops, but the unpatched build generated about 5,480 times as many lines.

This PR continues to use released twitch-irc 5.0.1. The compatibility preparation selects rustls's ring provider explicitly, accepts both the v5 and v6 IRC tag value shapes, and moves the container build to Rust 1.88 with a pinned cargo-chef. No fork or unreleased dependency is committed.

Dependency compatibility

  • this branch intentionally retains crates.io tmi 0.7.3 and twitch-irc 5.0.1
  • the three-fork integration build used the heads of tmi-rs PR Add MIT License #20, twitch-irc PR #231, and this Rustlog PR
  • that build passed all 29 Rustlog tests, a 14-scenario Robotty suite, and an 8-scenario lifecycle/network-loss suite
  • after compatible releases, adopting both upstream fixes requires dependency and lockfile updates only; no additional Rust source change is required
  • the tested v6 dependency set also updates prometheus to 0.14 and metrics-prometheus to 0.11.2 so Rustlog and twitch-irc share one Prometheus registry
  • after updating tmi, the local Robotty tag normalization is harmless but redundant and can be removed separately as cleanup

Validation

  • current released dependencies: cargo test --locked --all-targets on Rust 1.88, 25 passed
  • current released dependencies: complete release Docker image built and binary help smoke test passed
  • ARM64 release builder stage cross-compiled successfully; the upstream multi-platform Docker run is awaiting maintainer approval
  • tmi-rs PR Add MIT License #20 parser suites: 119 all-feature/SIMD tests and 19 scalar/no-default tests passed
  • twitch-irc PR #231: 118 unit tests plus 17/18 doctests passed across default and refreshing-token configurations
  • twitch-irc PR #231: formatting, strict Clippy feature matrices, and documentation with warnings denied passed
  • three-fork Robotty mock suite: 14/14 passed, including malformed/error responses, timeouts, resets, deduplication, command suppression, persistent replay, and request limits
  • three-fork lifecycle suite: 8/8 passed, including clean stop/restart, SIGTERM during an in-flight Robotty request, 45-second isolated route loss, automatic recovery, bounded logging, and production-isolation checks
  • git diff --check: passed

@Alb11747
Alb11747 force-pushed the codex/robotty-missed-message-recovery branch from 6595ea9 to 9a7df1b Compare August 11, 2026 00:59
@Alb11747
Alb11747 marked this pull request as ready for review August 11, 2026 01:05
@Alb11747
Alb11747 marked this pull request as draft August 11, 2026 09:03
@Alb11747
Alb11747 force-pushed the codex/robotty-missed-message-recovery branch from aeb9556 to b0d175f Compare August 11, 2026 21:32
Recover messages missed during startup, reconnects, and runtime joins through a bounded Robotty backfill path.

Validate, order, and deduplicate replayed messages before storage; configure the feature through the existing JSON configuration model.
@Alb11747
Alb11747 force-pushed the codex/robotty-missed-message-recovery branch from 626e3f4 to c9bb237 Compare August 12, 2026 04:41
@Alb11747 Alb11747 closed this Aug 12, 2026
@Alb11747
Alb11747 deleted the codex/robotty-missed-message-recovery branch August 12, 2026 05:09
@Alb11747

Copy link
Copy Markdown
Author

Superseded by #47 after renaming the fork branch to feat/robotty-missed-message-recovery. The replacement has the same clean commit and PR content.

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.

1 participant