Skip to content

Commit

Permalink
perf(IRC): parallelize connecting to TMI
Browse files Browse the repository at this point in the history
  • Loading branch information
LosFarmosCTL committed Jan 25, 2024
1 parent ac07178 commit 41e9570
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 27 deletions.
15 changes: 9 additions & 6 deletions Sources/Twitch/Chat/IRC/TwitchIRCClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ internal class TwitchIRCClient {
self.readConnections = [initialReadConnection]
}

internal func connect() async throws -> AsyncThrowingStream<
IncomingMessage, Error
> {
try await connectWriteConnection(self.writeConnection)
internal func connect() async throws -> AsyncThrowingStream<IncomingMessage, Error> {
// initialize all connections concurrently
try await withThrowingTaskGroup(of: Void.self) { group in
group.addTask { try await self.connectWriteConnection(self.writeConnection) }

for connection in self.readConnections {
try await connectReadConnection(connection)
for connection in self.readConnections {
group.addTask { try await self.connectReadConnection(connection) }
}

try await group.waitForAll()
}

return AsyncThrowingStream<IncomingMessage, Error> { continuation in
Expand Down
36 changes: 15 additions & 21 deletions Sources/Twitch/Chat/IRC/TwitchIRCConnection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ internal class TwitchIRCConnection {
}
}

try await requestCapabilities(timeout: timeout)
try await authenticate(timeout: timeout)
try await initialize(timeout: timeout)

return messageStream
}
Expand All @@ -65,40 +64,34 @@ internal class TwitchIRCConnection {
}

func join(to channel: String, timeout: Duration?) async throws {
try await continuations.register(
JoinContinuation(channel: channel), timeout: timeout
) {
try await self.websocket.send(
OutgoingMessage.join(to: channel).serialize())
}
// send a JOIN command and wait for the confirmation from twitch
try await continuations.register(JoinContinuation(channel: channel), timeout: timeout)
{ try await self.websocket.send(OutgoingMessage.join(to: channel).serialize()) }

joinedChannels.insert(channel)
}

func part(from channel: String, timeout: Duration?) async throws {
try await continuations.register(
PartContinuation(channel: channel), timeout: timeout
) {
try await self.websocket.send(
OutgoingMessage.part(from: channel).serialize())
}
// send a PART command and wait for the confirmation from twitch
try await continuations.register(PartContinuation(channel: channel), timeout: timeout)
{ try await self.websocket.send(OutgoingMessage.part(from: channel).serialize()) }

joinedChannels.remove(channel)
}

private func requestCapabilities(timeout: Duration?) async throws {
try await continuations.register(
CapabilitiesContinuation(), timeout: timeout
) {
private func initialize(timeout: Duration?) async throws {
// send a CAP REQ command and wait for the confirmation from twitch
try await continuations.register(CapabilitiesContinuation(), timeout: timeout) {
let message = OutgoingMessage.capabilities([.commands, .tags])
try await self.websocket.send(message.serialize())

try await self.authenticate(timeout: timeout)
}
}

private func authenticate(timeout: Duration?) async throws {
try await continuations.register(
AuthenticationContinuation(), timeout: timeout
) {
// send PASS + NICK commands and wait for the confirmation from twitch
try await continuations.register(AuthenticationContinuation(), timeout: timeout) {
var login: String?

// when connecting anonymously, the PASS message can be omitted
Expand All @@ -108,6 +101,7 @@ internal class TwitchIRCConnection {
try await self.websocket.send(pass.serialize())
}

// twitch allows anonymous connections using justinfanXXXXX
let nick = OutgoingMessage.nick(name: login ?? "justinfan12345")
try await self.websocket.send(nick.serialize())
}
Expand Down

0 comments on commit 41e9570

Please sign in to comment.