You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB Realm Android Java SDK修改Schema后无法触发Client Reset问题

问题

我使用MongoDB官方示例代码修改Schema后,无法触发Client Reset,但通过在Atlas中切换Sync可以完成该操作。即使修复Schema后,Client Reset仍无法触发,请问是否有方法可以知晓Client Reset的触发时机?

以下是官方参考示例代码:

String appID = YOUR_APP_ID; // replace this with your App ID
App app = null;
AtomicReference<App> globalApp = new AtomicReference<>(app);
// accessing the app from within the lambda below requires an effectively final object
app = new App(new AppConfiguration.Builder(appID)
        .defaultSyncClientResetStrategy(new DiscardUnsyncedChangesStrategy() {
            @Override
            public void onBeforeReset(Realm realm) {
                Log.w("EXAMPLE", "Beginning client reset for " + realm.getPath());
            }
            @Override
            public void onAfterReset(Realm before, Realm after) {
                Log.w("EXAMPLE", "Finished client reset for " + before.getPath());
            }
            @Override
            public void onError(SyncSession session, ClientResetRequiredError error) {
                Log.e("EXAMPLE", "Couldn't handle the client reset automatically." +
                        " Falling back to manual client reset execution: "
                        + error.getErrorMessage());
                // close all instances of your realm -- this application only uses one
                globalRealm.close();
                try {
                    Log.w("EXAMPLE", "About to execute the client reset.");
                    // execute the client reset, moving the current realm to a backup file
                    error.executeClientReset();
                    Log.w("EXAMPLE", "Executed the client reset.");
                } catch (IllegalStateException e) {
                    Log.e("EXAMPLE", "Failed to execute the client reset: " + e.getMessage());
                    // The client reset can only proceed if there are no open realms.
                    // if execution failed, ask the user to restart the app, and we'll client reset
                    // when we first open the app connection.
                    AlertDialog restartDialog = new AlertDialog.Builder(activity)
                            .setMessage("Sync error. Restart the application to resume sync.")
                            .setTitle("Restart to Continue")
                            .create();
                    restartDialog.show();
                }
                // open a new instance of the realm. This initializes a new file for the new realm
                // and downloads the backend state. Do this in a background thread so we can wait
                // for server changes to fully download.
                ExecutorService executor = Executors.newSingleThreadExecutor();
                executor.execute(() -> {
                    Realm newRealm = Realm.getInstance(globalConfig);
                    // ensure that the backend state is fully downloaded before proceeding
                    try {
                        globalApp.get().getSync().getSession(globalConfig).downloadAllServerChanges(10000,
                                TimeUnit.MILLISECONDS);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.w("EXAMPLE",
                            "Downloaded server changes for a fresh instance of the realm.");
                    newRealm.close();
                });
                // execute the recovery logic on a background thread
                try {
                    executor.awaitTermination(20000, TimeUnit.MILLISECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        })
        .build());
globalApp.set(app);
解答

Client Reset的触发时机

Client Reset仅在客户端与服务端的同步状态完全无法兼容时才会触发,具体场景包括:

  • 客户端Realm的同步历史与服务端完全脱节(比如服务端手动触发了Client Reset、Schema变更属于不兼容类型且服务端强制重置)
  • 客户端离线时间超过服务端设置的同步历史保留窗口,服务端已清理对应的同步日志
  • 服务端因数据损坏、权限变更等原因,标记该客户端会话需要重置
  • 客户端同步会话出现无法自动恢复的致命错误(如数据校验完全失败、无法访问同步服务)

你的场景中,修改Schema后未触发Client Reset,大概率是因为Schema变更属于兼容型变更(比如新增可选字段、修改字段描述),这类变更不会触发服务端强制重置;而切换Atlas Sync相当于重置了服务端的同步状态,才触发了客户端的重置操作。修复Schema后仍无法触发,可能是客户端本地的同步元数据还保留着旧的兼容状态,未触发服务端的重置标记。

监测Client Reset触发时机的方法

  1. 监听SyncSession状态
    通过SyncSession.addConnectionChangeListener或SyncSession.addProgressListener监听会话状态,当会话进入ClientReset状态时,即为触发时机。

  2. 依赖自定义回调
    你代码中实现的DiscardUnsyncedChangesStrategy的三个回调方法:

    • onBeforeReset:Client Reset开始前触发
    • onAfterReset:Client Reset完成后触发
    • onError:自动重置失败,需要手动处理时触发
      这些方法被调用时,直接表明Client Reset正在执行。
  3. 查看Realm详细日志
    开启Realm的全量日志(设置LogLevel.ALL),搜索ClientResetRequiredError或client reset相关关键词,可获取触发的具体时间和原因。

  4. 手动触发测试
    在Atlas控制台的Sync页面,找到对应客户端ID并执行「Trigger Client Reset」操作,观察客户端的回调是否触发,以此验证你的处理逻辑是否正常。

内容的提问来源于stack exchange,提问作者Vikash Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 05:44:55