-
Notifications
You must be signed in to change notification settings - Fork 140
CBG-4753: Add version_type preference for /_changes to allow CV-aware consumers
#7659
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Redocly previews |
torcolvin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some general thoughts in this code review but the
db/changes.go
Outdated
|
|
||
| // ChangeVersionString attempts to return the version string for the preferred ChangesVersionType, but will fall back to rev if cv is not available when requested. | ||
| func (ce *ChangeEntry) ChangeVersionString(versionType ChangesVersionType) string { | ||
| if s, ok := ce.Changes[0][versionType]; ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is pulled into a function, do you think this makes sense to check if len(ce.Changes) > 1 before going into this function to avoid a panic if this is called in a place that is unexpected and there are somehow no changes?
I think in practice a ChangeEntry should always have changes but it is sometimes constructed from an empty struct so there could be a case where it is buggy and I don't want Sync Gateway to panic in prod.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added an AssertfCtx - all of this codepath isn't set up to handle bubbling up errors, but realistically it's an assertion failure anyway and at least avoids a potential panic in prod.
db/changes.go
Outdated
| func (options ChangesOptions) String() string { | ||
| return fmt.Sprintf( | ||
| `{Since: %s, Limit: %d, Conflicts: %t, IncludeDocs: %t, Wait: %t, Continuous: %t, HeartbeatMs: %d, TimeoutMs: %d, ActiveOnly: %t, Revocations: %t, RequestPlusSeq: %d}`, | ||
| `{Since: %s, Limit: %d, Conflicts: %t, IncludeDocs: %t, Wait: %t, Continuous: %t, HeartbeatMs: %d, TimeoutMs: %d, ActiveOnly: %t, Revocations: %t, RequestPlusSeq: %d, VersionType: %s}`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I read this right, VersionType will be empty string for blip or active replicator. Do you think this is confusing if this code was used later? or we should log as %q?
For blip changes feeds probably using cv mode makes sense, but it also doesn't really matter. I'm trying to figure out a way to make debugging this the least amount of confusing.
Should we enforce when calling MultiChangesFeed that VersionType is not an empty string, and then I think this would make some of the other code easier to understand:
row.Changes = []ChangeByVersionType{{ChangesVersionTypeRevTreeID: populatedDoc.CurrentRev}}
switch options.VersionType {
case ChangesVersionTypeCV:
row.Changes[0] = ChangeByVersionType{options.VersionType: populatedDoc.HLV.GetCurrentVersionString()} 2Code has comments. Press enter to view.
case ChangesVersionTypeRevTreeID:
fallthrough
default:
// already initialized with a 'rev' change entry above
}
could become which is more obvious to me than knowing everywhere that options.VersionType = "" means ChangesVersionTypeRevTreeID:
switch options.VersionType {
case ChangesVersionTypeCV:
row.Changes[0] = ChangeByVersionType{options.VersionType: populatedDoc.HLV.GetCurrentVersionString()} 2Code has comments. Press enter to view.
case ChangesVersionTypeRevTreeID:
row.Changes = []ChangeByVersionType{{ChangesVersionTypeRevTreeID: populatedDoc.CurrentRev}}
default:
< err here>
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced with %q to make the empty string logging clearer.
There's already a ticket filed and a TODO to make BLIP use the version type option, but it's not really relevant for this PR.
I kind of agree on setting explicit VersionType values and removing the fallbacks, but it's affecting BLIP code that isn't implemented yet, and it would technically introduce more error codepaths deeper into changes code, which are awkward to handle, since there's no fallback available.
db/changes.go
Outdated
|
|
||
| // AuditReadEvent issues a read event for this change entry. If there is no document body, there will be no event used. | ||
| func (ce *ChangeEntry) AuditReadEvent(ctx context.Context) { | ||
| func (ce *ChangeEntry) AuditReadEvent(ctx context.Context, versionType ChangesVersionType) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could actually avoid changing this API this by just figuring out what ce.changes[0] key is.
It might also be possible to just change ce.ChangeVersionString to just return whichever key is present, since it seems like it should always use cv if it is present and otherwise fall back to rev
One way I thought of to make ce.ChangeVersionString easier (or other code) is to change ChangeByVersionType to be a different type of struct:
type ChangeVersion struct {
revtreeID string
cv string
}
// basically this validates that we never have both when we go to marshal the data to conform to the rest api or blip api?
func (c *ChangeVersion) MarshalJSON() ([]byte, error) {
if c.revtreeID != "" && c.cv != "" {
return nil, fmt.Errorf("having both revtree %q and cv %q is invalid", c.revtreeID, c.cv)
}
<marshal as map>
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this change give us other than indirection in the JSON Marshalling? Accessing fields by .revtreeID instead of ["rev"]?
Do you think that's more beneficial than a closer representation of the wire-protocol for this data type? I'm not convinced
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I changed to use a ce.ChangeVersionString(), which just returns the first version type it found in ce
We have to assume there's only one version type present with this approach - which should be true. That's the cost of being less explicit with preferred version type than the approach previously in this PR.
… to get CV instead of RevIDs
…t and BLIP sendChanges refactor
…ad of silent rev fallback
…rror on fetch - consistent with old behaviour
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds a version_type parameter to the REST API /_changes endpoint that allows CV-aware consumers to request Current Version (CV) values instead of the default Revision Tree IDs. The parameter accepts either rev (default) or cv values, enabling clients to choose their preferred document versioning scheme while maintaining backward compatibility.
Key changes:
- Added
version_typeparameter support for both GET and POST/_changesrequests - Implemented fallback logic to return
revfor older documents that don't have CV values - Updated test utilities and existing tests to work with the new versioning system
Reviewed Changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
rest/changes_api.go |
Adds parsing and validation of version_type parameter for changes feed requests |
rest/changes_test.go |
Comprehensive test coverage for different version types and feed configurations |
rest/utilities_testing.go |
Updates test helper function to support both revision and CV version types |
db/changes.go |
Core implementation of version type handling in changes feed logic |
db/sequence_id.go |
Improves error messages with actual sequence values |
docs/api/ |
OpenAPI specification updates for the new parameter |
| Various test files | Updates existing tests to use new test helper function signature |
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.
CBG-4753
version_typeoption to REST API Changes feeds which has two possible options -rev(default) orcvrevversion of the change).revmay still be produced on a feed requestingcvIntegration Tests
GSI=true,xattrs=truehttps://jenkins.sgwdev.com/job/SyncGatewayIntegration/37/