【问题标题】:AWS-Amplify DataStoreStateError: Tried to execute DataStore.query() while DataStore was "Stopping"AWS-Amplify DataStoreStateError:尝试在 DataStore “停止”时执行 DataStore.query()
【发布时间】:2022-11-11 00:31:52
【问题描述】:

JavaScript 框架 反应原生

放大 API 数据存储

扩大类别 api

环境信息 细节 描述错误 DataStoreStateError:尝试在 DataStore “停止”时执行 DataStore.query()。 这只能在 DataStore “启动”或“停止”时完成。补救措施: 确保首先完成对 stop() 和 clear() 的所有调用。 如果这不是可能...

嗨,我有一个放大项目来托管 react-native 移动应用程序的后端。突然它停止工作了。任何对数据存储的调用都会收到我上面提到的消息。

我们的工作计划是提供放大后端作为 NPM 包。应用程序开发人员使用此程序包调用 AWS-Amplify。自 6 个月以来,一切正常,直到 4 天。我们没有重大变化或其他东西。刚刚添加了一些我认为不会导致此问题的 lambda 函数。

当应用程序打开时,我们正在启动数据存储。 DataStore.start() 并在 SignIng 事件和 SignOut 事件中清除它。很长一段时间(4 个月)以来,我们没有对此流程进行任何更改。

我们试图在本地重现该问题,但以某种方式不可能。因为我们使用 typescript 来编写我们的 NPM 包。我们使用 node 或 tsx 在本地测试功能,一切正常,然后我们将其发布并下载到另一个项目 react-native 中,一切正常。部署后,无法执行来自 DataStore 的任何操作。应用程序崩溃了,Sentry 向我们显示了上面的消息。 4 天前到现在又开始发生这种情况。

预期行为 能够执行数据存储操作功能(查询、保存、删除...等)/获取与数据存储的连接。

复制步骤 每当我们在 react-native 应用程序中调用数据存储功能时。它将显示此消息:

DataStoreStateError:尝试在 DataStore “停止”时执行 DataStore.query()。 这只能在 DataStore “启动”或“停止”时完成。补救措施: 确保首先完成对 stop() 和 clear() 的所有调用。 如果这不是可能...

代码片段

// Put your code below this line.
    // where i clear data store and start it, just using auth events 
    // Clear the local datastore when signing out.
    // As advised in: https://docs.amplify.aws/lib/datastore/sync/q/platform/js/#clear-local-data
    EventHandler.OnSignOut = async () => {
        if (Application.hasBooted()) {
            await Application.clear();
        }
    };

    // Clear the local datastore when signing in.
    // As advised in: https://docs.amplify.aws/lib/datastore/sync/q/platform/js/#clear-local-data
    EventHandler.OnSignIn = async () => {
        if (Application.hasBooted()) {
            await Application.clear();
        }
    };

    // Boot the application as soon as the DataSync is completed
    // Check if it has not been booted already first
    EventHandler.OnDataSynced = async () => {
        if (!Application.hasBooted()) {
            await Application.boot();
        }
    };
    
    // Where i do datastore call
    /**
 * @name SaveAccount
 * @description: Save or update an account.
 *              If the account already exists in the datastore based
 *              on its id, it is updates. Otherwise a
 * @type {Function}
 * @param {AccountDetails} accountDetails
 * @param {AccountAttributes} params
 * @returns {Promise<AccountDetails>}
 */
const SaveAccount = async (
    accountDetails: AccountDetails,
    params?: AccountAttributes,
): Promise<AccountDetails> => {
    const current = await GetAccountDetails(accountDetails.id);
    if (current instanceof AccountDetails) {
        return await DataStore.save(
            AccountDetails.copyOf(
                current,
                updated => {
                    if (params) {
                        for (const key in params) {
                            updated[key] = params[key];
                        }
                    }
                },
            ),
        );
    }

    accountDetails = accountDetails instanceof AccountDetails
        ? accountDetails
        : new AccountDetails(accountDetails);

    return await DataStore.save(accountDetails);
};

aws-exports.js
/* eslint-disable */
// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.

const awsmobile = {
"aws_project_region": "",
"aws_cognito_identity_pool_id": "",
"aws_cognito_region": "",
"aws_user_pools_id": "",
"aws_user_pools_web_client_id": "",
"oauth": {},
"aws_cognito_username_attributes": [
"EMAIL"
],
"aws_cognito_social_providers": [],
"aws_cognito_signup_attributes": [],
"aws_cognito_mfa_configuration": "OFF",
"aws_cognito_mfa_types": [
"SMS"
],
"aws_cognito_password_protection_settings": {
"passwordPolicyMinLength": 8,
"passwordPolicyCharacters": [
"REQUIRES_LOWERCASE",
"REQUIRES_NUMBERS",
"REQUIRES_UPPERCASE"
]
},
"aws_cognito_verification_mechanisms": [
"EMAIL"
],
"aws_appsync_graphqlEndpoint": "*****",
"aws_appsync_region": "",
"aws_appsync_authenticationType": "API_KEY",
"aws_appsync_apiKey": "",
"aws_user_files_s3_bucket": "",
"aws_user_files_s3_bucket_region": "*"
};

package.json
{
  "name": "@financiallease/react-native-amplify",
  "version": "7.1.0",
  "description": "",
  "author": "itsupport@financiallease.nl",
  "main": "dist/financiallease.js",
  "module": "dist/financiallease.js",
  "browser": "dist/financiallease.js",
  "typings": "dist/financiallease.d.ts",
  "types": "dist/financiallease.d.ts",
  "license": "LGPL",
  "scripts": {
    "__BUNDLING": null,
    "build:clean": "rimraf dist/",
    "build": "npm run build:clean && rollup -c",
    "bundle-local": "npm run build && npm pack && mv -v financiallease-react-native-amplify-*.tgz /usr/local/npm/@financiallease/react-native-amplify.tgz",
    "__LINTING": null,
    "autoformat": "npm run lint-typescript -- --fix && npm run lint-nodejs -- --fix",
    "lint-nodejs": "eslint --config amplify/.eslintrc.js 'amplify/backend/function/**/index.js'",
    "lint-typescript": "eslint --config .eslintrc.js '{src,test}/**/*.ts'",
    "lint": "npm run lint-typescript && npm run lint-nodejs",
    "coverage": "jest -c jest.config.ts --collectCoverage --coverageDirectory=\"./coverage\" --ci --reporters=default --reporters=jest-junit --watchAll=false",
    "test": "jest -c jest.config.ts",
    "__DOC GENERATION": null,
    "docs:generate": "npm run build:clean && sed '/[[_TOC_]]/d' README.md > README.sanitized.md && typedoc --readme README.sanitized.md --entryPoints src --entryPointStrategy expand --out docs --theme hierarchy --name \"React Native Amplify - docs\" --includeVersion",
    "docs:serve": "node -r esm --inspect docker/server.js",
    "__AMPLIFY BACKEND": null,
    "amplify-modelgen": "node amplify/scripts/amplify-modelgen.js",
    "amplify-push": "node amplify/scripts/amplify-push.js",
    "scan": "npm run build && npm run lint && npm run test && npm run docs:generate",
    "upgrade-amplify-deps": "npx npm-check-updates -i '/(@?aws-amplify|@react-native-community/netinfo)/' && npm update"
  },
  "publishConfig": {
    "@financiallease:registry": "https://gitlab.com/api/v4/projects/35071033/packages/npm/"
  },
  "dependencies": {
    "@algolia/client-search": "^4.14.2",
    "@algolia/transporter": "^4.14.2",
    "@aws-amplify/core": "^4.7.2",
    "@aws-amplify/datastore": "^3.12.8",
    "@react-native-async-storage/async-storage": "^1.17.4",
    "@react-native-community/netinfo": "^9.3.0",
    "@types/amplify": "^1.1.25",
    "aws-amplify": "^4.3.33",
    "aws-amplify-react-native": "^6.0.5",
    "aws-sdk": "^2.1142.0",
    "deep-equal": "^2.0.5"
  },
  "devDependencies": {
    "@aws-amplify/cli-extensibility-helper": "^2.3.33",
    "@babel/core": "^7.17.9",
    "@babel/preset-env": "^7.16.11",
    "@babel/preset-typescript": "^7.16.7",
    "@rollup/plugin-alias": "^3.1.9",
    "@rollup/plugin-babel": "^5.3.1",
    "@rollup/plugin-commonjs": "^21.0.3",
    "@rollup/plugin-json": "^4.1.0",
    "@rollup/plugin-multi-entry": "^4.1.0",
    "@rollup/plugin-node-resolve": "^13.1.3",
    "@rollup/plugin-typescript": "^8.3.1",
    "@types/jest": "^27.4.1",
    "@types/jest-when": "^3.5.2",
    "@types/node": "^17.0.30",
    "@typescript-eslint/eslint-plugin": "^5.35.1",
    "@typescript-eslint/parser": "^5.18.0",
    "aws-sdk-mock": "^5.7.0",
    "babel-jest": "^28.0.3",
    "babel-plugin-module-resolver": "^4.1.0",
    "base64-js": "^1.5.1",
    "eslint": "^8.12.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-import-resolver-alias": "^1.1.2",
    "eslint-plugin-jsdoc": "^39.2.9",
    "eslint-plugin-react": "^7.29.4",
    "eslint-plugin-sort-exports": "^0.6.0",
    "esm": "^3.2.25",
    "fetch-mock": "^9.11.0",
    "isomorphic-unfetch": "^3.1.0",
    "jest": "^27.5.1",
    "jest-junit": "^13.2.0",
    "jest-when": "^3.5.1",
    "jsdoc": "^3.6.10",
    "mustache": "^4.2.0",
    "nodemon": "^2.0.16",
    "prettier": "^2.7.1",
    "rimraf": "^3.0.2",
    "rollup": "^2.70.1",
    "rollup-plugin-copy": "^3.4.0",
    "rollup-plugin-dts": "^4.2.2",
    "rollup-plugin-flat-dts": "^1.7.0",
    "rollup-plugin-sourcemaps": "^0.6.3",
    "rollup-plugin-terser": "^7.0.2",
    "rollup-plugin-ts": "^3.0.2",
    "ts-node": "^10.7.0",
    "tsconfig-paths": "^3.14.1",
    "tslib": "^2.3.1",
    "typedoc": "^0.22.15",
    "typedoc-theme-hierarchy": "^1.1.1",
    "typescript": "^4.6.3",
    "uuid": "^8.3.2"
  }
}

哨兵的日志

【问题讨论】:

    标签: amazon-web-services aws-amplify aws-appsync amplify aws-datastore


    【解决方案1】:

    引入此更改 in this PR 以显式处理重叠清除/停止和启动/查询/突变之间的内部竞争条件。以前,DataStore 消费者会看到随机的、不稳定的事务/锁定/损坏错误,这些错误无意义、难以恢复或沉默的.此更改引发了冲突,因此使用代码可以了解并处理这些冲突。

    话虽如此,您只需要确保 DataStore.clear() 首先解决,在确保您尝试运行的查询应该位于该边界的 post-clear() 一侧之后!这个可以就像重试循环或标志一样简单——甚至使用clear() 承诺作为你的“标志”。

    初始化你的标志:

    const onReady = Promise.resolve();
    

    当您需要清除时:

    const onReady = DataStore.clear();
    

    然后,对于清除完成后应该操作的操作:

    await onReady;
    const results = await DataStore.query(...);
    

    对于那些应该被取消(不再有意义)的人,如果他们中断了清除,您需要添加另一个标志,由onReady 管理以检查内联。

    【讨论】:

      猜你喜欢
      • 2020-05-16
      • 2020-08-17
      • 1970-01-01
      • 2020-01-13
      • 1970-01-01
      • 2022-12-14
      • 1970-01-01
      • 1970-01-01
      • 2022-12-06
      相关资源
      最近更新 更多