Created
March 9, 2016 07:48
-
-
Save amimimor/0de6e1cba62fb0662a5b to your computer and use it in GitHub Desktop.
A template for an HTTP Request dispatcher and worker 'pool' (sharing channels with the Dispatcher)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
// "flag" | |
"fmt" | |
"log" | |
"net/http" | |
"os" | |
"strings" | |
) | |
const ( | |
numWorkers = 4 | |
) | |
var c = make(chan *http.Request) | |
func main() { | |
flag.Parse() | |
quit := make(chan bool) | |
go produce("", c, quit) | |
d := &Dispatcher{quit: quit} | |
d.Init() | |
d.Dispatch() | |
<-quit | |
} | |
func produce(msg string, c chan *http.Request, quit chan bool) { | |
for i := 0; i <= numWorkers; i++ { | |
c <- cPost() // Expression to be sent can be any suitable value. | |
} | |
// this is actually useless since the producer should not call the quit channel | |
// but a 'global' counter that oversees that the number of jobs the workers received had | |
// been fulfilled plus a reasonable timeout for them to fetch | |
quit <- true | |
} | |
type Worker struct { | |
workers chan chan *http.Request | |
requests chan *http.Request | |
quit chan bool | |
} | |
type Dispatcher struct { | |
workers chan chan *http.Request | |
quit chan bool | |
} | |
func (d *Dispatcher) Init() { | |
d.workers = make(chan chan *http.Request, numWorkers) | |
} | |
func (d *Dispatcher) Dispatch() { | |
for i := 0; i <= numWorkers; i++ { | |
log.Printf("Dispatcher initalizing worker %d\n", i) | |
worker := &Worker{workers: d.workers, quit: d.quit} | |
worker.Init() | |
worker.Work() | |
} | |
go d.Listen() | |
} | |
func (d *Dispatcher) Listen() { | |
for { | |
select { | |
case job := <-c: | |
go func(j *http.Request) { | |
workerChan := <-d.workers | |
workerChan <- j | |
}(job) | |
} | |
} | |
} | |
func (w *Worker) Init() { | |
w.requests = make(chan *http.Request) | |
} | |
func (w *Worker) Work() { | |
go func() { | |
for { | |
w.workers <- w.requests | |
select { | |
case <-w.requests: // todo: assign the fetched chan value | |
fmt.Println("Doing the actual I/O request") | |
case <-w.quit: | |
return | |
// when done, I'm putting my channel back to the dispatcher so she can send me more jobs | |
} | |
} | |
}() | |
} | |
func cPost() *http.Request { | |
req, err := http.NewRequest( | |
"POST", | |
`/`, | |
strings.NewReader(`{"time":1111, "msg":"aaaaaa"}`), | |
) | |
if err != nil { | |
log.Fatalf("%v", err) | |
} | |
req.Header.Set( | |
"Content-Type", | |
"application/x-www-form-urlencoded; param=value", | |
) | |
return req | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment