moscajs / mosca

MQTT broker as a module
mosca.io
3.2k stars 509 forks source link

(Some) packages are not being delivered after client spent some time offline #549

Open benlikeshotchocolate opened 7 years ago

benlikeshotchocolate commented 7 years ago

I’m stuck with a problem that I cannot resolve. A client, that has subscriptions to a topic disconnect for some time. When it goes back online, only a subset of the packages that have been sent to the topic subscripted too will be delivered.

From my investigations, it seems like packages are being delivered to client if (and only if) they were sent within one hour after the client disconnected.

However, my expire config for both packages and subscriptions is set to 48h.

I'm very thankful for any hint:

var ascoltatore = {
    type: 'mongo',
    url: Config.db_url,
    pubsubCollection: 'ascoltatori',
    mongo: {}

};

var settings = {
    port: 62797,
    backend: ascoltatore,
    id: 'testbroker',
    stats: false,
    persistence: {
        factory: mosca.persistence.Mongo,
        url: ascoltatore.url,
        ttl: {
            subscriptions: 172800000,
            packets: 172800000
        }
    }
};

var server = new mosca.Server(settings);
mcollina commented 7 years ago

Can you please check if the ttl indexed defined in your database are configured correctly? There might be bugs in this block of code https://github.com/mcollina/mosca/blob/master/lib/persistence/mongo.js#L119-L144.

benlikeshotchocolate commented 7 years ago

I think the ttl indexes are correct because when i was debugging the code, it did not enter into the following if statement and packetTTLInSeconds was defined correctly (in my case ~48h):

if (addedIndexObj.length <= 0 || addedIndexObj[0].expireAfterSeconds != packetTTLInSeconds)
{
...
}

here are the indexes defined in my brokers database:

> db.packets.getIndexes()
[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "brokerlocal.packets"
    },
    {
        "v" : 1,
        "key" : {
            "client" : 1
        },
        "name" : "client_1",
        "ns" : "brokerlocal.packets"
    },
    {
        "v" : 1,
        "key" : {
            "added" : 1
        },
        "name" : "added_1",
        "ns" : "brokerlocal.packets",
        "expireAfterSeconds" : 172800
    }
]
mcollina commented 7 years ago

Are the packets still inside MongoDB and they don't get sent, or they are deleted from MongoDB?

benlikeshotchocolate commented 7 years ago

I finally found the cause of the problem. Apparently, the subscription expire date is being ignored:

db.subscriptions.getIndexes()
[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "brokerdb.subscriptions"
    },
    {
        "v" : 1,
        "key" : {
            "client" : 1
        },
        "name" : "client_1",
        "ns" : "brokerdb.subscriptions"
    },
    {
        "v" : 1,
        "key" : {
            "added" : 1
        },
        "name" : "added_1",
        "ns" : "brokerdb.subscriptions",
        "expireAfterSeconds" : 3600
    }
]
mcollina commented 7 years ago

So, that logic has something wrong with it. Would you like to fix it and send a PR?

benlikeshotchocolate commented 7 years ago

I'd look into it. Still a bit confused though, as the expireAfterSeconds field is set correctly on my local machine. However, the remote server that shares the exact same code as my local test machine is having that issue.

mcollina commented 7 years ago

Let me know about your findings!