Skip to content

Included objects decay to pointers when updating #91

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

Closed
TylerBrock opened this issue Nov 12, 2015 · 13 comments
Closed

Included objects decay to pointers when updating #91

TylerBrock opened this issue Nov 12, 2015 · 13 comments

Comments

@TylerBrock
Copy link
Contributor

We are seeing strange behavior that is different that that of the JS 1.5 and lower SDK in that when we update a field on an object that has included objects (fully hydrated), we see that the included objects decay to pointers after performing the update. We want to add this to the list of things we've discovered as blockers in #73.

This is a reproduction using the Parse JS SDK 1.6.9:

Setup

class Brand extends Parse.Object {
  constructor(attributes, options) {
    super('Brand', attributes, options);
  }
}
Parse.Object.registerSubclass('Brand', Brand);

class Item extends Parse.Object {
  constructor(attributes, options) {
    super('Item', attributes, options);
  }
}
Parse.Object.registerSubclass('Item', Item);

Test

var freshItem = new Item({cool: true});
var freshBrand = new Brand({item: item});

Parse.Object.saveAll([freshItem, freshBrand]).then((brand, item) => {
  var query = new Parse.Query(Brand);
  query.include('item');
  return query.get(brand.id);
}).then((savedBrand) => {
  var item = savedBrand.get('item');
  assert(item.has("cool"));  // has attributes of item (not decayed)
  assert(item.get("cool"));  // has attributes of item (not decayed)

  // This update will cause included objects on savedBrand to decay.
  brand.set('newField', true);

  return brand.save().then((updatedBrand) => {
    var item = savedBrand.get('item');
    assert(item.has("cool")); // fails, no attributes of item present (decayed)
    assert(item.get("cool")); // fails, no attributes of item present (decayed)
  });
})

When we attempt the same actions in the 1.5 SDK and lower the pointers do not decay (run line by line in our node REPL)

var Item = Parse.Object.extend("Item")
var Brand = Parse.Object.extend("Brand")

var brand = new Brand({name: "Acme"})
var item = new Item({brand: brand})

item.save()

var itemRef;
var itemQuery = new Parse.Query(Item);
itemQuery.include("brand").get("n0EnLswyJv").then(function(fetchedItem) {
  itemRef = fetchedItem;
})

itemRef.get("brand").get("name")
> 'Acme'

itemRef.set("price", 30)
itemRef.save()
itemRef.get("brand").get("name")
> 'Acme'
@TylerBrock TylerBrock changed the title Included objects decay to pointers when updating objects Included objects decay to pointers when updating Nov 12, 2015
@diegohaz
Copy link

I'm having the same issue.

@polerin
Copy link

polerin commented Dec 14, 2015

Same. This is wrecking havoc with my cloud code.

@whynotmatt
Copy link

I'm seeing the same error.

@andrewimm
Copy link
Contributor

I believe I have a fix. The "known server data" in the save response was overaggresively overwriting local data. Once I have some extra unit tests in place, I'll attempt to push this later today.

@andrewimm
Copy link
Contributor

Actually, I'm stumped. I added some extra checks that I thought might help, but then I went back to make some unit tests that only pass with the new changes, and I was unable to make anything fail prior to these changes.

I went back and ran Tyler's tests line-by-line in node using v1.6.13, and I get the expected "correct" behavior, no matter which objects I manipulate. Since there are so many people here with the same issue, can someone please come up with a reproducible test case?

@polerin
Copy link

polerin commented Jan 5, 2016

I'll try to rewrite one. I'm sorta tight on time so it won't be right this second.

@TylerBrock
Copy link
Contributor Author

Andrew, I also see the test work with 1.7.0, however we see this happen in production a lot in the following case:

  1. Query for object and include related objects
  2. Save object and wait on the result
  3. Before the save returns, run a before save hook on the same api server
  4. The save returns with an object no longer having the included related objects (decayed)

@andrewimm
Copy link
Contributor

@TylerBrock is that using parse-server? if so, I think it's a problem for that codebase, not this one.

@TylerBrock
Copy link
Contributor Author

No, using parse classic, we haven't moved off yet.

@andrewimm
Copy link
Contributor

Okay, got confused by the "same api server" bit. I'll take a look and see if I can repro this.

@TylerBrock
Copy link
Contributor Author

Thanks, let me know if i can help. We resolve the issue by storing the included object properties in a higher scope and then not depending on it further down the promise chain after the object decays.

@TylerBrock
Copy link
Contributor Author

This is the annotated block of code where we have the hack for the decay (one example of it at least)

  var phoneNumber;
  var messageQuery = new Parse.Query(Message);
  messageQuery.equalTo("sid", sid);
  messageQuery.include("fromAgent");
  messageQuery.first().then(function(message) {
    // We do this because message decays after being saved :-(
    phoneNumber = message.get('fromAgent').get('phoneNumber');
    message.set("status", newStatus);

    // ... do other stuff with message

    // message has a beforeSave() where we hydrate the object and serialize it back out
    // on this very same instance of Parse and that happens in between the next two lines
    return message.save();
  }).then(function(message) {
    // message.get('fromAgent').get('phoneNumber') is undefined here

    // this is where we use fromAgents's phone number....
  } 

@stale
Copy link

stale bot commented Feb 6, 2019

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.

@stale stale bot added the wontfix label Feb 6, 2019
@stale stale bot closed this as completed Feb 13, 2019
@dplewis dplewis added resolved and removed stale labels Oct 12, 2020
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

No branches or pull requests

6 participants