Skip to content

Close/deinit should be automatic #54

@LeifOfWilsonCreek

Description

@LeifOfWilsonCreek

First, thank you for writing this. RMQClient was my first try, and is extremely frustrating. 👍

Two bug related to close. First:

deinit {
    if isConnected {
        assertionFailure("close() was not called before deinit!")
    }
}

should be

deinit {
    if isConnected {
        try? await close()
    }
}

because otherwise writing the obvious usage doesn't work and alternatives becomes nigh unreadable:

do {
    let conn = try await AMQPConnection.connect(...)
    let chan = try await conn.openChannel()
    try await chan.basicQos(count: 1000, global: false)
    self.connection = conn
    self.channel = chan
} catch {
    print("Failed \(url); error=\(error)")
}

This doesn't work because if conn.openChannel() fails, conn doesn't get an explicit conn.close(), and AMQPConnection asserts. There's no need to make the caller jump through hoops calling .close() explicitly.

Second:

func close(reason: String = "", code: UInt16 = 200) async throws {
    return try await self.close(reason: reason, code: code).get()
}

should be:

func close(reason: String = "", code: UInt16 = 200) async throws {
    if !isConnected {return}  // insert this line
    return try await self.close(reason: reason, code: code).get()
}

Because when the connection is already closed, calling close (a very common mistake when trying to work around the above), causes an infinite hang. Even more confusingly, this hang also happens when an error closes the socket, then the caller tries to call .close() in cleanup.

Those two quick fixes save huge workarounds. Thanks 👍

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions