-
Notifications
You must be signed in to change notification settings - Fork 170
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
RCORE-2129 Do not send empty upload messages if there are no downloads to ack #7859
Conversation
Pull Request Test Coverage Report for Build daniel.tabacaru_852Details
💛 - Coveralls |
e8eae22
to
e4c353b
Compare
153332b
to
f6a363d
Compare
Pull Request Test Coverage Report for Build daniel.tabacaru_872Details
💛 - Coveralls |
test/object-store/sync/flx_sync.cpp
Outdated
} | ||
// Check no upload messages are sent during bootstrap. | ||
if (data.event == SyncClientHookEvent::BootstrapMessageProcessed) { | ||
should_send_upload = false; |
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.
do we want to check that we actually hit these cases in the test somehow?
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 could add a state machine (considered that actually)
test/object-store/sync/flx_sync.cpp
Outdated
if (data.query_version == 0) { | ||
return SyncClientHookAction::NoAction; | ||
} | ||
auto session = weak_session.lock(); |
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.
do we actually use the session here anywhere?
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.
no. i'll remove it.
test/object-store/sync/flx_sync.cpp
Outdated
auto new_subs = realm->get_latest_subscription_set().make_mutable_copy(); | ||
new_subs.insert_or_assign(Query(table)); | ||
auto subs = new_subs.commit(); | ||
subs.get_state_change_notification(sync::SubscriptionSet::State::Complete).get(); |
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.
should we add something here where we do a write in the DB that can't result in an upload - like say writing to a table not prefixed by class_
and make sure it doesn't send any uploads?
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.
great suggestion.
@@ -5023,6 +5023,44 @@ TEST_CASE("flx: nested collections in mixed", "[sync][flx][baas]") { | |||
CHECK(nested_list.get_any(1) == "foo"); | |||
} | |||
|
|||
TEST_CASE("flx: no upload during bootstraps", "[sync][flx][bootstrap][baas]") { | |||
FLXSyncTestHarness harness("flx_bootstrap_no_upload", {g_large_array_schema, {"queryable_int_field"}}); | |||
fill_large_array_schema(harness); |
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.
do we need to use the large array schema here with tons of data to upload/download?
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 in a single download message bootstrap the data is applied immediately before the client gets the chance to send an upload (and after the bootstrap is done there is a server version to ack so the upload is legit). but I can check.
test/object-store/sync/flx_sync.cpp
Outdated
fill_large_array_schema(harness); | ||
bool should_send_upload = true; | ||
|
||
SyncTestFile config(harness.app()->current_user(), harness.schema(), SyncConfig::FLXSyncEnabled{}); |
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.
you can do auto config = harness.make_test_file()
as a shortcut here
test/object-store/sync/flx_sync.cpp
Outdated
// Check no upload messages are sent during bootstrap. | ||
if (data.event == SyncClientHookEvent::BootstrapMessageProcessed) { | ||
CHECK((state.get() == TestState::Start || state.get() == TestState::BootstrapInProgress)); | ||
state.transition_to(TestState::BootstrapInProgress); | ||
} | ||
else if (data.event == SyncClientHookEvent::DownloadMessageIntegrated && | ||
data.batch_state == sync::DownloadBatchState::LastInBatch) { | ||
CHECK(state.get() == TestState::BootstrapInProgress); | ||
state.transition_to(TestState::BootstrapProcessed); | ||
} | ||
else if (data.event == SyncClientHookEvent::UploadMessageSent) { | ||
// Uploads are allowed before a bootstrap starts. | ||
if (state.get() == TestState::Start) { | ||
return SyncClientHookAction::NoAction; | ||
} | ||
CHECK(state.get() == TestState::BootstrapProcessed); | ||
state.transition_to(TestState::BootstrapAck); | ||
} |
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.
It might be more efficient to add this part under a lambda provided to state.transition_with()
since the mutex will only be locked once (and held) instead of every time for the state.get()
and state.transition_to()
calls.
It's not related to your changes, but would also you mind updating this debug statement (one that I added) so it is consistent with the other UPLOAD messages (perhaps remove the |
Don't we need to call |
I think you're right - there's another place where we return early and it calls |
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.
LGTM - thanks for making the update
test/object-store/sync/flx_sync.cpp
Outdated
realm->begin_transaction(); | ||
realm->commit_transaction(); | ||
wait_for_upload(*realm); |
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.
How would this fail without your changes, would it hang?
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.
it would send an upload message. But a recent change made wait_for_upload return immediately if all remaining changesets to upload are empty, so it may not give the client the chance to send the upload (and hence not fail without the change). wait_for_download()
makes more sense because after MARK is sent, then an upload would be sent.
CHANGELOG.md
Outdated
@@ -6,6 +6,7 @@ | |||
|
|||
### Fixed | |||
* When a public name is defined on a property, calling `realm::Results::sort()` or `realm::Results::distinct()` with the internal name could throw an error like `Cannot sort on key path 'NAME': property 'PersonObject.NAME' does not exist`. ([realm/realm-js#6779](https://github.com/realm/realm-js/issues/6779), since v12.12.0) | |||
* Fixed sending empty UPLOAD messages when there is no download to acknowledge ([#2129](https://jira.mongodb.org/browse/RCORE-2129), since v14.8.0). |
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.
Is this a correctness issue or a performance improvement? I don't think it is clear to someone just reading this line what the impact was.
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.
It's a performance improvement. It saves roundtrips to the server. But it's a bug fix since we introduced it in 14.8.0. I'll reword it.
What, How & Why?
We were sending unnecessary uploads to the server when there was no data to synchronize and no downloads to acknowledge.
Fixes #7711.
☑️ ToDos
[ ] C-API, if public C++ API changed[ ]bindgen/spec.yml
, if public C++ API changed