Closed youssef-almardini closed 1 year ago
Hi @youssef-almardini š thanks for raising this issue. Just curious, could you share the lambda functions and/or let us know if you might be using DataStore at all in one of them?
If this is only happening in production, could you try pinning your @aws-amplify/datastore
and aws-amplify
versions to the versions you are running locally? (aws-amplify@4.3.33 & @aws-amplify/datastore@3.12.8)
This error may be occurring because of changes we made recently as you mentioned, introduced in version 4.3.40 which might be the one being used in the production build.
We will continue to investigate this internally and report back with updates as they come. Thank you!
The error you're seeing is a result of #10450 and is intended to replace much more pernicious error states. Specifically, we had cases where query/mutation operations could become interleaved with stopping or clearing operations in unpredictable and incorrect ways. In some observed cases, this resulted in visible database/transaction errors. But, the boundary was ill-defined enough that the result of operating against a "clearing" DataStore was actually just not predictable.
clear()
and stop()
, so that they do not resolve until clearing/stopping operations actually complete. It also essentially "locks" DataStore in the interim. Whereas the operations against DataStore in a clearing
state would previously result in unpredictable, erroneous states or unexpected query results, infringements on that boundary are now predictable.(We are exploring the option of queueing operations up behind this lock. But, there's some nuance here, both in terms of how internal operations interact with this mechanism and how customers could interact with DataStore and know which side that boundary an operation will be executed on. š¬ For now, the solution is to make the boundary clear and visible so you have predictable contracts to program against.)
My suggestion for apps that must clear DataStore mid-session is to put DataStore calls into two categories:
clear()
.
E.g., A customer hits "sign out" and you immediately want to observeQuery
to re-populate a table.clear()
is in progress.
E.g., if you're populating data and your customer hits "sign out", you probably want to abort those operations.For those that should always execute, even if DataStore is clearing, I'd do something like this:
// at app start, set a flag to indicate the app is ready.
let isReady = Promise.resolve();
function signOut() {
isReady = DataStore.clear();
}
async function getData() {
await isReady;
return DataStore.query(Model);
}
For operations that don't make sense if a clear has been invoked, either add another flag that be checked in-line, or try-catch and translate the given DataStoreStateError
into something meaningful in your UI.
I might also add a third category:
await
-ing, just make the call. š¤ With all that said, if the errors only occurs in your test runner, this may be as simple has having the test runner await
on the DataStore.clear()
result before proceeding.
And, if you're already doing these things and still seeing the error, we'll need more detailed repro steps. Specifically, I'd want to start with:
I hope that helps!
Hi š Closing this as we have not heard back from you. If you are still experiencing this issue and in need of assistance, please feel free to comment and provide us with any information previously requested by our team members so we can re-open this issue and be better able to assist you.
Thank you!
@svidgen, this is generally working, but sometimes DataStore get stuck on "stopping"
Having something similar to this:
let isReady = Promise.resolve();
function stop() {
isReady = DataStore.stop();
}
async function getData() {
await isReady;
return DataStore.query(Model);
}
When stuck on "stopping" isReady will never resolve and getData() will never return.
I deal with it with something similar to this, I rather deal with the error than to wait for data indefinitely:
function stop() {
isReady = Promise.any([DataStore.stop(), sleep(1_000)])
}
My app can have frequent DataStore.stop() and start() and this is happening naturally form time to time. It difficult to reproduce it on purpose though. The only reliable way I found is to start DataStore fresh and while it's doing its first sync frequently stop(), start() and mess with the network condition.
Before opening, please confirm:
JavaScript Framework
React Native
Amplify APIs
DataStore
Amplify Categories
api
Environment information
Describe the bug
DataStoreStateError: Tried to execute
DataStore.query()
while DataStore was "Stopping". This can only be done while DataStore is "Started" or "Stopped". To remedy: Ensure all calls tostop()
andclear()
have completed first. If this is not poss...Hi, I have an amplify project to host backend for react-native mobile app. Suddenly it stopped to work. Any call to the data store will receive the message i mentioned above.
Our work plan is to provide amplify backend as an NPM package. This package is used from app developer to make calls to AWS-Amplify. Since 6 months everything works fine until 4 days go. We didn't had breaking changes or something. Just added a few lambda function which i don't think it could cause this issue.
We are starting datastore when app is open.
DataStore.start()
and clear it onSignIng event
andSignOut event
. We didn't make any change in this flow since a long time (4 months).We tried to reproduce the issue locally but it is not possible for somehow. Since we are using
typescript
to write our NPM package. We test functionality locally withnode
ortsx
where everything works, then we publish it and downloaded in another projectreact-native
where everything works good. Once it is deployed, no action from DataStore could be executed. The app crashed andSentry
show us the message above. And again that start to happen 4 days ago until now.Expected behavior
To be able to execute DataStore manipulation functionality (query, save, delete... etc) / Get connection with data store.
Reproduction steps
Whenever we call datastore functions in the react-native app. It will show this message:
DataStoreStateError: Tried to execute
DataStore.query()
while DataStore was "Stopping". This can only be done while DataStore is "Started" or "Stopped". To remedy: Ensure all calls tostop()
andclear()
have completed first. If this is not poss...Code Snippet
Log output
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": "" };
export default awsmobile;
Manual configuration
No response
Additional configuration
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" } }
Mobile Device
iphone
Mobile Operating System
ios
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
logs in production using sentry: