Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subscribing to updates via Faye/websockets results in duplicate records

Update

Demo: http://jsbin.com/ogorab/311/edit


I'm trying to build a simple chat room that updates in realtime using Faye/Websockets. Messages are posted using regular REST, but there is also a subscription via Faye to /messages/created, which uses store.pushPayload to push the new messages.

Now the following scenario happens and I can see where it goes wrong but I have no clue how to solve it:

  1. User submits chat message
  2. ChatController handles the submit, calls createRecord with the chat message, and subsequently #save
  3. The chat messages is instantly shown in the chat (triggered by createRecord). Note that no id has been assigned yet.
  4. A REST request is send to the server
  5. The server first publishes the message to Faye
  6. The server responds to the REST request
  7. Before the ajax call is resolved, a message has arrived at /messages/created
  8. The message is again inserted in the view (it should be merged with the original message of course, but that one still hasn't been assigned an id)
  9. The ajax call is resolved, and the id of the original message is assigned.

This results in duplicate messages, in the following order:

  1. [message via createRecord, will resolve via ajax response]
  2. [message inserted via pushPayload/Faye]

I hope you can understand so far. A solution would be to have Faye wait for the save call to resolve before pushing the payload. Unfortunately I don't have a reference to the record that is being saved (happens in a controller, faye subscription is set up in ApplicationRouter).

Also I would like this to work in a generic way:)

like image 238
Thomas Brus Avatar asked Oct 21 '22 17:10

Thomas Brus


1 Answers

Finally found a solution for this, but other suggestions are still welcome.

Turns out that Store#didSaveRecord updates the id after the record is saved. By overriding this method (and then calling super, in that order), we can first check if a record for that id already exists:

App.Store = DS.Store.extend
  didSaveRecord: (record, data) ->
    # This will remove any existing records with the same id
    @getById(record.constructor, data.id)?.unloadRecord()
    @_super(record, data)
like image 174
Thomas Brus Avatar answered Nov 04 '22 02:11

Thomas Brus