forked from GoogleCloudPlatform/golang-samples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
worker.go
134 lines (109 loc) · 3.24 KB
/
worker.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2015 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
// Sample pubsub_worker demonstrates the use of the Cloud Pub/Sub API to communicate between two modules.
// See https://cloud.google.com/go/getting-started/using-pub-sub
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"strings"
"sync"
books "google.golang.org/api/books/v1"
"cloud.google.com/go/pubsub"
"golang.org/x/net/context"
"github.com/GoogleCloudPlatform/golang-samples/getting-started/bookshelf"
)
const subName = "book-worker-sub"
var (
countMu sync.Mutex
count int
booksClient *books.Service
subscription *pubsub.Subscription
)
func main() {
ctx := context.Background()
if bookshelf.PubsubClient == nil {
log.Fatal("You must configure the Pub/Sub client in config.go before running pubsub_worker.")
}
var err error
booksClient, err = books.New(http.DefaultClient)
if err != nil {
log.Fatalf("could not access Google Books API: %v", err)
}
// ignore returned errors, which will be "already exists". If they're fatal
// errors, then following calls (e.g. in the subscribe function) will also fail.
topic, _ := bookshelf.PubsubClient.CreateTopic(ctx, bookshelf.PubsubTopicID)
subscription, _ = bookshelf.PubsubClient.CreateSubscription(ctx, subName, pubsub.SubscriptionConfig{Topic: topic})
// Start worker goroutine.
go subscribe()
// [START http]
// Publish a count of processed requests to the server homepage.
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
countMu.Lock()
defer countMu.Unlock()
fmt.Fprintf(w, "This worker has processed %d books.", count)
})
port := "8080"
if p := os.Getenv("PORT"); p != "" {
port = p
}
log.Fatal(http.ListenAndServe(":"+port, nil))
// [END http]
}
func subscribe() {
ctx := context.Background()
err := subscription.Receive(ctx, func(ctx context.Context, msg *pubsub.Message) {
var id int64
if err := json.Unmarshal(msg.Data, &id); err != nil {
log.Printf("could not decode message data: %#v", msg)
msg.Ack()
return
}
log.Printf("[ID %d] Processing.", id)
if err := update(id); err != nil {
log.Printf("[ID %d] could not update: %v", id, err)
msg.Nack()
return
}
countMu.Lock()
count++
countMu.Unlock()
msg.Ack()
log.Printf("[ID %d] ACK", id)
})
if err != nil {
log.Fatal(err)
}
}
// update retrieves the book with the given ID, finds metata from the Books
// server and updates the database with the book's details.
func update(bookID int64) error {
book, err := bookshelf.DB.GetBook(bookID)
if err != nil {
return err
}
vols, err := booksClient.Volumes.List(book.Title).Do()
if err != nil {
return err
}
if len(vols.Items) == 0 {
return nil
}
info := vols.Items[0].VolumeInfo
book.Title = info.Title
book.Author = strings.Join(info.Authors, ", ")
book.PublishedDate = info.PublishedDate
if book.Description == "" {
book.Description = info.Description
}
if book.ImageURL == "" && info.ImageLinks != nil {
url := info.ImageLinks.Thumbnail
// Replace http with https to prevent Content Security errors on the page.
book.ImageURL = strings.Replace(url, "http://", "https://", 1)
}
return bookshelf.DB.UpdateBook(book)
}