Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Creating a Basic Chat App with Pub/Sub and Go

Avatar for Tom Camp Tom Camp
October 27, 2021

Creating a Basic Chat App with Pub/Sub and Go

Go has been designed from the ground up around scalability and concurrency. Pub/Sub, a common messaging paradigm, is not only also designed around these concepts, but actually mimicks one of Golang’s core concepts; channels.
In this talk, I will be giving an introduction to the concepts of Pub/Sub, its relevance to common Golang use-cases, and then demonstrating how one could create a basic chat application using it in Golang.

Avatar for Tom Camp

Tom Camp

October 27, 2021

Other Decks in Technology

Transcript

  1. It’s good to be back in the ‘real world’! People

    are increasingly expecting realtime experiences from their apps @tomcamp333
  2. What we’ll be talking about... • How networking has changed

    over the years (and parallels in programming changes) • Using goroutines, Go Channels, and Pub/Sub to make a simple chat app! • Pub/Sub beyond chat @tomcamp333
  3. REST: Request - Response Method Very simple, but… • Request

    sent each time a response is required • Slow communication time • Requester doesn’t know when new data is available • Lots of needless requests @tomcamp333
  4. REST: Request - Response Method Analogous to synchronous programming: •

    Code running on main function (client) • Calls a function (server) • Main waits for response from function before continuing @tomcamp333
  5. Long Polling Method Long polling allows us to avoid unnecessary

    requests, but… • Still needs a full round trip per update • If the rate of updates is not known, we still need to request updates frequently to make sure we don’t miss information @tomcamp333
  6. Long Polling Method Analogous to asynchronous functions: • Main function

    (the client) makes a request to an async function (the server) • Main does other things while async function runs • Once async function finishes (there’s info available), it returns results to main @tomcamp333
  7. Realtime Subscription Eg MQTT, SSE, WebSockets: • Establishes a connection,

    then allows for messages to be sent at any time • No need to request updates (no round trip required!) • Receives updates at the rate they’re generated @tomcamp333
  8. Realtime Subscription Analogous to Go channels: • Two goroutines (clients/servers)

    • They share a Channel (connection), over which they can communicate with one another asynchronously @tomcamp333
  9. How does data move around the web? @tomcamp333 1. Rest

    Requests 2. Long Polling 3. Realtime Subscriptions
  10. Pub/Sub with Go Channels We can duplicate this behaviour with

    Go Channels: type Pubsub struct { subscriptions map[string][]chan string } func (pubsub *Pubsub) Publish(topic string, message string) { for _, ch := range pubsub.subscriptions[topic] { ch <- message } } @tomcamp333
  11. It is no coincidence that we’ve developed tools in both

    programming (Go Channels) and communication (Pub/Sub) to allow for complex asynchronous communication between asynchronous entities @tomcamp333
  12. What do we need? • Usernames • Ability to send

    messages to everyone in a chat room • Ability to receive messages from everyone in a chat room Preferably we can: • Check what happened before we joined (the chat history) • See who is currently online @tomcamp333
  13. Connecting to a Pub/Sub Broker In order to establish a

    connection with our broker (Ably): • We need to authenticate using a key or token • We need to say who we are so others can identify us import "github.com/ably/ably-go/ably" client, err := ably.NewRealtime( ably.WithKey( "My Ably API key" ), ably.WithClientID(username) ) @tomcamp333
  14. Attaching to a topic Now that we have a connection,

    we need to indicate we’ll be doing something with a topic @tomcamp333 // Connect to the Ably Channel with name 'chat' channel := client.Channels. Get("chat")
  15. Publishing messages Next, we want to send (publish) messages. We

    can do so with channel.Publish(). We will read from the terminal input, and publish to the broker in a goroutine. @tomcamp333 reader := bufio.NewReader(os.Stdin) for { text, _ := reader.ReadString( '\n') _ := channel.Publish(context.Background(), text) }
  16. Subscribing to messages Then, we need to interact with a

    topic (or a Channel as it’s called in Ably). We will subscribe to a channel with channel.SubscribeAll(). @tomcamp333 _, err := channel.SubscribeAll( context.Background(), func(msg *ably.Message) { fmt.Printf( "Received message from %v: '%v'\n" , msg.ClientID, msg.Data ) } )
  17. We can communicate! @tomcamp333 import "github.com/ably/ably-go/ably" client, err := ably.NewRealtime(

    ably.WithKey("My Ably API key"), ably.WithClientID(username) ) _, err := channel.SubscribeAll(context.Background(), func(msg *ably.Message) { fmt.Printf("Received message from %v: '%v'\n", msg.ClientID, msg.Data) }) reader := bufio.NewReader(os.Stdin) for { text, _ := reader.ReadString('\n') _ := channel.Publish(context.Background(), text) }
  18. Listening for enter/leave events Let’s check when people enter and

    leave the chat and print a message to notify of their presence. We can use channel.Presence.SubscribeAll() @tomcamp333 _, _ := channel.Presence.SubscribeAll(context.Background(), func(msg *ably.PresenceMessage) { if msg.Action == ably.PresenceActionEnter { fmt.Printf("%v has entered the chat\n", msg.ClientID) } else if msg.Action == ably.PresenceActionLeave { fmt.Printf("%v has left the chat\n", msg.ClientID) } })
  19. Checking History of chat Let’s check what has been said

    before we joined. @tomcamp333 pages, err := channel.History().Pages(context.Background()) hasHistory := true for ; hasHistory; hasHistory = pages.Next(context.Background()) { for _, msg := range pages.Items() { fmt.Printf( "Message %v: '%v'\n" , msg.ClientID, msg.Data) } }
  20. Check out the code! You can take a look at

    all of the code in the GitHub repository: https://github.com/ably-labs/go-chat @tomcamp333
  21. Pub/Sub can be used for anything! Now we know the

    basics of Pub/Sub. • Publishing, subscribing, Presence and History. It be used to make anything you can think of! • Games • Tracking food/deliveries • IoT device updates • Collaboration projects @tomcamp333
  22. h ps://roshambo.ably.dev/game/1 The rules • Rock beats paper • Paper

    beats scissors • Scissors beats rock GitHub h ps://github.com/ably-labs/ably-rock-paper-scissors Let’s play a game!
  23. • HTML, CSS and JS on the frontend • Go

    validating moves on the backend • Ably as a Pub/Sub broker How is this made?
  24. Ably is running a hackathon in the lounge! Top prize:

    AirPods Pro Theme winners: £100 Amazon Make your own!
  25. Thank you for listening! Any questions? You can find me

    at: @tomcamp333 @ablyrealtime @tomcamp333