-
Notifications
You must be signed in to change notification settings - Fork 58
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
Refactor websocket adapters #248
Conversation
// first time connecting | ||
this.#log("connecting") | ||
this.peerId = peerId | ||
this.peerMetadata = peerMetadata ?? {} |
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.
only set these on initial connection
this.peerMetadata = peerMetadata ?? {} | ||
} else { | ||
this.#log("reconnecting") | ||
assert(peerId === this.peerId) |
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.
...but ensure that the peerId isn't changed when reconnecting
onError = (event: WebSocket.ErrorEvent) => { | ||
const { code } = event.error | ||
if (code === "ECONNREFUSED") { | ||
this.#log("Connection refused, retrying...") | ||
} else { | ||
/* c8 ignore next */ | ||
throw event.error | ||
} | ||
} |
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.
Previously we weren't handling socket errors at all, so they weren't ever surfaced anywhere. This ensures that they're properly thrown. I also have it retry if the server refuses the connection (e.g. it's still starting up). See this test:
automerge-repo/packages/automerge-repo-network-websocket/test/Websocket.test.ts
Lines 95 to 115 in 52572c4
it("should connect even when server is not initially available", async () => { | |
const port = await getPort() //? | |
const retryInterval = 100 | |
const browserAdapter = await setupClient({ port, retryInterval }) | |
const _browserRepo = new Repo({ | |
network: [browserAdapter], | |
peerId: browserPeerId, | |
}) | |
await pause(500) | |
const { serverAdapter } = await setupServer({ port, retryInterval }) | |
const serverRepo = new Repo({ | |
network: [serverAdapter], | |
peerId: serverPeerId, | |
}) | |
await eventPromise(browserAdapter, "peer-candidate") | |
}) |
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.
Much nicer, thanks. It's possible we'll want an exponential backoff at some point but I don't think it's critical at the moment.
this.send({ type: "leave", senderId: this.peerId! }) | ||
assert(this.peerId) | ||
assert(this.socket) | ||
this.send({ type: "leave", senderId: this.peerId }) |
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.
These messages are now handled on the server.
automerge-repo/packages/automerge-repo-network-websocket/src/NodeWSServerAdapter.ts
Lines 147 to 152 in 52572c4
} else if (isLeaveMessage(message)) { | |
const { senderId } = message | |
const socket = this.sockets[senderId] | |
/* c8 ignore next */ | |
if (!socket) return | |
this.#terminate(socket as WebSocketWithIsAlive) |
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.
Will these messages crash an old server?
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.
(We should test unrecognized message handling.)
} | ||
this.remotePeerId = peerId | ||
this.emit("peer-candidate", { peerId, peerMetadata }) | ||
peerCandidate(remotePeerId: PeerId, peerMetadata: PeerMetadata) { |
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.
renamed announceConnection
to peerCandidate
// It doesn't seem like this gets called; | ||
// we handle leaving in the socket close logic | ||
// TODO: confirm this | ||
// ? |
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.
The client adapter does send leave
messages when .disconnect()
is called.
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.
Another candidate for a shared utilities package
peerMetadata: { storageId: undefined, isEphemeral: true }, | ||
supportedProtocolVersions: ["1"], | ||
}) | ||
}) | ||
|
||
it.skip("should announce disconnections", async () => { | ||
it("should announce disconnections", async () => { |
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.
new test (I'd taken a stab at it earlier). fixes #209
await eventPromise(browserAdapter, "peer-candidate") | ||
}) | ||
|
||
it("should reconnect after being disconnected", async () => { |
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.
new test
]) | ||
}) | ||
|
||
it("should connect even when server is not initially available", async () => { |
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.
new test
0d07b62
to
b919b1d
Compare
a311513
to
af5dd03
Compare
Current dependencies on/for this PR:
This stack of pull requests is managed by Graphite. |
787f36e
to
694b532
Compare
af5dd03
to
50db010
Compare
694b532
to
da69dfd
Compare
50db010
to
3eeef12
Compare
3c2e71f
to
637564f
Compare
637564f
to
3eeef12
Compare
merged with other stuff |
@@ -1,8 +1,9 @@ | |||
import { | |||
NetworkAdapter, | |||
type PeerId, |
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.
These type assertions allow imported type removal for transpilers without loading the full object graph. Is there a reason you took them out?
BrowserWebSocketClientAdapter
andNodeWSServerAdapter
for readability and maintainability - see comments below.leave
message on the server - see comments.disconnect
method on the server - see comments.