Skip to content

CBG-5262 fix missing changes with active_only=true and limit=#8144

Open
torcolvin wants to merge 2 commits intomainfrom
CBG-5262
Open

CBG-5262 fix missing changes with active_only=true and limit=#8144
torcolvin wants to merge 2 commits intomainfrom
CBG-5262

Conversation

@torcolvin
Copy link
Copy Markdown
Collaborator

CBG-5262 fix missing changes with active_only=true and limit=

When ActiveOnly is set, the N1QL query will filtered tombstoned documents but not documents which have undergone a channel filter. In this case, active only and limit were compatible. In the case of a channel removal, the limit

To make sure this works in cases of mixed active/inactive documents and channel backfill:

  • Filter non active entries from getChangesInChannelFromQuery that are not caught by N1QL (channel removals)
  • Fill the active entries from the cache, which could involve parsing a greater number of cached entries than limit has

When activeOnly is set, that doesn't populate channel cache, so it isn't a problem to filter the entries for getChangesInChannelFromQuery.

  • Are there test cases I should be covering that are missing?
  • Is there a more efficient way to avoid the extra loop in GetChanges?

Pre-review checklist

  • Removed debug logging (fmt.Print, log.Print, ...)
  • Logging sensitive data? Make sure it's tagged (e.g. base.UD(docID), base.MD(dbName))
  • Updated relevant information in the API specifications (such as endpoint descriptions, schemas, ...) in docs/api

Integration Tests

When ActiveOnly is set, the N1QL query will filtered tombstoned documents but not documents which have undergone a
channel filter.

To make sure this works in cases of mixed active/inactive documents and channel backfill:

- Filter non active entries from getChangesInChannelFromQuery that are not caught by N1QL (channel removals)
- Fill the active entries from the cache, which could involve parsing a greater number of cached entries than limit has
Copilot AI review requested due to automatic review settings April 1, 2026 22:04
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes an edge case in the channel cache changes retrieval path where active_only=true combined with limit could lead to returning fewer active changes than requested, especially when non-active entries (e.g., channel removals) are interleaved with active documents.

Changes:

  • Filter non-active (removal/deleted) entries during getChangesInChannelFromQuery when activeOnly is set, so limit calculations operate on active entries only.
  • Adjust singleChannelCacheImpl.GetChanges to scan cached entries and skip non-active ones when trying to fill up to Limit in ActiveOnly mode.
  • Add a unit test covering ActiveOnly + Limit behavior with a small channel cache length.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
db/channel_cache_test.go Adds a regression test for active_only=true with limit when cache contains mixed active/removal entries.
db/channel_cache_single.go Updates cache+query merge logic to avoid limit being “consumed” by non-active cached entries in ActiveOnly mode.
db/changes_view.go Filters out non-active query rows in activeOnly mode and updates limit loop logic accordingly.

Comment thread db/channel_cache_single.go Outdated
Comment on lines +452 to +465
if !options.ActiveOnly || len(resultFromQuery)+len(resultFromCache) <= options.Limit {
result = append(result, resultFromCache[0:n]...)
} else {
totalEntries := len(result)
for _, entry := range resultFromCache {
if totalEntries >= options.Limit {
break
}
if !entry.IsActive() {
continue
}
result = append(result, entry)
totalEntries++
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

When ActiveOnly is true and Limit is 0 (meaning “no limit”), the new branch will take the else path and immediately break because totalEntries >= options.Limit (0). That prevents any cached entries from being appended, so GetChanges can incorrectly return only the query results and drop newer cached active entries.

Suggestion: treat Limit==0 as unlimited in this logic (e.g., include it in the fast-path append, or make the loop’s break condition conditional on options.Limit > 0). Also consider always filtering out non-active cache entries when ActiveOnly is true, even when unlimited.

Copilot uses AI. Check for mistakes.
Comment thread db/channel_cache_test.go Outdated
Comment thread db/channel_cache_test.go Outdated
Comment thread db/changes_view.go Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Comment thread db/changes_view.go
Comment on lines +154 to 158
// If active-only, loop until either retrieve (limit) active entries, or reach endSeq.
if activeOnly {
// If we've reached limit, we're done
if activeEntryCount >= limit || limit == 0 {
if len(entries) >= limit || limit == 0 {
break
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

In activeOnly mode, entries accumulates across loop iterations, but each call to QueryChannels still uses the original limit. After filtering out non-active rows, a later iteration can append more than the remaining needed entries, resulting in len(entries) > limit and violating the requested limit. Consider querying with remaining := limit - len(entries) (when limit > 0) and/or truncating entries to limit before returning.

Copilot uses AI. Check for mistakes.
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.

2 participants