Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Setting and unsetting property without saving Parse.Object causes server error #2117

Open
wants to merge 10 commits into
base: alpha
Choose a base branch
from

Conversation

mortenmo
Copy link
Contributor

@mortenmo mortenmo commented Apr 29, 2024

Pull Request

Issue

Closes: #1798

Approach

On the path of making my app work well offline, this was one more blocker.

The problem is that if you set a parent object o.set('data', {a: b, b: 3}) and then set or unset anything on data (example: o.unset('data.a') without saving between (or save failed for no connection), you get a server error on save(). 1798 indicates this needs to be fixed on client. What fails seems to be mongo doesn't support setting an object and then sub-properties in the same call which is what the server attempts to do in this case.

This fix merges Ops if a "parent" Op exists locally and is not changed and applies the new Op to that parent. In the end this means that when sent to server it wont create the issue above and succeed even if subproperties were set/unset/incremented as a part of local operation before save.

Small(?) change to ParseObject.set with calling validPendingParentOp that if the current Op attribute has dots (.) it will look for pending parent Operations. If one is found, applyOpToParent is called taking the new Op and applying the change to it locally. Put these new functions in ParseOp, but that might not be the best place for them (maybe ObjectStateController?).

Tasks

  • Add tests
  • Add test to validate server can save properly now

Copy link

Thanks for opening this pull request!

Copy link

codecov bot commented Apr 29, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (b50790a) to head (fdba10f).
Report is 47 commits behind head on alpha.

Additional details and impacted files
@@            Coverage Diff             @@
##             alpha     #2117    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files           61        64     +3     
  Lines         6186      6398   +212     
  Branches      1499      1543    +44     
==========================================
+ Hits          6186      6398   +212     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@dplewis
Copy link
Member

dplewis commented Apr 29, 2024

Can you check code coverage? Looks like you are missing a test.

@mortenmo
Copy link
Contributor Author

Another alternative solution that might be preferred is to put a similar fix into ParseObject._getSaveJSON() instead? That means the Ops array stays the same (which is actually what the tests should check I'll fix that, that's in the end what the server cares about). But the data is merged in the saveJSON only.

@mtrezza mtrezza changed the title fix: 1798 - When property and subproperties are set/unset without save, mongo fails fix: Un-/setting property and sub-property without saving causes server error Apr 30, 2024
@mtrezza mtrezza changed the title fix: Un-/setting property and sub-property without saving causes server error fix: Setting and unsetting property without saving causes server error Apr 30, 2024
@dplewis
Copy link
Member

dplewis commented May 3, 2024

@mortenmo Good Work! Can you add an integration test to make sure it's not crashing?

@mortenmo
Copy link
Contributor Author

mortenmo commented May 3, 2024

@mortenmo Good Work! Can you add an integration test to make sure it's not crashing?

Yes. Took a subset of related testcases and made versions that don't save between the object creation and setting/unsetting making sure the results are the same. Just had to figure out how to run them :)

@mortenmo
Copy link
Contributor Author

mortenmo commented May 4, 2024

@dplewis type check was failing I assume from the changing CoreManager to ts. I put in a fix here but have to back that out if you fixed it somewhere else as well.

@dplewis
Copy link
Member

dplewis commented May 5, 2024

Yeah sorry for the confusion. Can you revert changes unrelated to the issue? This PR looks good to me. I just to test it myself. Luckily I’ve been looking into dot notation and the internals recently so it shouldn’t take too long

Copy link
Member

@dplewis dplewis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

mtrezza
mtrezza previously approved these changes May 16, 2024
@dplewis
Copy link
Member

dplewis commented May 17, 2024

@mortenmo Can you rebase from alpha? ParseObject was converted to typescript and is causing conflicts in this PR.

@mortenmo
Copy link
Contributor Author

Made some git mistakes that my git skillz couldn't get me out of, but should be good now.

Copy link
Member

@dplewis dplewis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice Git skillz!

@mtrezza mtrezza changed the title fix: Setting and unsetting property without saving causes server error fix: Setting and unsetting property without saving Parse.Object causes server error May 18, 2024
@mtrezza
Copy link
Member

mtrezza commented May 18, 2024

Isn't there more to this issue? In #1798 it's described that it causes an internal server error, which sounds like Parse Server needs a patch as well, to that doesn't crash on malformed request?

@mortenmo
Copy link
Contributor Author

mortenmo commented May 21, 2024

Isn't there more to this issue? In #1798 it's described that it causes an internal server error, which sounds like Parse Server needs a patch as well, to that doesn't crash on malformed request?

@mtrezza I don't think so. The reason the server "barfed" on the Ops is that Mongo (maybe also Postgres?) doesn't support chained updates when you changed the "parent". When you change/set a property (eg object) to an object and then do a set object.foo to something in the same save, Mongo threw an error. This PR merges those on the client before sending to server (whether it is set or unset), so the server doesn't get those Op commands anymore.

It is unclear to me if the server should support an operation to set object={ ... } and set object.name='foo' in the same save or if the clients should avoid it. It is only a problem if you set a parent and then a "child" property. If you think the server should, then yes there should be another issue opened on the server. But the JS SDK shouldn't trigger that problem anymore, but others might?

@mtrezza
Copy link
Member

mtrezza commented May 21, 2024

I mean it should not be possible to cause the server to crash with internal server error. Even if the Parse JS SDK doesn't send this anymore, it would still be possible to send this to Parse Server via the REST API and cause the crash, right?

@mortenmo
Copy link
Contributor Author

When I tried it manually, server does respond with a 500, but to be clear doesn't completely crash. But yes, it is possible to send through and at a minimum a validation server side with a 400 response is probably better.

@mtrezza
Copy link
Member

mtrezza commented May 21, 2024

I believe a 500 error may actually be a process crash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Internal server error on set followed by unset
3 participants