@@ -7,13 +7,15 @@ import (
7
7
"fmt"
8
8
"log"
9
9
"net/http"
10
+ "net/url"
10
11
"strings"
11
12
"time"
12
13
)
13
14
14
15
const (
15
- baseURL = "https://api.pinboard.in/v1"
16
- userAgent = "UnsavoryNG"
16
+ baseURL = "https://api.pinboard.in/v1"
17
+ userAgent = "UnsavoryNG"
18
+ workerCount = 50
17
19
)
18
20
19
21
// Client bundles all values necessary for API requests.
@@ -25,16 +27,10 @@ type Client struct {
25
27
Token string
26
28
}
27
29
28
- type checkResponse struct {
29
- URL string
30
- Status string
31
- StatusCode int
32
- }
33
-
34
30
// NewClient returns a configured unsavory.Client.
35
31
func NewClient (token string , dryRun bool ) * Client {
36
32
client := & http.Client {
37
- Timeout : time .Second * 10 ,
33
+ Timeout : time .Second * 5 ,
38
34
}
39
35
40
36
return & Client {
@@ -44,38 +40,20 @@ func NewClient(token string, dryRun bool) *Client {
44
40
client : client }
45
41
}
46
42
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.
49
44
func (c * Client ) Run () {
50
45
if c .DryRun {
51
46
log .Printf ("You are using dry run mode. No links will be deleted!\n \n " )
52
47
}
53
48
54
49
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 ()
62
51
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 )
76
54
}
77
55
78
- func (c * Client ) getAllURLs () []string {
56
+ func (c * Client ) getURLs () []string {
79
57
var posts []struct {
80
58
URL string `json:"href"`
81
59
}
@@ -89,21 +67,53 @@ func (c *Client) getAllURLs() []string {
89
67
90
68
json .NewDecoder (resp .Body ).Decode (& posts )
91
69
92
- urls := make ([]string , len (posts ))
70
+ count := len (posts )
71
+ urls := make ([]string , count )
93
72
94
73
for i , post := range posts {
95
74
urls [i ] = post .URL
96
75
}
97
76
return urls
98
77
}
99
78
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
+ }
105
116
}
106
- results <- checkResponse {url , resp .Status , resp .StatusCode }
107
117
}
108
118
109
119
func (c * Client ) deleteURL (url string ) {
0 commit comments