Ember Data, Rest, Socket.IO, something like a race condition


#1

I am working on a web application that uses a mix of Ember’s rest adapter and socket.io. I have a few models that receive updates on our backend (outside of the Ember/client relationship), whose changes need to be pushed to Ember, immediately, thus the socket connection.

I have written an Ember service that watches for a few socket events, which are pretty simple: They push up a payload of data, representing a model (in the same format as the rest api), and an action (Create, Update, or Delete). The service then uses Ember’s store to perform the appropriate action:

  1. Delete event from socket: If peekRecord returns a record for the deleted ID, it uses store.unloadRecord(…) to remove the record
  2. Create or Update event from socket: store.pushPayload(…) is used to upsert the payload.

This is working great! However…

The problem I’m running into is… if I use the store to create a new record, and model.save() to persist it… When I call model.save() (makes an HTTP Post request), the socket connection returns the new record before the rest api, uses pushPayload to push the new record into store before save updates the record’s ID. The result is two records in Ember’s data store with the same ID. The process goes like this:

  1. let widget = store.createRecord(‘widget’, { label: ‘My Widget’ });
  2. widget.save();
  3. // widget is HTTP posted to rest api
  4. // widget is created in database
  5. // database event triggers socket event, pushing new widget payload back to client: {widgets: [{ id: 69, label: ‘My Widget’ }]}
  6. My aforementioned service runs store.pushPayload({widgets: [{ id: 69, label: ‘My Widget’ }]}); // new widget record is created in store
  7. // original HTTP post request returns with status 201, {widget: { id: 69, label: ‘My Widget’ }}
  8. store updates widget record created in step 1 to reflect id = 69

Store now has two records, representing the same object (widget with id of 69).

Does anyone have any advice or suggestions as to how I can get around this issue?

Thanks! Adam