Skip to content

fix(history): deliver on-demand history-sync and deepen on-link backfill - #133

Open
nicolasnovis wants to merge 3 commits into
evolution-foundation:mainfrom
nicolasnovis:fix/on-demand-history-sync-and-full-sync-depth
Open

fix(history): deliver on-demand history-sync and deepen on-link backfill#133
nicolasnovis wants to merge 3 commits into
evolution-foundation:mainfrom
nicolasnovis:fix/on-demand-history-sync-and-full-sync-depth

Conversation

@nicolasnovis

@nicolasnovis nicolasnovis commented Jul 24, 2026

Copy link
Copy Markdown

Summary

Two small fixes so that message history actually reaches newly linked devices:

  1. On-demand history-sync now delivers. HistorySyncRequest sent the peer request to messageInfo.Chat (the contact). Peer messages must be sent to the account's own JID — sending to the contact fails with failed to encrypt peer message ... no signal session established with <device> and the phone never returns any history. Switched to client.SendPeerMessage, which whatsmeow documents as the correct way to send a BuildHistorySyncRequest (it targets getOwnID().ToNonAD() with Peer: true). The target chat/cursor is already encoded inside the built request, so no information is lost.

  2. On-link backfill is now deep. RequireFullSync = true alone still produced a shallow, uneven backfill because the phone falls back to conservative defaults when no HistorySyncConfig is provided. Setting an explicit deep window makes a freshly linked device receive the full available history.

Why

On the current release, after pairing a device:

  • The initial HistorySync push only brings a small, uneven slice of recent messages.
  • POST /chat/history-sync returns 200 but no HistorySync (ON_DEMAND) event ever arrives — the request 500s internally with no signal session established, and even when a session exists the request is addressed to the wrong JID so the phone has nothing to answer.

Together these make it impossible to backfill a conversation's history through the API.

Changes

  • pkg/chat/service/chat_service.go — send the on-demand request via SendPeerMessage.
  • pkg/whatsmeow/service/whatsmeow.go — set DeviceProps.HistorySyncConfig (FullSyncDaysLimit, FullSyncSizeMbLimit, StorageQuotaMb).

Notes

The FullSyncDaysLimit/size values are conservative-but-generous defaults; happy to make them configurable via instance settings/env if preferred.

Summary by Sourcery

Ensure newly linked devices receive complete message history via on-link and on-demand history sync.

Bug Fixes:

  • Fix on-demand history sync requests being sent to the contact JID instead of the account’s own JID so that history is actually returned.

Enhancements:

  • Configure explicit deep HistorySync parameters (days, size, storage quota) so full history is backfilled to newly linked devices.

…ssage

The on-demand history-sync request was sent to messageInfo.Chat (the contact)
with Peer:true. Peer messages must go to the account's OWN JID — sending to the
contact fails with "no signal session established" and never returns history.

whatsmeow's BuildHistorySyncRequest documents SendPeerMessage as the way to send
it (it targets getOwnID().ToNonAD() with Peer:true). The target chat/cursor is
already encoded inside the built request, so no information is lost.
…kfill

RequireFullSync=true alone yields a shallow/uneven backfill because the phone
falls back to conservative defaults when no HistorySyncConfig is provided.
Setting an explicit deep window makes newly linked devices receive the full
available message history.
@sourcery-ai

sourcery-ai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Ensures newly linked devices receive complete message history by fixing how on-demand history-sync requests are sent and by explicitly configuring a deep on-link history sync window in device properties.

Sequence diagram for on-demand history-sync request using SendPeerMessage

sequenceDiagram
    actor ApiClient
    participant ChatService as chatService
    participant WMClient as whatsmeowClient
    participant Phone

    ApiClient->>ChatService: HistorySyncRequest(data, instance)
    ChatService->>WMClient: GetMessageInfo(data.ChatID)
    ChatService->>WMClient: BuildHistorySyncRequest(&messageInfo, data.Count)
    WMClient-->>ChatService: histRequest
    ChatService->>WMClient: SendPeerMessage(context, histRequest)
    WMClient->>Phone: peer history-sync request to own JID
    Phone-->>WMClient: HistorySync ON_DEMAND response
    WMClient-->>ChatService: res
    ChatService-->>ApiClient: HistorySync data
Loading

Sequence diagram for deep on-link history sync configuration in StartClient

sequenceDiagram
    participant WhatsmeowService as whatsmeowService
    participant Store as deviceStore
    participant Phone

    WhatsmeowService->>Store: StartClient(cd)
    WhatsmeowService->>Store: set DeviceProps.Os
    WhatsmeowService->>Store: set DeviceProps.RequireFullSync = true
    WhatsmeowService->>Store: set DeviceProps.HistorySyncConfig(FullSyncDaysLimit, FullSyncSizeMbLimit, StorageQuotaMb)
    Store-->>Phone: registration with DeviceProps
    Phone-->>Store: deep HistorySync for newly linked device
Loading

File-Level Changes

Change Details Files
Fix on-demand history-sync delivery by sending the built history request as a peer message to the account’s own JID instead of the contact.
  • Use client.SendPeerMessage rather than client.SendMessage for on-demand history-sync requests.
  • Remove explicit target chat parameter; rely on the cursor/chat encoded in the built HistorySyncRequest.
  • Add clarifying comments about why peer messages must target the own JID and reference whatsmeow’s BuildHistorySyncRequest documentation.
  • Preserve existing logging and error handling around history-sync requests.
pkg/chat/service/chat_service.go
Deepen on-link history backfill by explicitly setting a generous HistorySyncConfig on device properties when starting the WhatsApp client.
  • Keep RequireFullSync enabled to force a full sync for newly linked devices.
  • Initialize DeviceProps.HistorySyncConfig with explicit FullSyncDaysLimit, FullSyncSizeMbLimit, and StorageQuotaMb values to request a deep history window.
  • Add comments explaining why RequireFullSync alone is insufficient and why explicit HistorySyncConfig is needed for full backfill behavior.
  • Ensure the new HistorySyncConfig assignment integrates with existing DeviceProps initialization without altering versioning or logging behavior.
pkg/whatsmeow/service/whatsmeow.go

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • The hard‑coded HistorySyncConfig limits (10 years / 2GB) in StartClient are quite opinionated; consider moving them to configuration or at least named constants so deployments can tune history depth and resource usage.
  • Since HistorySyncRequest now always uses SendPeerMessage with context.Background(), consider threading a request/context down into this call so history sync requests can be cancelled or time‑bounded by the caller rather than always using a detached background context.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The hard‑coded `HistorySyncConfig` limits (10 years / 2GB) in `StartClient` are quite opinionated; consider moving them to configuration or at least named constants so deployments can tune history depth and resource usage.
- Since `HistorySyncRequest` now always uses `SendPeerMessage` with `context.Background()`, consider threading a request/context down into this call so history sync requests can be cancelled or time‑bounded by the caller rather than always using a detached background context.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

… + thread caller context

- Extract the HistorySyncConfig depth/size limits into named package
  constants (historyFullSyncDaysLimit / historyFullSyncSizeMbLimit /
  historyStorageQuotaMb) so deployments can tune them in one place.
- Thread the caller's context into HistorySyncRequest instead of a detached
  context.Background(), so the on-demand history-sync peer message can be
  cancelled / time-bounded by the request. Signature updated across the
  ChatService interface, the implementation, and the gin handler
  (ctx.Request.Context()).
@nicolasnovis

Copy link
Copy Markdown
Author

Thanks for the review! Addressed both points in ff3542b:

  • Moved the HistorySyncConfig limits into named package constants (historyFullSyncDaysLimit / historyFullSyncSizeMbLimit / historyStorageQuotaMb) so history depth / resource usage can be tuned in one place.
  • Threaded the caller's context into HistorySyncRequest instead of context.Background(), so the on-demand history-sync peer message can be cancelled / time-bounded by the request (signature updated across the interface, impl and the gin handler via ctx.Request.Context()).

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