Skip to content
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

Closed
wants to merge 14 commits into from
Closed

Conversation

HerbCaudill
Copy link
Collaborator

  • Refactors BrowserWebSocketClientAdapter and NodeWSServerAdapter for readability and maintainability - see comments below.
  • Makes the retry and keepAlive intervals configurable, so we can speed them up in testing and get those processes covered by tests.
  • Handles the leave message on the server - see comments.
  • Implements the disconnect method on the server - see comments.
  • Refactors the package's test suites to simplify setup.
  • Adds tests to bring this package to 100% coverage.

// first time connecting
this.#log("connecting")
this.peerId = peerId
this.peerMetadata = peerMetadata ?? {}
Copy link
Collaborator Author

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)
Copy link
Collaborator Author

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

Comment on lines +103 to +112
onError = (event: WebSocket.ErrorEvent) => {
const { code } = event.error
if (code === "ECONNREFUSED") {
this.#log("Connection refused, retrying...")
} else {
/* c8 ignore next */
throw event.error
}
}
Copy link
Collaborator Author

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:

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")
})

Copy link
Member

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 })
Copy link
Collaborator Author

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.

} else if (isLeaveMessage(message)) {
const { senderId } = message
const socket = this.sockets[senderId]
/* c8 ignore next */
if (!socket) return
this.#terminate(socket as WebSocketWithIsAlive)

Copy link
Member

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?

Copy link
Member

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) {
Copy link
Collaborator Author

@HerbCaudill HerbCaudill Dec 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed announceConnection to peerCandidate

Comment on lines -172 to -175
// It doesn't seem like this gets called;
// we handle leaving in the socket close logic
// TODO: confirm this
// ?
Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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 () => {
Copy link
Collaborator Author

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 () => {
Copy link
Collaborator Author

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 () => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new test

@HerbCaudill HerbCaudill requested a review from alexjg December 4, 2023 16:27
@HerbCaudill HerbCaudill marked this pull request as ready for review December 4, 2023 16:28
@HerbCaudill HerbCaudill force-pushed the refactor-websocket-adapters branch from 0d07b62 to b919b1d Compare December 4, 2023 17:11
@HerbCaudill HerbCaudill changed the base branch from main to use-repo-tests December 5, 2023 13:28
@HerbCaudill HerbCaudill force-pushed the refactor-websocket-adapters branch from a311513 to af5dd03 Compare December 5, 2023 13:28
This was referenced Dec 5, 2023
@HerbCaudill
Copy link
Collaborator Author

HerbCaudill commented Dec 5, 2023

@HerbCaudill HerbCaudill force-pushed the refactor-websocket-adapters branch from 3c2e71f to 637564f Compare December 28, 2023 16:51
@HerbCaudill HerbCaudill changed the base branch from use-repo-tests to main December 28, 2023 16:54
@HerbCaudill HerbCaudill force-pushed the refactor-websocket-adapters branch from 637564f to 3eeef12 Compare December 28, 2023 17:00
@HerbCaudill
Copy link
Collaborator Author

merged with other stuff

@@ -1,8 +1,9 @@
import {
NetworkAdapter,
type PeerId,
Copy link
Member

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants