-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
L2l #1
base: master
Are you sure you want to change the base?
L2l #1
Changes from all commits
54cdceb
53382b5
41ff294
ccbb70e
963906e
b784ddd
44c12b2
fed0fc4
9d730ce
098aa62
58f8ae4
7227b50
a7043bf
e6c8acc
f9b3382
ad87b88
4e34871
cf33cc0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import L2LClient from "lively.2lively/client.js"; | ||
import { string, num, promise, fun } from "lively.lang"; | ||
import { Channel } from "./channel.js"; | ||
|
||
|
||
export class L2LChannel extends Channel{ | ||
constructor(senderRecvrA, onReceivedMethodA, senderRecvrB, onReceivedMethodB){ | ||
super(senderRecvrA, onReceivedMethodA, senderRecvrB, onReceivedMethodB); | ||
if (!this.senderRecvrA.l2lclient){ this.senderRecvrA.l2lclient = L2LChannel.makeL2LClient() } | ||
if (!this.senderRecvrB.l2lclient){ this.senderRecvrB.l2lclient = L2LChannel.makeL2LClient() } | ||
} | ||
|
||
static makeL2LClient(hostname,port, namespace,io){ | ||
var client = L2LClient.forceNew({}) | ||
return client | ||
} | ||
|
||
registerReceive(client,method){ | ||
var l2l = client.l2lclient; | ||
l2l.addService("lively.sync", (tracker, msg, ackFn, sender) => { | ||
method(msg.data) | ||
}); | ||
} | ||
|
||
async getSessions(senderA,senderB,ackFn){ | ||
var l2lB = senderB.l2lclient | ||
l2lB.sendTo(l2lB.trackerId,'listRoom',{roomName: l2lB.socketId.split('#')[1]},(a) => {ackFn(a)}) | ||
} | ||
|
||
isOnline() { return this.online; } | ||
|
||
goOffline() { | ||
console.log(this) | ||
this.online = false; | ||
|
||
var l2lA = this.senderRecvrA.l2lclient, | ||
l2lB = this.senderRecvrB.l2lclient | ||
if(!l2lA || l2lA.isRegistered() == false){ console.log('l2lA Missing');return} | ||
if(!l2lB || l2lB.isRegistered() == false){ console.log('l2lB Missing');return} | ||
l2lA.sendTo(l2lA.trackerId,'leaveRoom',{roomName: l2lB.socketId.split('#')[1]}) | ||
|
||
if (this.senderRecvrA && this.senderRecvrA.l2lclient) { | ||
this.senderRecvrA.l2lclient.remove() | ||
console.log('senderRecvrA disconnected') | ||
|
||
} else { | ||
console.log('senderRecvrA not disconnected'); | ||
} | ||
|
||
if (this.senderRecvrB && this.senderRecvrB.l2lclient) { | ||
|
||
this.getSessions(this.senderRecvrA,this.senderRecvrB,(a)=> { | ||
if(a.data.sockets.hasOwnProperty(l2lB.socketId)){ | ||
l2lB.sendTo(l2lB.trackerId,'leaveRoom',{roomName: l2lB.socketId.split('#')[1]}) | ||
l2lB.remove(); | ||
} else { | ||
console.log('senderRecvrB not disconnected'); | ||
} | ||
}) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't the procedure for cleaning up l2lA and l2lB be the same? it seems strange that you have to query for getSessions to disconnect b? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's because I need to make sure it's the last thing in the room before it disconnects, since it's the master. |
||
|
||
} | ||
|
||
|
||
doSend(sender,outgoing,self) { | ||
var { recvr, method, queue, delay, descr } = this.componentsForSender(sender); | ||
sender.l2lclient.sendTo(recvr.l2lclient.id,'lively.sync',outgoing,()=>{console.log('received')}) | ||
// recvr[method](outgoing,sender,self) | ||
} | ||
|
||
|
||
|
||
async goOnline() { | ||
var l2lA = this.senderRecvrA.l2lclient, | ||
l2lB = this.senderRecvrB.l2lclient | ||
await l2lA.whenRegistered(300) | ||
await l2lB.whenRegistered(300) | ||
|
||
this.registerReceive(this.senderRecvrA,this.senderRecvrA.receiveOpsFromMaster) | ||
this.registerReceive(this.senderRecvrB,this.senderRecvrB.receiveOpsFromClient) | ||
|
||
l2lA.sendTo(l2lA.trackerId,'joinRoom',{roomName: l2lB.socketId.split('#')[1]}) | ||
l2lB.sendTo(l2lB.trackerId,'joinRoom',{roomName: l2lB.socketId.split('#')[1]}) | ||
this.online = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to wait for acknowledgment for joining the rooms to be sure we are really only? In other words, what happens when joinRoom fails? I cannot find error handling somewhere |
||
this.watchdogProcess(); | ||
} | ||
|
||
|
||
|
||
|
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,10 @@ import { disconnect, disconnectAll, connect } from "lively.bindings"; | |
import { buildTestWorld, destroyTestWorld } from "./helper.js"; | ||
import { Client } from "../client.js"; | ||
import { Master } from "../master.js"; | ||
|
||
import { L2LChannel as L2LChannel } from "../l2lchannel.js"; | ||
import L2LClient from "lively.2lively/client.js"; | ||
import L2LTracker from "lively.2lively/tracker.js"; | ||
import { Channel} from "../channel.js"; | ||
|
||
// System.decanonicalize("mocha-es6", "http://localhost:9011/lively.sync/tests/sync-test.js") | ||
// var env1, env2, env3, | ||
|
@@ -27,7 +30,7 @@ async function setup(nClients) { | |
for (var i = 0; i < nClients; i++) { | ||
let env = state[`env${i+1}`] = await buildTestWorld(masterEnv.world.exportToJSON(), pt(0,300*(i+1))), | ||
client = state[`client${i+1}`] = new Client(env.world, `client${i+1}`); | ||
client.connectToMaster(master); | ||
await client.connectToMaster(master); | ||
state[`world${i+1}`] = env.world; | ||
connect(env.changeManager, 'changeRecorded', client, 'newChange'); | ||
} | ||
|
@@ -85,6 +88,102 @@ describe("messaging between master and client", () => { | |
|
||
}); | ||
|
||
|
||
|
||
describe("lively2lively backchannel tests", function() { | ||
this.timeout(1*1000) | ||
before(async() =>{ | ||
testingClient = await L2LClient.forceNew({}); | ||
await testingClient.whenRegistered(300); | ||
}) | ||
after(async() => { | ||
await testingClient.remove(); | ||
}) | ||
beforeEach(async () => setup(2)); | ||
afterEach(async () => teardown()); | ||
|
||
it("ensure clients have l2l clients", async () => { | ||
|
||
var {world1, masterWorld, client1, master} = state; | ||
var testChannel = L2LChannel.establish(client1, "receiveOpsFromMaster", master, "receiveOpsFromClient") | ||
|
||
expect((testChannel.senderRecvrA.l2lclient) && (testChannel.senderRecvrA.l2lclient instanceof L2LClient)).equals(true,'client A not L2LClient') | ||
expect((testChannel.senderRecvrB.l2lclient) && (testChannel.senderRecvrB.l2lclient instanceof L2LClient)).equals(true,'client B not L2LClient') | ||
|
||
await testChannel.whenOnline(300) | ||
|
||
testChannel.goOffline(); | ||
}) | ||
|
||
it('ensure clients can share a master', async () => { | ||
|
||
var {world1, masterWorld, client1, client2, master} = state; | ||
var testChannel = L2LChannel.establish(client1, "receiveOpsFromMaster", master, "receiveOpsFromClient") | ||
window.testChannel = testChannel | ||
expect((testChannel.senderRecvrA.l2lclient) && (testChannel.senderRecvrA.l2lclient instanceof L2LClient)).equals(true,'client A not L2LClient') | ||
expect((testChannel.senderRecvrB.l2lclient) && (testChannel.senderRecvrB.l2lclient instanceof L2LClient)).equals(true,'client B not L2LClient') | ||
|
||
await testChannel.whenOnline(300) | ||
|
||
var channelId = testChannel.senderRecvrB.l2lclient.socketId.split('#')[1] | ||
|
||
var testChannel2 = L2LChannel.establish(client2, "receiveOpsFromMaster", master, "receiveOpsFromClient") | ||
|
||
expect((testChannel2.senderRecvrA.l2lclient) && (testChannel2.senderRecvrA.l2lclient instanceof L2LClient)).equals(true,'client A not L2LClient') | ||
expect((testChannel2.senderRecvrB.l2lclient) && (testChannel2.senderRecvrB.l2lclient instanceof L2LClient)).equals(true,'client B not L2LClient') | ||
|
||
await testChannel2.whenOnline(300) | ||
|
||
expect(testChannel2.senderRecvrB === testChannel.senderRecvrB).equals(true,'Clients have different masters') | ||
|
||
testChannel.goOffline(); | ||
testChannel2.goOffline(); | ||
}) | ||
|
||
it('ensure clients can communicate across channel', async () => { | ||
var {world1, masterWorld, client1, master} = state; | ||
var client1Buffer = [] | ||
var masterBuffer = [] | ||
var payload = "Test for lively.sync messaging" | ||
var ack = 'received' | ||
function masterCheck(item){ | ||
masterBuffer.push(item) | ||
} | ||
function ackFn(item){ | ||
client1Buffer.push(item) | ||
client1.l2lclient.sendTo(master.l2lclient.id,'lively.sync',{payload: ack}) | ||
} | ||
client1.receiveOpsFromMaster = ackFn; | ||
master.receiveOpsFromClient = masterCheck; | ||
|
||
var testChannel = L2LChannel.establish(client1, "receiveOpsFromMaster", master, "receiveOpsFromClient") | ||
|
||
await testChannel.whenOnline(500) | ||
|
||
master.l2lclient.sendTo(client1.l2lclient.id,'lively.sync',{payload: payload}) | ||
await promise.waitFor(200, () => client1Buffer.length >= 1); | ||
await promise.waitFor(200, () => masterBuffer.length >= 1); | ||
testChannel.goOffline(); | ||
expect(client1Buffer[0].payload).equals(payload,'payload not correct') | ||
expect(masterBuffer[0].payload).equals(ack,'payload not correct') | ||
}) | ||
|
||
it('Temp test, check status of inherited methods',async() => { | ||
|
||
var {world1, masterWorld, client1, client2, master} = state; | ||
var opChannel = Channel.establish(client1, "receiveOpsFromMaster", master, "receiveOpsFromClient") | ||
// await opChannel.whenOnline(300) | ||
var metaChannel = L2LChannel.establish(client1, "receiveOpsFromMaster", master, "receiveOpsFromClient") | ||
await metaChannel.whenOnline(300) | ||
console.log({state,opChannel,metaChannel,client1,master}) | ||
opChannel.goOffline() | ||
metaChannel.goOffline() | ||
|
||
}) | ||
|
||
}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. None of those tests actually runs lively.sync. How would the tests ""messaging between master and client - single op" and "syncing master with two clients - simple prop" look like when using l2l? |
||
|
||
|
||
describe("syncing master with two clients", function() { | ||
|
||
// this.timeout(5*1000); | ||
|
@@ -192,7 +291,7 @@ describe("syncing master with two clients", function() { | |
expect(masterWorld.fill).equals(Color.green); | ||
expect(world1.fill).equals(Color.yellow); | ||
|
||
client1.connectToMaster(master); | ||
await client1.connectToMaster(master); | ||
await client1.syncWithMaster(); | ||
expect(world1.fill).equals(Color.green); | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use async/awai as much as possible. It makes code much more readable than callback style