feathers-plus / feathers-offline-realtime

Offline-first realtime replication, with optimistic updates while connected.
MIT License
33 stars 9 forks source link

Creating a record while having no internet connection fails with timeout #12

Closed madc closed 5 years ago

madc commented 7 years ago

We have implemented optimistic mutation as described in the docs:

    /**
     * Creating a new message using optimisic mutation
     * https://docs.feathersjs.com/guides/offline-first/optimistic-mutation.html
     */
    static actOnCreateMessage = async (obj) => {
        const { conversationID, text }= obj;
        const messagesRealtime = new Realtime(
            this.client.service('api/chat/v1/messages'),
            {
                query: { conversationID },
                publication: record => record.conversationID === conversationID,
                uuid: true
            }
        );

        this.client.use('clientMessages', optimisticMutator({ replicator: messagesRealtime }));
        const clientMessages = this.client.service('clientMessages');

        await messagesRealtime.connect();

        try {
            const response = await clientMessages.create({ conversationID, text });
            return { response };
        } catch (error) {
            return { error };
        }
    }

So as this works fine when connected to the internet, the app breaks with a timeout when offline:

Error: Timeout of 5000ms exceeded calling api/chat/v1/messages::find
eddyystop commented 7 years ago

In https://docs.feathersjs.com/guides/offline-first/strategies.html the Keep queue while disconnected and Process queue on reconnection sections show that optimistic mutation for this repo works only when online.

I will make that more obvious in the docs.

Optimistic mutation while disconnected may or may not come shortly depending on internal issues.

eddyystop commented 7 years ago

Upon review, https://docs.feathersjs.com/guides/offline-first/optimistic-mutation.html already has

Realtime replication only replicates when the client has a connection to the server.
It also requires the client be connected to the server with WebSockets.
madc commented 7 years ago

In other words it is my job to assure a connection is present, otherwise i need to be aware, that unexpected events (timeout, etc) can happen?

eddyystop commented 7 years ago

You should check that replicator.connected === true before doing an optimistic update. You could display a message on the UI otherwise, for example "There is no connection to the server. Only inqueries are allowed at the moment."

It is also your responsibility to inform the replicator when a connection is (re)established or lost using replicator.connect() and replicator.disconnect(). A repo handling this for both browser and react native is being worked on, but that will take a while to get solid in the wild.

eddyystop commented 7 years ago

The replicator.connected === true mentioned above also needs to be done before using the remote service directly as you are doing. There is no possibility of using a remote service directly while disconnected.

The optimistic mutator would return the error Replicator not connected to remote. (offline).

eddyystop commented 7 years ago

I'm leaving this open as it may be useful for others to read.

danieleades commented 5 years ago

Optimistic mutation while disconnected may or may not come shortly depending on internal issues.

What is the state of this? Any progress on "sync-data, sync-net"?

eddyystop commented 5 years ago

It's not on the horizon. There are too many higher priorities.

laurensiusadi commented 5 years ago

I really need to implement sync on reconnect, any suggestions where to start my work @eddyystop ? Thanks

eddyystop commented 5 years ago

Have you considered using couch and pouch? I may have the names wrong but the db is popular in offline.

laurensiusadi commented 5 years ago

@eddyystop yes I've seen it before. so somehow need to integrate pouchDB with feathers-client, and couchDB with feathers server?

danieleades commented 5 years ago

I've played around with using pouchDB/couchDB with feathers, but found there wasn't a lot of value there. It ends up being a lot of indirection for little gain, and I found it far easier to write and reason about my data model by using pouchdb directly (without feathers). I would love to see offline-first in feathers, but I think it would need to be first class support, rather than a shallow integration with pouchDB

laurensiusadi commented 5 years ago

@danieleades So what's the stack you end up using? (I'm planning to use Vue) So pouchDB then setup server with what? How bout authentication?

danieleades commented 5 years ago

@danieleades So what's the stack you end up using? (I'm planning to use Vue) So pouchDB then setup server with what? How bout authentication?

Actually in the end i used RxDB. It's an opinionated, event-driven database built on top of pouchdb. I heartily recommend it. Didn't get as far as authentication, but you could leverage RxDB's local storage for storing tokens. I ran a CouchDB instance in a docker container for testing the offline-first sync. worked a treat.

I desperately wanted feathers to solve all my problems, mainly because feathers-vuex is such a nice implementation, but in the end RxDB was far more tidy.

laurensiusadi commented 5 years ago

@danieleades I'm going to check that out. Have you tried Hoodie? It's also build on top of pouchdb and sync directly with couchdb server. It has auth but not perfect (forgot password not working properly). Problem was it's not updated regularly and got some bugs.

danieleades commented 5 years ago

@laurensiusadi I did look at Hoodie, and I have to say it has matured a lot since I last looked at it. Could be a good option. I chose rxdb for two reasons-

  1. JsonSchema-based validation (non typesafe applications freak me out)
  2. Query subscriptions- rxdb is realtime, which was kind of a killer feature for me. I wanted multiple tabs/users with live updates, and rxdb made this pretty easy