-
Notifications
You must be signed in to change notification settings - Fork 3
/
search.go
86 lines (70 loc) · 1.7 KB
/
search.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package pitchfork
import (
"encoding/json"
"errors"
"time"
)
type PfSearcherI func(ctx PfCtx, c chan PfSearchResult, search string, abort <-chan bool) (err error)
var searchers []PfSearcherI
type PfSearchResult struct {
Source string `json:"source"`
Title string `json:"title"`
Link string `json:"link"`
Summary string `json:"summary"`
}
func SearcherRegister(f PfSearcherI) {
searchers = append(searchers, f)
}
func SearchResult(c chan PfSearchResult, source string, title string, link string, summary string) {
c <- PfSearchResult{source, title, link, summary}
}
func Search(ctx PfCtx, async bool, search string) (results []PfSearchResult, te time.Duration, err error) {
if len(searchers) == 0 {
err = errors.New("No Searchers available")
return
}
/* Abort signals other goroutine that any work needs not to be completed */
abort := make(chan bool)
done := make(chan error)
result := make(chan PfSearchResult)
busy := 0
/* Start Tracking time */
t1 := TrackStart()
for s := 0; s < len(searchers); s++ {
busy++
sf := searchers[s]
go func() {
done <- sf(ctx, result, search, abort)
}()
}
for busy > 0 {
select {
case <-ctx.GetAbort():
/* Client disconnected, abort all searchers */
close(abort)
break
case err = <-done:
/* Search completed */
if err != nil {
ctx.Errf("Search failed: %s", err)
ctx.OutLn("Search failed")
}
busy--
break
case res := <-result:
if async {
jsn, e := json.Marshal(res)
if e != nil {
err = errors.New("JSON encoding failed: " + e.Error())
return
}
ctx.OutLn("%s", string(jsn))
} else {
results = append(results, res)
}
break
}
}
te = TrackTime(t1, "Search")
return
}