aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRagnis Armus <ragnis@aragnis.com>2018-04-14 23:14:40 +0300
committerRagnis Armus <ragnis@aragnis.com>2018-04-14 23:14:40 +0300
commit74cdb573e0c1101d48bb738aa66a52ee31309cba (patch)
tree3b4b7d4e465b1a7a4e6cc35c32192fe64f5d1a62
parenta1a9b720f1160ecd561fdccf36bad8a9accbfa83 (diff)
Pass context to searchers
-rw-r--r--search/search.go9
-rw-r--r--search/thepiratebay.go12
-rw-r--r--search/util.go35
-rw-r--r--sync.go18
4 files changed, 49 insertions, 25 deletions
diff --git a/search/search.go b/search/search.go
index 35fcca6..97a8e59 100644
--- a/search/search.go
+++ b/search/search.go
@@ -1,12 +1,13 @@
package search
import (
+ "context"
"sort"
"strings"
)
// MagnetURLFunc returns a magnet link URL
-type MagnetURLFunc func() (string, error)
+type MagnetURLFunc func(ctx context.Context) (string, error)
// Result is a single search result
type Result struct {
@@ -25,7 +26,7 @@ type ResultFilterFunc func(*Result) bool
// Searcher can search for torrents
type Searcher interface {
- Search(query string) (Results, error)
+ Search(ctx context.Context, query string) (Results, error)
}
// AggregatorError is an error during results aggregation
@@ -61,14 +62,14 @@ func (ag *Aggregator) AddSearcher(s Searcher) {
// Search performs a search using all searchers and aggregates the results
// removing any duplicates.
-func (ag Aggregator) Search(query string) (Results, error) {
+func (ag Aggregator) Search(ctx context.Context, query string) (Results, error) {
var (
ret Results
errs []error
names = make(map[string]bool)
)
for _, s := range ag.searchers {
- list, err := s.Search(query)
+ list, err := s.Search(ctx, query)
if err != nil {
errs = append(errs, err)
continue
diff --git a/search/thepiratebay.go b/search/thepiratebay.go
index f40b769..0f208e3 100644
--- a/search/thepiratebay.go
+++ b/search/thepiratebay.go
@@ -1,26 +1,20 @@
package search
import (
- "errors"
+ "context"
"fmt"
"github.com/PuerkitoBio/goquery"
- "net/http"
"net/url"
"strconv"
)
// Thepiratebay is a Searcher backed by The Pirate Bay
type Thepiratebay struct {
- HTTPClient *http.Client
}
// Search performs a search
-func (tpb *Thepiratebay) Search(query string) (results Results, err error) {
- if tpb.HTTPClient == nil {
- err = errors.New("no HTTP client")
- return
- }
- doc, err := newGoqueryDocument(tpb.HTTPClient, &url.URL{
+func (tpb *Thepiratebay) Search(ctx context.Context, query string) (results Results, err error) {
+ doc, err := newGoqueryDocument(ctx, url.URL{
Scheme: "https",
Host: "thepiratebay.org",
Path: fmt.Sprintf("/search/%s/0/7/0", query),
diff --git a/search/util.go b/search/util.go
index 7bcd011..399d01b 100644
--- a/search/util.go
+++ b/search/util.go
@@ -1,16 +1,21 @@
package search
import (
+ "context"
"fmt"
"github.com/PuerkitoBio/goquery"
"net/http"
"net/url"
)
-func newGoqueryDocument(c *http.Client, u *url.URL) (*goquery.Document, error) {
- resp, err := c.Get(u.String())
+func newGoqueryDocument(ctx context.Context, u url.URL) (*goquery.Document, error) {
+ req, err := http.NewRequest(http.MethodGet, u.String(), http.NoBody)
if err != nil {
- return nil, fmt.Errorf("http GET: %v", err)
+ return nil, fmt.Errorf("creating request: %v", err)
+ }
+ resp, err := httpDo(ctx, req)
+ if err != nil {
+ return nil, err
}
defer resp.Body.Close()
doc, err := goquery.NewDocumentFromReader(resp.Body)
@@ -21,7 +26,29 @@ func newGoqueryDocument(c *http.Client, u *url.URL) (*goquery.Document, error) {
}
func newMagnetURLFuncFromString(s string) MagnetURLFunc {
- return func() (string, error) {
+ return func(ctx context.Context) (string, error) {
return s, nil
}
}
+
+func httpDo(ctx context.Context, req *http.Request) (*http.Response, error) {
+ tr := &http.Transport{}
+ client := &http.Client{Transport: tr}
+ ch := make(chan bool, 1)
+ var (
+ resp *http.Response
+ err error
+ )
+ go func() {
+ resp, err = client.Do(req)
+ ch <- true
+ }()
+ select {
+ case <-ctx.Done():
+ tr.CancelRequest(req)
+ <-ch
+ return nil, ctx.Err()
+ case _ = <-ch:
+ return resp, err
+ }
+}
diff --git a/sync.go b/sync.go
index f3224d1..799847d 100644
--- a/sync.go
+++ b/sync.go
@@ -1,9 +1,9 @@
package main
import (
+ "context"
"flag"
"fmt"
- "net/http"
"time"
"github.com/Ragnis/autousts/search"
@@ -94,11 +94,10 @@ func cmdSync(db *DB, argv []string) int {
func syncShow(show *Show, out chan<- *search.Result, fin chan<- bool) {
aggr := &search.Aggregator{}
- aggr.AddSearcher(&search.Thepiratebay{
- HTTPClient: &http.Client{
- Timeout: 10 * time.Second,
- },
- })
+ aggr.AddSearcher(&search.Thepiratebay{})
+
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
for {
pointer, ok := show.NextPointer()
@@ -108,7 +107,7 @@ func syncShow(show *Show, out chan<- *search.Result, fin chan<- bool) {
query := fmt.Sprintf(show.Query, pointer)
- results, err := aggr.Search(query)
+ results, err := aggr.Search(ctx, query)
if err != nil {
fmt.Println("Search error: " + err.Error())
break
@@ -144,7 +143,10 @@ func containsPointer(str string, ptr Pointer) bool {
}
func addTorrentFromResult(tc *transmission.TransmissionClient, r *search.Result) error {
- magnet, err := r.MagnetURL()
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+
+ magnet, err := r.MagnetURL(ctx)
if err != nil {
return fmt.Errorf("getting magnet link: %v", err)
}