Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "bufio"
- "encoding/csv"
- "errors"
- "fmt"
- "net/http"
- "os"
- "strconv"
- "strings"
- "sync"
- "time"
- )
- type output struct {
- url string
- statusCode int
- success bool
- }
- func main() {
- readWorkers, err := strconv.Atoi(os.Getenv("READ_WORKERS"))
- if err != nil || readWorkers == 0 {
- readWorkers = 10
- }
- writeWorkers, err := strconv.Atoi(os.Getenv("WRITE_WORKERS"))
- if err != nil || writeWorkers == 0 {
- writeWorkers = 10
- }
- t := time.Now()
- file, err := os.Open("urls20.txt")
- if err != nil {
- println(err)
- }
- defer file.Close()
- scanner := bufio.NewScanner(file)
- maxBufferSize := 1024 * 20
- buf := make([]byte, 0, maxBufferSize)
- scanner.Buffer(buf, 10*1024)
- resultsFile, err := os.OpenFile("results.csv", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
- if err != nil {
- panic(fmt.Sprintf("Cannot open/create file. Error: %s", err))
- }
- defer resultsFile.Close()
- writer := csv.NewWriter(resultsFile)
- defer writer.Flush()
- urls := make(chan string)
- results := make(chan output)
- client := http.Client{
- Timeout: time.Second * 10,
- }
- var mu sync.Mutex
- wg1 := sync.WaitGroup{}
- wg2 := sync.WaitGroup{}
- go func() {
- for scanner.Scan() {
- urls <- strings.TrimSpace(scanner.Text())
- }
- close(urls)
- }()
- for i := 0; i < readWorkers; i++ {
- wg1.Add(1)
- go func() {
- defer wg1.Done()
- count := 0
- for url := range urls {
- count++
- results <- calculateResult(url, client)
- }
- }()
- }
- for i := 0; i < writeWorkers; i++ {
- wg2.Add(1)
- go func() {
- defer wg2.Done()
- count := 0
- for result := range results {
- count++
- err = writeResultToCsv(result, writer, mu)
- if err != nil {
- fmt.Println(fmt.Sprintf("Error while writing url %s with message '%s'. Putting back to queue", result.url, err))
- results <- result
- }
- }
- }()
- }
- wg1.Wait()
- close(results)
- wg2.Wait()
- elapsed := time.Since(t)
- fmt.Println("Finished in", elapsed)
- }
- func writeResultToCsv(result output, writer *csv.Writer, mu sync.Mutex) error {
- mu.Lock()
- defer mu.Unlock()
- var b string
- if result.success {
- b = "true"
- } else {
- b = "false"
- }
- var data = [][]string{{result.url, fmt.Sprintf("%d", result.statusCode), b}}
- err := writer.WriteAll(data)
- if err != nil {
- return errors.New(fmt.Sprintf("Cannot write results for url %s, message: %s", result.url, err))
- }
- writer.Flush()
- return nil
- }
- func calculateResult(url string, client http.Client) output {
- var result output
- req, err := http.NewRequest("HEAD", url, nil)
- if err != nil {
- panic(fmt.Sprintf("Preparing request failed. Error: %s", err))
- }
- resp, err := client.Do(req)
- if err != nil {
- result.success = false
- result.statusCode = -1
- result.url = url
- return result
- }
- if resp.StatusCode < 300 && resp.StatusCode > 199 {
- result.success = true
- } else {
- result.success = false
- }
- result.statusCode = resp.StatusCode
- result.url = url
- return result
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement