Created
January 18, 2016 13:01
-
-
Save vodolaz095/5443ed253caeaa84f1ac to your computer and use it in GitHub Desktop.
Small Go Powered parser to query Yahoo api for money xchange rates and store data in redis database
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
/* | |
Test task: Small Go powered parser to query Yahoo api | |
for money xchange rates and store data | |
in local redis database. | |
Time taken ~1 hour | |
*/ | |
import ( | |
"encoding/json" | |
"fmt" | |
"io/ioutil" | |
"net/http" | |
"os" | |
"time" | |
"gopkg.in/redis.v3" | |
) | |
//API url | |
const exchangeRateURL = "https://query.yahooapis.com/v1/public/yql?q=select+*+from+yahoo.finance.xchange+where+pair+=+%22USDRUB,EURRUB%22&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=" | |
//Rate stores information about exchange rate for current object | |
type Rate struct { | |
ID string `json:"id"` | |
Name string `json:"Name"` | |
Rate string `json:"Rate"` | |
Ask string `json:"Ask"` | |
Bid string `json:"Bid"` | |
} | |
type responseQuery struct { | |
Count int `json:"count"` | |
Created time.Time `json:"created"` | |
ResultsRate responseResults `json:"results"` | |
} | |
type responseResults struct { | |
Rate []Rate `json:"rate"` | |
} | |
type response struct { | |
Query responseQuery `json:"query"` | |
} | |
//GetRates performs getting information from 3rd party api | |
func GetRates() ([]Rate, error) { | |
rP := response{} | |
client := &http.Client{} | |
req, err := http.NewRequest("GET", exchangeRateURL, nil) | |
if err != nil { | |
return nil, err | |
} | |
res, err := client.Do(req) | |
if err != nil { | |
return nil, err | |
} | |
defer res.Body.Close() | |
if res.StatusCode == 200 { | |
raw, err := ioutil.ReadAll(res.Body) | |
if err != nil { | |
return nil, err | |
} | |
err = json.Unmarshal(raw, &rP) | |
if err != nil { | |
return nil, err | |
} | |
return rP.Query.ResultsRate.Rate, err | |
} | |
return nil, fmt.Errorf("Wrong status code - %d", res.StatusCode) | |
} | |
//RedisStorage is a interface to redis database | |
type RedisStorage struct { | |
Client *redis.Client | |
} | |
//InitRedisStorage is a constructor for redis database client, loads config from OS environment values of `REDIS_HOST`,`REDIS_PORT`,`REDIS_AUTHPASS` | |
func InitRedisStorage() (RedisStorage, error) { | |
host := os.Getenv("REDIS_HOST") | |
if host == "" { | |
host = "localhost" | |
} | |
port := os.Getenv("REDIS_PORT") | |
if port == "" { | |
port = "6379" | |
} | |
auth := os.Getenv("REDIS_AUTHPASS") | |
client := redis.NewClient(&redis.Options{ | |
Addr: fmt.Sprintf("%s:%s", host, port), | |
Password: auth, | |
DB: 0, // use default DB | |
}) | |
return RedisStorage{Client: client}, nil | |
} | |
//StoreRate saves Rate's values into database | |
func (rs *RedisStorage) StoreRate(v Rate, now time.Time) error { | |
return rs.Client.HMSet( | |
v.Name, | |
"rate", v.Rate, | |
"ask", v.Ask, | |
"bid", v.Bid, | |
"timestamp", fmt.Sprintf("%d", now.UnixNano())).Err() | |
} | |
func main() { | |
now := time.Now() | |
loc, err := time.LoadLocation("Europe/Moscow") | |
if err != nil { | |
panic(err) | |
} | |
rates, err := GetRates() | |
if err != nil { | |
panic(err) | |
} | |
fmt.Printf("%s\n", now.In(loc).Format("Mon 2 January 2006 15:04:05")) | |
storage, err := InitRedisStorage() | |
for _, v := range rates { | |
fmt.Printf("%s: Rate: %s. Bid: %s. Ask: %s.\n", v.Name, v.Rate, v.Bid, v.Ask) | |
err = storage.StoreRate(v, now) | |
if err != nil { | |
panic(err) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment