timehop / apns

A Go package to interface with the Apple Push Notification Service
https://godoc.org/github.com/timehop/apns
MIT License
185 stars 47 forks source link

Connection Ideas #49

Closed taylortrimble closed 1 year ago

taylortrimble commented 9 years ago

Hi all,

I've shared these ideas with @bdotdub and gone over parts with @nathany now as well. I just found my notes and figured I'd type them here on GitHub as well.

The ideas I will lay out below was guided by some factors from the community:

Here's what I came up with:

The current Connection struct in master is simply a net.Conn wrapper with some configuration. This isn't the same as a mockable interface, and is probably insufficient. In develop, Connection handles three things:

I posit that if we move the responsibility for reconnection into the Client, we can get rid of the Connection altogether and simply use io.ReadWriteCloser. It would work this way:


type ConnectionProvider func(gateway string, cert tls.Certificate) (io.ReadWriteCloser, error)

type Client struct {
    ...
    Gateway       string
    Cert          tls.Certificate
    NewConnection ConnectionProvider
    ...
}

func DefaultConnectionProvider(gateway string, cert tls.Certificate) (tls.Conn, err Error) {
    gatewayParts := strings.Split(gw, ":")
    config := tls.Config{
        Certificates:       []tls.Certificate{cert},
        ServerName:         gatewayParts[0],
    }

    return tls.Dial("tcp", gateway, config)
}

func NewClient(gateway, cert tls.Config) *Client{
    return &Client{
        Gateway: gateway,
        Cert: cert,
        NewConnection: DefaultConnectionProvider,
    }
}

func Example() {
    cert, err := tls.LoadX509KeyPair(certFile, keyFile)
    if err != nil {
        panic("cannot load APNS cert")
    }

    client := NewClient(ProductionGateway, cert)
    ...
}

With this scheme, the Client is able to make a new connection whenever it needs one. The user is able to replace NewConnection to provide a custom-configured connection, as well as replace NewConnection to provide a mock connection. DefaultConnectionProvider is exported so it can be used if the user wants override only a few settings from the default connection.

Let me know what you guys think!

nathany commented 9 years ago

What is an example of using a custom function? Say for #32 Nagel's algorithm.

I like the direction. Though I'm curious about the alternatives:

I'd like to come up with a cleaner way to do gatewayParts before making this something people may need to write.