Parse-SDK-JS
Parse-SDK-JS copied to clipboard
Stale data with Cloud functions and deleted fields
New Issue Checklist
- [x] I am not disclosing a vulnerability.
- [x] I am not just asking a question.
- [x] I have searched through existing issues.
- [x] I can reproduce the issue with the latest versions of Parse Server and the Parse JS SDK.
Issue Description
Objects returned by Cloud functions may cause the client to return stale data when used with deleted fields.
Steps to reproduce
- Suppose there is a collection
Item
with optional String-fieldlabel
- Suppose that collection initially contains one Item with
label: 'foobar'
- Suppose there is a cloud function
listItems
that returns the list of items, ie.
Parse.Cloud.define('listItems', async req => await (new Parse.Query(Parse.Object.extend('Item'))).find())
- Call that cloud function and list the item's labels, ie.
(await Parse.Cloud.run('listItems')).map(item => item.get('label')) ==> [ 'foobar' ]
- In Parse dashboard, delete the label of that one Item so that its value becomes undefined
- Call that cloud code function again, without invalidating the client cache (without reloading the browser page):
(await Parse.Cloud.run('listItems')).map(item => item.get('label')) ==> [ 'foobar' ]
Actual Outcome
(await Parse.Cloud.run('listItems')).map(item => item.get('label')) ==> [ 'foobar' ]
Expected Outcome
(await Parse.Cloud.run('listItems')).map(item => item.get('label')) ==> [ undefined ]
Environment
Server
- Parse Server version: master / 4.5.0
- Operating system: Linux
- Local or remote host (AWS, Azure, Google Cloud, Heroku, Digital Ocean, etc): local
Database
- System (MongoDB or Postgres): MongoDB
- Database version: 4.2.8
- Local or remote host (MongoDB Atlas, mLab, AWS, Azure, Google Cloud, etc): local
Client
- Parse JS SDK version: 3.2.0
Logs
It is observable that the second response does not include "label": "foobar"
(or just "label"
) in its response.
Analog to https://github.com/parse-community/Parse-SDK-JS/issues/205 and its fix https://github.com/parse-community/Parse-SDK-JS/pull/206, this seems to be caused by the fact that Parse-SDK-JS uses the SingleInstanceStateController
and Parse.Cloud.run
calls decode
which calls ParseObject.fromJSON(value)
when it should call ParseObject.fromJSON(value, true)
.
The UniqueInstanceStateController
does not exhibit this issue since it takes into account the objCount
when fetching state.
The following patch solves this issue for me. However, I have not been able to come up with a meaningful test case.
diff --git a/src/decode.js b/src/decode.js
index 42512fb..b29bb8e 100644
--- a/src/decode.js
+++ b/src/decode.js
@@ -34,7 +34,7 @@ export default function decode(value: any): any {
return ParseObject.fromJSON(value);
}
if (value.__type === 'Object' && value.className) {
- return ParseObject.fromJSON(value);
+ return ParseObject.fromJSON(value, true);
}
if (value.__type === 'Relation') {
// The parent and key fields will be populated by the parent
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Is there anything missing from the issue description as to get some feedback?
Could you please open a PR with the solution and a test case which reproduces the issue?
@aforemny I can take this from here, or do you want to continue?
@JohannWeging Please do go ahead :-) Thanks!
@aforemny @JohannWeging Did a PR ever get created for this issue? We ran into this same problem, although our case is for deleted fields being returned from Parse.User.logIn()
rather than Parse.Cloud.run()
.
@mtrezza Is there anything I can do to help with this?
After some more investigation, I'm realizing that our particular issue will likely not be fixed by the proposed fix in decode.js
. Our issue comes from Parse.User.logIn
, which doesn't call decode
with the full response object. Instead, it calls _finishFetch
, which then calls stateController.commitServerChanges()
.
The end result is that the network response representing the newly logged-in user is only treated as "changes" to the objectCache, and any previously set fields remain even if they had since been deleted (through the Parse Dashboard, for example).
Between the Parse.Cloud.run
case and this Parse.User.logIn
case, I'm a bit worried that there could be even more places where deleted fields are not being properly handled. Can any Parse maintainers provide some insight into how deleted fields like these are supposed to be handled by the SDK in general?
Is there anything I can do to help with this?
I am not aware of any PR that addresses this issue. I think a failing test case to demo the issue would be helpful. If your issue is unrelated to this existing issue, you could open a new issue for discussion.
@mtrezza I created a PR https://github.com/parse-community/Parse-SDK-JS/pull/1442 with a failing test for the Parse.User.logIn
case. These seem like very similar issues to me, so I'm happy for that PR to also be used to address the Parse.Cloud.run
case.