kinto.js icon indicating copy to clipboard operation
kinto.js copied to clipboard

What to do after received data from Websocket?

Open ptgamr opened this issue 9 years ago • 27 comments

What should we do after received the changes from Websocket? Trigger collection.sync would be inefficient for me (data is already available in the websocket message)

//sample repsonse
{
  channel: "94b660c6-68f3-83c4-97fa-8e8ac4715204-kinto_demo_calendar-record",
  data: "the data that changes",
  event: "update"
}

I think we could create/update/delete record manually. But how to best update the lastModified time is still mysterious.

ptgamr avatar Sep 10 '16 12:09 ptgamr

Good question!

You are right, triggering a sync() is very inefficient. That's we did on the 'calendar' demo here because it was easy for demonstration purposes.

You must store the data locally instead.

If you have chosen to go with the SERVER_WINS approach, it is even simpler, you just stick the incoming data into the local database, like this:

channel.onChange((response) => {
  if (response.event == "create") {
    store.create(response.data, {synced: true})
  }
});

The response.data should contain the last_modified attribute from the server, so — as far as I understand — you shouldn't worry about it.

If you want to detect conflicts, you'll have to go with code like:

channel.onChange((response) => {
  if (response.event == "update") {
    store.get(response.data.id)
     .then(function (existing) {
       if (existing.data._status != 'synced')
            // This was changed locally and not yet synced.
            // compare `existing` and `response.data`
            // or just ignore change (ie. CLIENT_WINS) 
       }
     });
  }
});

Tell us what you find out along the way! It would be nice to add info about that in the documentation!

leplatrem avatar Sep 12 '16 08:09 leplatrem

Thanks @leplatrem for the detailed response. I'll try to do what you suggested.

However, I think it would be perfect if the kintojs client can just provide a simple API to work with for eg.

collection.syncIncomming(dataFromWebsocket, strategy)

which will return a SyncResultObject just like sync()

ptgamr avatar Sep 12 '16 08:09 ptgamr

Good idea!

In your example dataFromWebsocket is what comes from kinto-pusher I guess.

What about something more generic like applyChange(action, data, strategy) ? (disclaimer: I'm not good at naming things)

If you have a draft of some working don't hesitate to share it as a start ;)

leplatrem avatar Sep 12 '16 10:09 leplatrem

Hey @leplatrem, I detected that you guys have a very similar function in collection.js already: https://github.com/Kinto/kinto.js/blob/master/src/collection.js#L621 ;) Maybe we could make a public API for that?

Btw, I'm writing an Ember Data adapter to work with Kinto api: https://github.com/ptgamr/ember-kinto . There is a live demo at: https://ember-kinto-demo.herokuapp.com/

Here is the changes based on what you suggested above: https://github.com/ptgamr/ember-kinto/commit/354c9f59a3b918768013af051763987405f4a39c#diff-1551788d4134d14f484faa251ebee47eR103

Until now I saw that the concept of kinto fits quite nicely with Ember Data ;) Thanks for that!

ptgamr avatar Sep 12 '16 13:09 ptgamr

Maybe we could make a public API for that?

It's actually part of the public API, though it's not documented in the user docs. Could you please tell if using the method works for your use case? If so we may want to document it better. If not we can still improve it :)

n1k0 avatar Sep 12 '16 13:09 n1k0

@n1k0 Sadly that I haven't figured out how to construct a SyncResultObject

import { SyncResultObject } from 'npm:kinto';
new SyncResultObject();

throws me an error:

TypeError: _npmKinto.SyncResultObject is not a constructor

ptgamr avatar Sep 12 '16 14:09 ptgamr

Try

import { SyncResultObject } from "kinto/lib/collection"

Hint: you have sample import statements on top of each esdoc pages (for instance) :)

n1k0 avatar Sep 12 '16 15:09 n1k0

@n1k0 it's really hard for me to figure out what is inside the changeObject. Would you mind give me a hint?

ptgamr avatar Sep 13 '16 13:09 ptgamr

@ptgamr Yeah, that's poorly documented, I agree. The change object contains two properties:

  • changes, an array exposing the list of changes that occurred on the server since the last successful synchronization (basically the list of updated and/or deleted records);
  • lastModified: the last modified timestamp of the remote collection.

I should probably add what I just wrote into the docs.

n1k0 avatar Sep 13 '16 13:09 n1k0

Thanks @n1k0 ...

import { SyncResultObject } from "kinto/lib/collection" doesn't work for me... As I'm using Browserify to import the script into my ember page ember-browserify.

ptgamr avatar Sep 13 '16 13:09 ptgamr

Does const {SyncResultObject} = require("kinto/lib/collection") work?

n1k0 avatar Sep 13 '16 13:09 n1k0

Nope. I guess I have to find another way to import kinto.js

ptgamr avatar Sep 13 '16 13:09 ptgamr

That's very strange

n1k0 avatar Sep 13 '16 13:09 n1k0

@n1k0 for your references, this is the way I'm currently using to import kinto to ember: http://www.jimmylauzau.com/blog/2016/03/22/importing-node-modules-in-ember-js

ptgamr avatar Sep 13 '16 13:09 ptgamr

Oh. It's probably an issue to file against ember-browserify then.

n1k0 avatar Sep 13 '16 14:09 n1k0

Yes.

Ember-browserify cannot be used with named imports e.g. import { foo } from 'bar'; as we have no way of knowing at the time of browserifying what portions of the import are being used.

ptgamr avatar Sep 13 '16 14:09 ptgamr

@n1k0 I made a work around to copy the implementation of SyncResultObject class into my project (as it's fairy simple). And importChanges works like a charm! You can see the latest demo here: https://ember-kinto-demo.herokuapp.com/lists

ptgamr avatar Sep 13 '16 14:09 ptgamr

Awesome :)

n1k0 avatar Sep 13 '16 14:09 n1k0

@ptgamr can we close this issue, or should further action be taken to fully address it?

n1k0 avatar Sep 13 '16 16:09 n1k0

@n1k would be nice if we could add one more section to the Tutorial (https://kintojs.readthedocs.io/en/latest/tutorial/#synchronizing-tasks) to explain how to deal with real-time changes from websocket. Cause I think this is a fairly common use-case, it will make life easier for other developers.

Regarding the importChanges api, it still a hack to re-implement the SyncResultObject. And I think even in the case when you include kinto.js script in your page, it's not possible to construct a new SyncResultObject() because the only reference we have on the page is Kinto, users are not able to access other parts of the lib very easily.

Would it be useful if we could add support for an API call which do not require users to pass in a SyncResultObject ? The api will create one internally.

ptgamr avatar Sep 13 '16 22:09 ptgamr

would be nice if we could add one more section to the Tutorial

@ptgamr Would you be interested in writing it? :)

Would it be useful if we could add support for an API call which do not require users to pass in a SyncResultObject

Yeah probably. It's somewhat of a pain to figure out how to expose things in the compiled file though. If you have suggestions, I take them!

n1k0 avatar Sep 14 '16 07:09 n1k0

@n1k0 yes, I can find sometime prepare the PR this week. Cheers ;)

ptgamr avatar Sep 14 '16 08:09 ptgamr

@ptgamr awesome, thank you 👍

n1k0 avatar Sep 14 '16 09:09 n1k0

Wouldn't it make sense for this (both on the Kinto and the Kinto.js side) to make core?

lgleim avatar Oct 08 '16 18:10 lgleim

Sorry, what do you mean «for this» ? Websockets? If so yes, it would make sense indeed. We took our time because we wanted a pluggable solution that is not tight to a commercial service, nor reimplementing a whole WS backend... It's very probable that the kinto-webpush plugin goes into core once it's stable and accepted.

leplatrem avatar Oct 10 '16 08:10 leplatrem

Websockets/Webpush is exactly what I meant. As far as I understand there is however no direct (automatic) handling of pushed changes in Kintojs. Will this be addressed as well?

lgleim avatar Oct 10 '16 14:10 lgleim

We need to wait for the plugin to be working before doing that. For now there are two ways of handling that:

  • Either the push notification is just a trigger for a sync
  • Or the push notification contains the changes.

In the first case you can already use Kinto.JS with it. The second case is nice but if you miss a push message you start to be outdated.

Natim avatar Oct 11 '16 08:10 Natim