Skip to content

Instantly share code, notes, and snippets.

@MihaelIsaev
Created July 4, 2022 21:23
Show Gist options
  • Save MihaelIsaev/d5b2fa4243627b51c625515eae4cc74a to your computer and use it in GitHub Desktop.
Save MihaelIsaev/d5b2fa4243627b51c625515eae4cc74a to your computer and use it in GitHub Desktop.
AwesomeWS automatic ping implementation
class YourCustomWS: ClassicObserver, LifecycleHandler {
var pingTask: RepeatedTask?
var waitForPongAttempts: [WaiterForPongAttempt] = []
public required init (app: Application, key: String, path: String, exchangeMode: ExchangeMode) {
super.init(app: app, key: key, path: path, exchangeMode: exchangeMode)
pingTask = app.eventLoop.scheduleRepeatedTask(initialDelay: .seconds(5), delay: .seconds(5)) { [weak self] task in
guard let self = self else { return }
self.waitForPongAttempts.enumerated().forEach { i, object in
if object.attempt >= 2 {
self.waitForPongAttempts.remove(at: i)
object.client.disconnect(code:.normalClosure).whenComplete { _ in }
self.on(close: object.client)
return
} else if object.attempt <= 0 {
object.attempt += 1
object.client.socket.sendPing()
} else {
object.attempt += 1
object.client.socket.sendPing()
}
}
}
app.lifecycle.use(self)
}
func shutdown(_ application: Application) {
pingTask?.cancel()
clients.forEach { $0.disconnect(code: .goingAway) }
}
override func on(open client: AnyClient) {
super.on(open: client)
waitForPongAttempts.append(.init(client))
}
override func on(close client: AnyClient) {
super.on(close: client)
if let index = waitForPongAttempts.firstIndex(where: { $0.client.id == client.id }) {
waitForPongAttempts.remove(at: index)
}
}
override func on(ping client: AnyClient) {
super.on(ping: client)
}
override func on(pong client: AnyClient) {
super.on(pong: client)
self.waitForPongAttempts.first(where: { $0.client.id == client.id })?.attempt = 0
}
class WaiterForPongAttempt: Hashable {
let client: AnyClient
var attempt = 0
init (_ client: AnyClient) {
self.client = client
}
static func == (lhs: MicromarketWS.WaiterForPongAttempt, rhs: MicromarketWS.WaiterForPongAttempt) -> Bool {
lhs.client.id == rhs.client.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(client.id)
}
}
}
extension WSID {
static var yourCustomWS: WSID<YourCustomWS> { .init("custom") }
}
// in configure.swift
app.ws.build(.yourCustomWS)
.at("v1", "custom", "ws")
.mode(.both)
.middlewares(SomeMiddleware())
.serve()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment