golang timer synchronize to multiple clients

Viewed 45

I have a go webserver running that has a websocket to localhost, this waits for a message to be received and then starts a timer. I want the timer to be synchronized across n different clients.

My code is working for only 1 client.

here is my go code:

package main

import (
    "fmt"
    "log"
    "net/http"
    "strconv"
    "time"

    "github.com/gorilla/mux"
    "github.com/gorilla/websocket"
)

type Message struct {
    StartTime string `json:"StartTime"`
}

var (
    wsUpgrader = websocket.Upgrader{
        ReadBufferSize:  1024,
        WriteBufferSize: 1024,
    }

    wsConn *websocket.Conn
)

func WsEndpoint(w http.ResponseWriter, r *http.Request) {

    wsUpgrader.CheckOrigin = func(r *http.Request) bool {

        return true
    }
    var err error
    wsConn, err = wsUpgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Printf("could not upgrade: %s\n", err.Error())
        return
    }
    t, _ := time.ParseDuration("1s")
    tk := time.NewTicker(t)

    defer wsConn.Close()

    for {
        var msg Message

        err := wsConn.ReadJSON(&msg)
        if err != nil {
            fmt.Printf("error reading JSON: %s\n", err.Error())
            break
        }

        fmt.Printf("Message Received: %s\n", msg.StartTime)
        handleTimer(msg.StartTime, tk)
    }

}

func handleTimer(msg string, tk *time.Ticker) {

    i, _ := strconv.Atoi(msg)
    for range tk.C {

        SendMessage(strconv.Itoa(i))

        i -= 1

    }
}

func SendMessage(msg string) {
    err := wsConn.WriteMessage(websocket.TextMessage, []byte(msg))
    if err != nil {
        fmt.Printf("error sending message: %s\n", err.Error())
    }
}

func main() {

    router := mux.NewRouter()

    router.HandleFunc("/socket", WsEndpoint)

    log.Fatal(http.ListenAndServe(":9100", router))

}

and my vue.js app:

<template>
<div>
  <div class="w-full max-w-xs">
    <form class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4" :action="sendMessage" @click.prevent="onSubmit">
    <div class="mb-4">
      <label class="block text-gray-700 text-sm font-bold mb-2" for="something">
        Enter Something
      </label>
      <input v-model="message" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" type="number" placeholder="Start Time">
    </div>

    <div class="flex items-center justify-between">
          <input type="submit" value="Send" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" @click="sendMessage">
    </div>
  </form>
  </div>
  <div class="text-center mt-60">
    <h1 class="text-7xl">{{ this.received }}</h1>
  </div>
</div>
</template>

<script>


export default {
  name: 'App',
  data() {
    return {
      message: "",
      socket: null,
      received: "",
      hours: null,
      minutes: null,
      seconds:null
    }
  },
  mounted() {
    this.socket = new WebSocket("ws://localhost:9100/socket") 
    this.socket.onmessage = (msg) => {

      let hours = Math.floor(msg.data / 3600) 
      let minutes = Math.floor(msg.data / 60)
      let seconds = msg.data % 60


      if(minutes < 10)
      {
        minutes = "0" + minutes
      }

      if(minutes == 60)
      {
        minutes = "00"
      }
      
      if(seconds < 10) {
        seconds = "0" + seconds
      }

      if(seconds == 0) {
        seconds = "00"
      }
      this.received = "0" + hours + ":" + minutes + ":" + seconds

      if(this.received == "00:00:00")
      {
        alert('times up!')
        this.socket = null
      }
    }
  },

As i said before, this works perfectly on only 1 client. But if I connect another client to localhost:8080 which is the server ran up by npm run serve, the original client stops counting and the new client takes over the counting. How do I handle multiple clients?

0 Answers
Related