Skip to content

Instantly share code, notes, and snippets.

@esimov
Created February 2, 2016 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save esimov/93775134ce247c8ab10d to your computer and use it in GitHub Desktop.
Save esimov/93775134ce247c8ab10d to your computer and use it in GitHub Desktop.
Resource poller using goroutines
package main
import (
"fmt"
"log"
"net/http"
"time"
)
const (
statusInterval = 2 * time.Second
pollInterval = 2 * time.Second
)
var urls = []string{
"http://www.google.com",
"http://www.facebook.com",
"http://www.twitter.com",
"http://www.esimov.com",
}
type Resource struct {
url string
errorsCount int
}
type State struct {
url string
status string
}
func (r *Resource) Poll() string {
resp, err := http.Head(r.url)
if err != nil {
fmt.Println("Error...", r.url, err)
r.errorsCount++
return err.Error()
}
r.errorsCount = 0
return resp.Status
}
func Poller(in <-chan *Resource, out chan<- *Resource, status chan<- State) {
for s := range in {
state := s.Poll()
status <- State{s.url, state}
out <- s
}
}
func StateMonitor(updateInterval time.Duration) chan<- State {
ticker := time.NewTicker(updateInterval)
updates := make(chan State)
urlStatus := make(map[string]string)
go func() {
for {
select {
case <-ticker.C:
logState(urlStatus)
case s := <-updates:
urlStatus[s.status] = s.status
}
}
}()
return updates
}
func (r *Resource) Sleep(done chan<- *Resource) {
time.Sleep(pollInterval + 2*time.Second*time.Duration(r.errorsCount))
done <- r
}
func logState(s map[string]string) {
log.Println("Current State: ")
for k, v := range s {
log.Printf("%s %s", k, v)
}
}
func main() {
pending, complete := make(chan *Resource), make(chan *Resource)
// Launch the StateMonitor.
status := StateMonitor(statusInterval)
// Launch some Poller goroutines.
for i := 0; i < 2; i++ {
go Poller(pending, complete, status)
}
// Send some Resources to the pending queue.
go func() {
for _, url := range urls {
pending <- &Resource{url: url}
}
}()
for r := range complete {
go r.Sleep(pending)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment