tinode / chat

Instant messaging platform. Backend in Go. Clients: Swift iOS, Java Android, JS webapp, scriptable command line; chatbots
GNU General Public License v3.0
11.74k stars 1.84k forks source link

P2P conversations cannot be restored after {leave unsub=true} #747

Closed gabriel-vasile closed 2 years ago

gabriel-vasile commented 2 years ago

tinode version: 0.18.5

After this fix P2P conversations cannot be restored after both users {leave unsub=true}.

To reproduce, start with a fresh install of sandbox tinode and run reproduce.html in browser. reproduce.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <script crossorigin="anonymous"
      src="https://cdn.jsdelivr.net/npm/tinode-sdk/umd/tinode.dev.js">
    </script>
    <meta charset="UTF-8">
</head>

<body id="home">
    <h1>HTML5 boilerplate</h1>
<script>
u1 = {
    u: "alice",
    p: "alice123",
}
u2 = {
    u: "bob",
    p: "bob123",
}

t1 = new Tinode({
    host: "localhost:6060",
    apiKey: "AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K",
});
t2 = new Tinode({
    host: "localhost:6060",
    apiKey: "AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K",
});

async function run() {
    await t1.connect()
    await t1.loginBasic(u1.u, u1.p)
    await t2.connect()
    await t2.loginBasic(u2.u, u2.p)
    await t1.subscribe(t2.getCurrentUserID())
    await t2.subscribe(t1.getCurrentUserID())
    await t1.leave(t2.getCurrentUserID(), true)
    await t2.leave(t1.getCurrentUserID(), true)
    await t1.subscribe(t2.getCurrentUserID())
}
run()
</script>
</body>
</html>

expected: last subscribe in reproduce.html runs successfully and conversation is restored with previous messages. got: last subscribe gives {"ctrl":{"id":"118029","topic":"usrrLRncQTBnDg","code":503,"text":"locked","ts":"2022-05-04T08:29:31.127Z"}}

user1 logs:

{"hi":{"id":"118025","ver":"0.18.3","ua":"Undefined (Firefox/95.0; Linux x86_64); tinodejs/0.18.3","lang":"en-US","platf":"web"}}
{"ctrl":{"id":"118025","params":{"build":"mysql:undef","maxFileUploadSize":8388608,"maxMessageSize":262144,"maxSubscriberCount":128,"maxTagCount":16,"maxTagLength":96,"minTagLength":2,"ver":"0.18"},"code":201,"text":"created","ts":"2022-05-04T08:29:31.052Z"}}
{"login":{"id":"118026","scheme":"basic","secret":"Ym9iOmJvYjEyMw=="}}
{"ctrl":{"id":"118026","params":{"authlvl":"auth","expires":"2022-05-18T08:29:31.115Z","token":"Nm9/cppnzEdrroRiFAABAAEAEbHENPtU3yQehINU184fvDKNDiC/oxc26TEFDfgcMwg=","user":"usrNm9_cppnzEc"},"code":200,"text":"ok","ts":"2022-05-04T08:29:31.052Z"}}
{"sub":{"id":"118027","topic":"usrrLRncQTBnDg"}}
{"ctrl":{"id":"118027","topic":"usrrLRncQTBnDg","code":200,"text":"ok","ts":"2022-05-04T08:29:31.118Z"}}
{"pres":{"topic":"usrrLRncQTBnDg","src":"usrrLRncQTBnDg","what":"acs","dacs":{"want":"N","given":"N"}}}
{"leave":{"id":"118028","topic":"usrrLRncQTBnDg","unsub":true}}
{"ctrl":{"id":"118028","topic":"usrrLRncQTBnDg","code":200,"text":"ok","ts":"2022-05-04T08:29:31.125Z"}}
{"sub":{"id":"118029","topic":"usrrLRncQTBnDg"}}
{"ctrl":{"id":"118029","topic":"usrrLRncQTBnDg","code":503,"text":"locked","ts":"2022-05-04T08:29:31.127Z"}}

user2 logs:

{"hi":{"id":"100326","ver":"0.18.3","ua":"Undefined (Firefox/95.0; Linux x86_64); tinodejs/0.18.3","lang":"en-US","platf":"web"}}
{"ctrl":{"id":"100326","params":{"build":"mysql:undef","maxFileUploadSize":8388608,"maxMessageSize":262144,"maxSubscriberCount":128,"maxTagCount":16,"maxTagLength":96,"minTagLength":2,"ver":"0.18"},"code":201,"text":"created","ts":"2022-05-04T08:29:30.97Z"}}
{"login":{"id":"100327","scheme":"basic","secret":"YWxpY2U6YWxpY2UxMjM="}}
{"ctrl":{"id":"100327","params":{"authlvl":"auth","expires":"2022-05-18T08:29:31.036Z","token":"rLRncQTBnDhrroRiFAABAAEAASnT97a1Ei09YNhVPDgRIa26GZ6HetOlq7RVxE17MUg=","user":"usrrLRncQTBnDg"},"code":200,"text":"ok","ts":"2022-05-04T08:29:30.971Z"}}
{"sub":{"id":"100328","topic":"usrNm9_cppnzEc"}}
{"ctrl":{"id":"100328","topic":"usrNm9_cppnzEc","code":200,"text":"ok","ts":"2022-05-04T08:29:31.117Z"}}
{"leave":{"id":"100329","topic":"usrNm9_cppnzEc","unsub":true}}
{"ctrl":{"id":"100329","topic":"usrNm9_cppnzEc","code":200,"text":"ok","ts":"2022-05-04T08:29:31.119Z"}}
or-else commented 2 years ago

The "code":503,"text":"locked" is exactly how it's supposed to work if an attempt to subscribe is made within 5 seconds after unsubscribing.

Please describe a legitimate use case when subscribe must happen within 5 seconds after unsubscribe.

gabriel-vasile commented 2 years ago

Just sleep(5s) before the last subscribe:

<!DOCTYPE html>
<html lang="en">
<head>
    <script crossorigin="anonymous"
      src="https://cdn.jsdelivr.net/npm/tinode-sdk/umd/tinode.dev.js">
    </script>
    <meta charset="UTF-8">
</head>

<body id="home">
    <h1>HTML5 boilerplate</h1>
<script>
u1 = {
    u: "alice",
    p: "alice123",
}
u2 = {
    u: "bob",
    p: "bob123",
}

t1 = new Tinode({
    host: "localhost:6060",
    apiKey: "AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K",
});
t2 = new Tinode({
    host: "localhost:6060",
    apiKey: "AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K",
});
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
async function run() {
    await t1.connect()
    await t1.loginBasic(u1.u, u1.p)
    await t2.connect()
    await t2.loginBasic(u2.u, u2.p)
    await t1.subscribe(t2.getCurrentUserID())
    await t2.subscribe(t1.getCurrentUserID())
    await t1.leave(t2.getCurrentUserID(), true)
    await t2.leave(t1.getCurrentUserID(), true)
    await sleep(5100)
    await t1.subscribe(t2.getCurrentUserID())
}
run()
</script>
</body>
</html>
I2022/05/09 08:59:03 in: '{"sub":{"id":"93280","topic":"usrrgaRT_86T54"}}' sid='K6pyAl_hyF8' uid='PHFQgtoIMfQ'
E2022/05/09 08:59:03 hub: missing both subscriptions for 'p2prgaRT_86T548cVCC2ggx9A' (SHOULD NEVER HAPPEN!)
E2022/05/09 08:59:03 init_topic: failed to load or create topic: p2prgaRT_86T548cVCC2ggx9A internal
or-else commented 2 years ago

Duplicate of #738