Skip to content

Commit 20dda87

Browse files
committed
Introduce worker pool
Also simplify/refactor some code
1 parent 9838062 commit 20dda87

File tree

1 file changed

+49
-39
lines changed

1 file changed

+49
-39
lines changed

internal/unsavory/unsavory.go

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ import (
77
"fmt"
88
"log"
99
"net/http"
10+
"net/url"
1011
"strings"
1112
"time"
1213
)
1314

1415
const (
15-
baseURL = "https://api.pinboard.in/v1"
16-
userAgent = "UnsavoryNG"
16+
baseURL = "https://api.pinboard.in/v1"
17+
userAgent = "UnsavoryNG"
18+
workerCount = 50
1719
)
1820

1921
// Client bundles all values necessary for API requests.
@@ -25,16 +27,10 @@ type Client struct {
2527
Token string
2628
}
2729

28-
type checkResponse struct {
29-
URL string
30-
Status string
31-
StatusCode int
32-
}
33-
3430
// NewClient returns a configured unsavory.Client.
3531
func NewClient(token string, dryRun bool) *Client {
3632
client := &http.Client{
37-
Timeout: time.Second * 10,
33+
Timeout: time.Second * 5,
3834
}
3935

4036
return &Client{
@@ -44,38 +40,20 @@ func NewClient(token string, dryRun bool) *Client {
4440
client: client}
4541
}
4642

47-
// Run fetches all URLs, checks them individually and removes saved links return
48-
// a 404 status code.
43+
// Run fetches all URLs and kicks of the check process.
4944
func (c *Client) Run() {
5045
if c.DryRun {
5146
log.Printf("You are using dry run mode. No links will be deleted!\n\n")
5247
}
5348

5449
log.Println("Retrieving URLs")
55-
urls := c.getAllURLs()
56-
log.Printf("Retrieved %d URLS\n", len(urls))
57-
58-
results := make(chan checkResponse)
59-
for _, url := range urls {
60-
go c.checkURL(url, results)
61-
}
50+
urls := c.getURLs()
6251

63-
var result checkResponse
64-
for range urls {
65-
result = <-results
66-
switch result.StatusCode {
67-
case 200:
68-
continue
69-
case 404:
70-
log.Printf("Deleting %s\n", result.URL)
71-
c.deleteURL(result.URL)
72-
default:
73-
log.Printf("%s:%s\n", result.Status, result.URL)
74-
}
75-
}
52+
log.Printf("Retrieved %d URLS\n", len(urls))
53+
c.checkURLs(urls)
7654
}
7755

78-
func (c *Client) getAllURLs() []string {
56+
func (c *Client) getURLs() []string {
7957
var posts []struct {
8058
URL string `json:"href"`
8159
}
@@ -89,21 +67,53 @@ func (c *Client) getAllURLs() []string {
8967

9068
json.NewDecoder(resp.Body).Decode(&posts)
9169

92-
urls := make([]string, len(posts))
70+
count := len(posts)
71+
urls := make([]string, count)
9372

9473
for i, post := range posts {
9574
urls[i] = post.URL
9675
}
9776
return urls
9877
}
9978

100-
func (c *Client) checkURL(url string, results chan<- checkResponse) {
101-
resp, err := c.client.Head(url)
102-
if err != nil {
103-
results <- checkResponse{url, err.Error(), 0}
104-
return
79+
func (c *Client) checkURLs(urls []string) {
80+
ch := make(chan string)
81+
82+
for i := 0; i < workerCount; i++ {
83+
go c.checkURL(ch)
84+
}
85+
86+
for _, url := range urls {
87+
ch <- url
88+
}
89+
close(ch)
90+
}
91+
92+
func (c *Client) checkURL(urls chan string) {
93+
for {
94+
u, ok := <-urls
95+
if !ok {
96+
return
97+
}
98+
99+
resp, err := c.client.Head(u)
100+
if err != nil {
101+
if _, ok := err.(*url.Error); ok {
102+
log.Printf("Deleting (no such host): %s\n", u)
103+
c.deleteURL(u)
104+
}
105+
} else {
106+
switch resp.StatusCode {
107+
case http.StatusOK:
108+
continue
109+
case http.StatusNotFound, http.StatusGone:
110+
log.Printf("Deleting (404): %s\n", u)
111+
c.deleteURL(u)
112+
default:
113+
log.Printf("%d: %s\n", resp.StatusCode, u)
114+
}
115+
}
105116
}
106-
results <- checkResponse{url, resp.Status, resp.StatusCode}
107117
}
108118

109119
func (c *Client) deleteURL(url string) {

0 commit comments

Comments
 (0)