barrier pattern in the book added

This commit is contained in:
Jian Han 2018-01-08 22:30:16 +10:00
parent f887bcedec
commit 0a1036f2c6
5 changed files with 191 additions and 7 deletions

View File

@ -3,7 +3,6 @@ package ch1
import ( import (
"fmt" "fmt"
"strings" "strings"
"sync"
) )
var initialString string var initialString string
@ -11,8 +10,7 @@ var initialBytes []byte
var stringLength int var stringLength int
var finalString string var finalString string
var lettersProcessed int var lettersProcessed int
var applicationStatus bool var applicationStatusL bool
var wg sync.WaitGroup
func getLetters(gQ chan string) { func getLetters(gQ chan string) {
for i := range initialBytes { for i := range initialBytes {
@ -22,7 +20,7 @@ func getLetters(gQ chan string) {
func capitalizeLetters(gQ chan string, sQ chan string) { func capitalizeLetters(gQ chan string, sQ chan string) {
for { for {
if lettersProcessed >= stringLength { if lettersProcessed >= stringLength {
applicationStatus = false applicationStatusL = false
break break
} }
select { select {
@ -34,7 +32,7 @@ func capitalizeLetters(gQ chan string, sQ chan string) {
} }
} }
func RunLetter() { func RunLetter() {
applicationStatus = true applicationStatusL = true
getQueue := make(chan string) getQueue := make(chan string)
stackQueue := make(chan string) stackQueue := make(chan string)
initialString = `Four score and seven years ago our fathers initialString = `Four score and seven years ago our fathers
@ -50,7 +48,7 @@ created equal.`
close(getQueue) close(getQueue)
close(stackQueue) close(stackQueue)
for { for {
if applicationStatus == false { if applicationStatusL == false {
fmt.Println("Done") fmt.Println("Done")
fmt.Println(finalString) fmt.Println(finalString)
break break

View File

@ -0,0 +1,101 @@
package ch1
import (
"fmt"
"io/ioutil"
"net/http"
"sync"
"time"
)
var applicationStatus bool
var urls []string
var urlsProcessed int
var foundUrls []string
var fullText string
var totalURLCount int
var wg sync.WaitGroup
var v1 int
func readURLs(statusChannel chan int, textChannel chan string) {
time.Sleep(time.Millisecond * 1)
fmt.Println("Grabbing", len(urls), "urls")
for i := 0; i < totalURLCount; i++ {
fmt.Println("Url", i, urls[i])
resp, _ := http.Get(urls[i])
text, err := ioutil.ReadAll(resp.Body)
textChannel <- string(text)
if err != nil {
fmt.Println("No HTML body")
}
statusChannel <- 0
}
}
func addToScrapedText(textChannel chan string, processChannel chan bool) {
for {
select {
case pC := <-processChannel:
if pC == true {
// hang on
}
if pC == false {
close(textChannel)
close(processChannel)
}
case tC := <-textChannel:
fullText += tC
}
}
}
func evaluateStatus(statusChannel chan int, textChannel chan string, processChannel chan bool) {
for {
select {
case status := <-statusChannel:
fmt.Print(urlsProcessed, totalURLCount)
urlsProcessed++
if status == 0 {
fmt.Println("Got url")
}
if status == 1 {
close(statusChannel)
}
if urlsProcessed == totalURLCount {
fmt.Println("Read all top-level URLs")
processChannel <- false
applicationStatus = false
}
}
}
}
func RunSpider() {
applicationStatus = true
statusChannel := make(chan int)
textChannel := make(chan string)
processChannel := make(chan bool)
totalURLCount = 0
urls = append(urls, "http://www.mastergoco.com/index1.html")
urls = append(urls, "http://www.mastergoco.com/index2.html")
urls = append(urls, "http://www.mastergoco.com/index3.html")
urls = append(urls, "http://www.mastergoco.com/index4.html")
urls = append(urls, "http://www.mastergoco.com/index5.html")
fmt.Println("Starting spider")
urlsProcessed = 0
totalURLCount = len(urls)
go evaluateStatus(statusChannel, textChannel, processChannel)
go readURLs(statusChannel, textChannel)
go addToScrapedText(textChannel, processChannel)
for {
if applicationStatus == false {
fmt.Println(fullText)
fmt.Println("Done!")
break
}
select {
case sC := <-statusChannel:
fmt.Println("Message on StatusChannel", sC)
}
}
}

View File

@ -4,5 +4,6 @@ import "github.com/jianhan/go-patterns/concurrency/mastering_concurrency_in_go/c
func main() { func main() {
// ch1.Run() // ch1.Run()
ch1.RunLetter() // ch1.RunLetter()
ch1.RunSpider()
} }

View File

@ -0,0 +1,69 @@
package main
import (
"fmt"
"io/ioutil"
"net/http"
"time"
)
func main() {
barrier("http://httpbin.org/headers", "http://httpbin.org/User-Agen")
}
var timeoutMilliseconds int = 5000
type barrierResp struct {
Err error
Resp string
}
func barrier(endpoints ...string) {
requestNumber := len(endpoints)
in := make(chan barrierResp, requestNumber)
defer close(in)
responses := make([]barrierResp, requestNumber)
for _, endpoint := range endpoints {
go makeRequest(in, endpoint)
}
var hasError bool
for i := 0; i < requestNumber; i++ {
resp := <-in
if resp.Err != nil {
fmt.Println("ERROR: ", resp.Err)
hasError = true
break
}
responses[i] = resp
}
if !hasError {
for _, resp := range responses {
fmt.Println(resp.Resp)
}
}
}
func makeRequest(out chan<- barrierResp, url string) {
res := barrierResp{}
client := http.Client{
Timeout: time.Duration(time.Duration(timeoutMilliseconds) * time.Millisecond),
}
resp, err := client.Get(url)
if err != nil {
res.Err = err
out <- res
return
}
byt, err := ioutil.ReadAll(resp.Body)
if err != nil {
res.Err = err
out <- res
return
}
res.Resp = string(byt)
out <- res
}

View File

@ -0,0 +1,15 @@
package main
import "testing"
func TestBarrier(t *testing.T) {
t.Run("Correct endpoints", func(t *testing.T) {
endpoints := []string{"http://httpbin.org/headers", "http://httpbin.org/User-Agent"}
})
t.Run("One endpoint incorrect", func(t *testing.T) {
endpoints := []string{"http://malformed-url", "http://httpbin.org/User-Agent"}
})
t.Run("Very Short Timeout", func(t *testing.T) {
endpoints := []string{"http://httpbin.org/headers", "http://httpbin.org/User-Agent"}
})
}