@@ -422,17 +422,15 @@ void SyncSession::update_error_and_mark_file_for_deletion(SyncError& error, Shou
422
422
}
423
423
}
424
424
425
- void SyncSession::download_fresh_realm (sync::ProtocolErrorInfo::Action server_requests_action )
425
+ void SyncSession::download_fresh_realm (const sync::SessionErrorInfo& error_info )
426
426
{
427
427
// first check that recovery will not be prevented
428
- if (server_requests_action == sync::ProtocolErrorInfo::Action::ClientResetNoRecovery) {
428
+ if (error_info. server_requests_action == sync::ProtocolErrorInfo::Action::ClientResetNoRecovery) {
429
429
auto mode = config (&SyncConfig::client_resync_mode);
430
430
if (mode == ClientResyncMode::Recover) {
431
431
handle_fresh_realm_downloaded (
432
- nullptr ,
433
- {ErrorCodes::RuntimeError,
434
- " A client reset is required but the server does not permit recovery for this client" },
435
- server_requests_action);
432
+ nullptr , {ErrorCodes::RuntimeError,
433
+ " A client reset is required but the server does not permit recovery for this client" });
436
434
return ;
437
435
}
438
436
}
@@ -469,14 +467,15 @@ void SyncSession::download_fresh_realm(sync::ProtocolErrorInfo::Action server_re
469
467
catch (...) {
470
468
// Failed to open the fresh path after attempting to delete it, so we
471
469
// just can't do automatic recovery.
472
- handle_fresh_realm_downloaded (nullptr , exception_to_status (), server_requests_action );
470
+ handle_fresh_realm_downloaded (nullptr , exception_to_status ());
473
471
return ;
474
472
}
475
473
476
474
util::CheckedLockGuard state_lock (m_state_mutex);
477
475
if (m_state != State::Active) {
478
476
return ;
479
477
}
478
+
480
479
RealmConfig fresh_config;
481
480
{
482
481
util::CheckedLockGuard config_lock (m_config_mutex);
@@ -511,7 +510,7 @@ void SyncSession::download_fresh_realm(sync::ProtocolErrorInfo::Action server_re
511
510
using SubscriptionState = sync::SubscriptionSet::State;
512
511
fresh_sub.get_state_change_notification (SubscriptionState::Complete)
513
512
.then ([=](SubscriptionState) -> util::Future<sync::SubscriptionSet> {
514
- if (server_requests_action != sync::ProtocolErrorInfo::Action::MigrateToFLX) {
513
+ if (error_info. server_requests_action != sync::ProtocolErrorInfo::Action::MigrateToFLX) {
515
514
return fresh_sub;
516
515
}
517
516
if (!self->m_migration_store ->is_migration_in_progress ()) {
@@ -527,7 +526,7 @@ void SyncSession::download_fresh_realm(sync::ProtocolErrorInfo::Action server_re
527
526
fresh_sync_session->m_migration_store ->create_subscriptions (*fresh_sub_store, *query_string);
528
527
return fresh_sub_store->get_latest ()
529
528
.get_state_change_notification (SubscriptionState::Complete)
530
- .then ([= ](SubscriptionState) {
529
+ .then ([fresh_sub_store ](SubscriptionState) {
531
530
return fresh_sub_store->get_latest ();
532
531
});
533
532
})
@@ -536,29 +535,32 @@ void SyncSession::download_fresh_realm(sync::ProtocolErrorInfo::Action server_re
536
535
// it immediately
537
536
fresh_sync_session->force_close ();
538
537
if (subs.is_ok ()) {
539
- self->handle_fresh_realm_downloaded (db, Status::OK (), server_requests_action,
540
- std::move (subs.get_value ()));
538
+ self->handle_fresh_realm_downloaded (db, std::move (error_info), std::move (subs.get_value ()));
541
539
}
542
540
else {
543
- self->handle_fresh_realm_downloaded (nullptr , subs.get_status (), server_requests_action );
541
+ self->handle_fresh_realm_downloaded (nullptr , std::move ( subs.get_status ()) );
544
542
}
545
543
});
546
544
}
547
545
else { // pbs
548
- fresh_sync_session->wait_for_download_completion ([=, weak_self = weak_from_this ()](Status s ) {
546
+ fresh_sync_session->wait_for_download_completion ([=, weak_self = weak_from_this ()](Status status ) {
549
547
// Keep the sync session alive while it's downloading, but then close
550
548
// it immediately
551
549
fresh_sync_session->force_close ();
552
550
if (auto strong_self = weak_self.lock ()) {
553
- strong_self->handle_fresh_realm_downloaded (db, s, server_requests_action);
551
+ if (status.is_ok ()) {
552
+ strong_self->handle_fresh_realm_downloaded (db, std::move (error_info));
553
+ }
554
+ else {
555
+ strong_self->handle_fresh_realm_downloaded (nullptr , std::move (status));
556
+ }
554
557
}
555
558
});
556
559
}
557
560
fresh_sync_session->revive_if_needed ();
558
561
}
559
562
560
- void SyncSession::handle_fresh_realm_downloaded (DBRef db, Status status,
561
- sync::ProtocolErrorInfo::Action server_requests_action,
563
+ void SyncSession::handle_fresh_realm_downloaded (DBRef db, StatusWith<sync::SessionErrorInfo> error_info,
562
564
std::optional<sync::SubscriptionSet> new_subs)
563
565
{
564
566
util::CheckedUniqueLock lock (m_state_mutex);
@@ -569,15 +571,15 @@ void SyncSession::handle_fresh_realm_downloaded(DBRef db, Status status,
569
571
// - unable to write the fresh copy to the file system
570
572
// - during download of the fresh copy, the fresh copy itself is reset
571
573
// - in FLX mode there was a problem fulfilling the previously active subscription
572
- if (!status .is_ok ()) {
573
- if (status == ErrorCodes::OperationAborted) {
574
+ if (!error_info .is_ok ()) {
575
+ if (error_info. get_status () == ErrorCodes::OperationAborted) {
574
576
return ;
575
577
}
576
578
lock.unlock ();
577
579
578
580
sync::SessionErrorInfo synthetic (
579
581
Status{ErrorCodes::AutoClientResetFailed,
580
- util::format (" A fatal error occurred during client reset: '%1'" , status. reason ())},
582
+ util::format (" A fatal error occurred during client reset: '%1'" , error_info. get_status ())},
581
583
sync::IsFatal{true });
582
584
handle_error (synthetic);
583
585
return ;
@@ -593,9 +595,12 @@ void SyncSession::handle_fresh_realm_downloaded(DBRef db, Status status,
593
595
// that moving to the inactive state doesn't clear them - they will be
594
596
// re-registered when the session becomes active again.
595
597
{
596
- m_server_requests_action = server_requests_action;
597
598
m_client_reset_fresh_copy = db;
598
599
CompletionCallbacks callbacks;
600
+ // Save the client reset error for when the original sync session is revived
601
+ REALM_ASSERT (error_info.is_ok ()); // required if we get here
602
+ m_client_reset_error = std::move (error_info.get_value ());
603
+
599
604
std::swap (m_completion_callbacks, callbacks);
600
605
// always swap back, even if advance_state throws
601
606
auto guard = util::make_scope_exit ([&]() noexcept {
@@ -607,11 +612,13 @@ void SyncSession::handle_fresh_realm_downloaded(DBRef db, Status status,
607
612
});
608
613
// Do not cancel the notifications on subscriptions.
609
614
bool cancel_subscription_notifications = false ;
615
+ bool is_migration =
616
+ m_client_reset_error->server_requests_action == sync::ProtocolErrorInfo::Action::MigrateToFLX ||
617
+ m_client_reset_error->server_requests_action == sync::ProtocolErrorInfo::Action::RevertToPBS;
610
618
become_inactive (std::move (lock), Status::OK (), cancel_subscription_notifications); // unlocks the lock
611
619
612
620
// Once the session is inactive, update sync config and subscription store after migration.
613
- if (server_requests_action == sync::ProtocolErrorInfo::Action::MigrateToFLX ||
614
- server_requests_action == sync::ProtocolErrorInfo::Action::RevertToPBS) {
621
+ if (is_migration) {
615
622
apply_sync_config_after_migration_or_rollback ();
616
623
auto flx_sync_requested = config (&SyncConfig::flx_sync_requested);
617
624
update_subscription_store (flx_sync_requested, std::move (new_subs));
@@ -695,7 +702,7 @@ void SyncSession::handle_error(sync::SessionErrorInfo error)
695
702
case ClientResyncMode::RecoverOrDiscard:
696
703
[[fallthrough]];
697
704
case ClientResyncMode::Recover:
698
- download_fresh_realm (error. server_requests_action );
705
+ download_fresh_realm (error);
699
706
return ; // do not propagate the error to the user at this point
700
707
}
701
708
break ;
@@ -707,7 +714,7 @@ void SyncSession::handle_error(sync::SessionErrorInfo error)
707
714
m_migration_store->migrate_to_flx (*error.migration_query_string ,
708
715
m_original_sync_config->partition_value );
709
716
save_sync_config_after_migration_or_rollback ();
710
- download_fresh_realm (error. server_requests_action );
717
+ download_fresh_realm (error);
711
718
return ;
712
719
case sync::ProtocolErrorInfo::Action::RevertToPBS:
713
720
// If the client was updated to use FLX natively, but the server was rolled back to PBS,
@@ -721,7 +728,7 @@ void SyncSession::handle_error(sync::SessionErrorInfo error)
721
728
// Original config was PBS, rollback the migration
722
729
m_migration_store->rollback_to_pbs ();
723
730
save_sync_config_after_migration_or_rollback ();
724
- download_fresh_realm (error. server_requests_action );
731
+ download_fresh_realm (error);
725
732
return ;
726
733
case sync::ProtocolErrorInfo::Action::RefreshUser:
727
734
if (auto u = user ()) {
@@ -824,17 +831,15 @@ void SyncSession::handle_progress_update(uint64_t downloaded, uint64_t downloada
824
831
upload_estimate, query_version);
825
832
}
826
833
827
- static sync::Session::Config::ClientReset make_client_reset_config ( const RealmConfig& base_config,
828
- const std::shared_ptr<SyncConfig>& sync_config,
829
- DBRef&& fresh_copy, bool recovery_is_allowed ,
830
- bool schema_migration_detected)
834
+
835
+ static sync::Session::Config::ClientReset
836
+ make_client_reset_config ( const RealmConfig& base_config, const std::shared_ptr<SyncConfig>& sync_config ,
837
+ DBRef&& fresh_copy, sync::SessionErrorInfo&& error_info, bool schema_migration_detected)
831
838
{
832
839
REALM_ASSERT (sync_config->client_resync_mode != ClientResyncMode::Manual);
833
840
834
- sync::Session::Config::ClientReset config;
835
- config.mode = sync_config->client_resync_mode ;
836
- config.fresh_copy = std::move (fresh_copy);
837
- config.recovery_is_allowed = recovery_is_allowed;
841
+ sync::Session::Config::ClientReset config{sync_config->client_resync_mode , std::move (fresh_copy),
842
+ std::move (error_info.status ), error_info.server_requests_action };
838
843
839
844
// The conditions here are asymmetric because if we have *either* a before
840
845
// or after callback we need to make sure to initialize the local schema
@@ -940,17 +945,15 @@ void SyncSession::create_sync_session()
940
945
}
941
946
session_config.custom_http_headers = sync_config.custom_http_headers ;
942
947
943
- if (m_server_requests_action != sync::ProtocolErrorInfo::Action::NoAction) {
944
- // Migrations are allowed to recover local data.
945
- const bool allowed_to_recover = m_server_requests_action == sync::ProtocolErrorInfo::Action::ClientReset ||
946
- m_server_requests_action == sync::ProtocolErrorInfo::Action::MigrateToFLX ||
947
- m_server_requests_action == sync::ProtocolErrorInfo::Action::RevertToPBS;
948
- // Use the original sync config, not the updated one from the migration store
949
- session_config.client_reset_config =
950
- make_client_reset_config (m_config, m_original_sync_config, std::move (m_client_reset_fresh_copy),
951
- allowed_to_recover, m_previous_schema_version.has_value ());
952
- session_config.schema_version = m_previous_schema_version.value_or (m_config.schema_version );
953
- m_server_requests_action = sync::ProtocolErrorInfo::Action::NoAction;
948
+ if (m_client_reset_error) {
949
+ auto client_reset_error = std::exchange (m_client_reset_error, std::nullopt);
950
+ if (client_reset_error->server_requests_action != sync::ProtocolErrorInfo::Action::NoAction) {
951
+ // Use the original sync config, not the updated one from the migration store
952
+ session_config.client_reset_config =
953
+ make_client_reset_config (m_config, m_original_sync_config, std::move (m_client_reset_fresh_copy),
954
+ std::move (*client_reset_error), m_previous_schema_version.has_value ());
955
+ session_config.schema_version = m_previous_schema_version.value_or (m_config.schema_version );
956
+ }
954
957
}
955
958
956
959
session_config.progress_handler = [weak_self](uint_fast64_t downloaded, uint_fast64_t downloadable,
0 commit comments