-
Notifications
You must be signed in to change notification settings - Fork 6
/
app.go
132 lines (110 loc) · 3 KB
/
app.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
package main
import (
"context"
"encoding/json"
"errors"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/callicoder/go-docker-compose/model"
"github.com/go-redis/redis"
"github.com/gorilla/mux"
)
func indexHandler(w http.ResponseWriter, r *http.Request) {
hostname, _ := os.Hostname()
w.Write([]byte(hostname + ": Welcome! Please hit the `/qod` API to get the quote of the day.\n"))
}
func quoteOfTheDayHandler(client *redis.Client) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
currentTime := time.Now()
date := currentTime.Format("2006-01-02")
hostname, _ := os.Hostname()
val, err := client.Get(date).Result()
if err == redis.Nil {
log.Println("Cache miss for date ", date)
quoteResp, err := getQuoteFromAPI()
if err != nil {
w.Write([]byte(hostname + ": Sorry! We could not get the Quote of the Day. Please try again.\n"))
return
}
quote := quoteResp.Contents.Quotes[0].Quote
client.Set(date, quote, 24*time.Hour)
w.Write([]byte(hostname + ": " + quote + "\n"))
} else {
log.Println("Cache Hit for date ", date)
w.Write([]byte(hostname + ": " + val + "\n"))
}
}
}
func main() {
// Create Redis Client
redisUrl := getEnv("REDIS_URL", "localhost:6379")
redisPwd := getEnv("REDIS_PASSWORD", "")
log.Printf("Connecting to Redis Url '%s'\n", redisUrl)
client := redis.NewClient(&redis.Options{
Addr: redisUrl,
Password: redisPwd,
DB: 0,
})
_, err := client.Ping().Result()
if err != nil {
log.Fatal(err)
}
// Create Server and Route Handlers
r := mux.NewRouter()
r.HandleFunc("/", indexHandler)
r.HandleFunc("/qod", quoteOfTheDayHandler(client))
srv := &http.Server{
Handler: r,
Addr: ":8080",
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
}
// Start Server
go func() {
log.Println("Starting Server")
if err := srv.ListenAndServe(); err != nil {
log.Fatal(err)
}
}()
// Graceful Shutdown
waitForShutdown(srv)
}
func waitForShutdown(srv *http.Server) {
interruptChan := make(chan os.Signal, 1)
signal.Notify(interruptChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
// Block until we receive our signal.
<-interruptChan
// Create a deadline to wait for.
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
srv.Shutdown(ctx)
log.Println("Shutting down")
os.Exit(0)
}
func getQuoteFromAPI() (*model.QuoteResponse, error) {
API_URL := "http://quotes.rest/qod.json"
resp, err := http.Get(API_URL)
if err != nil {
return nil, err
}
defer resp.Body.Close()
log.Println("Quote API Returned: ", resp.StatusCode, http.StatusText(resp.StatusCode))
if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
quoteResp := &model.QuoteResponse{}
json.NewDecoder(resp.Body).Decode(quoteResp)
return quoteResp, nil
} else {
return nil, errors.New("Could not get quote from API")
}
}
func getEnv(key, defaultValue string) string {
value := os.Getenv(key)
if value == "" {
return defaultValue
}
return value
}