Graceful panic/recover for market data errors

master
Michael Dvorkin 11 years ago
parent 391520c95a
commit 7accc918cb
  1. 10
      layout.go
  2. 36
      yahoo_market.go

@ -48,7 +48,11 @@ func (self *Layout) Initialize() *Layout {
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func (self *Layout) Market(m *Market) string { func (self *Layout) Market(market *Market) string {
if ok, err := market.Ok(); !ok {
return err
}
markup := `{{.Dow.name}}: {{.Dow.change}} ({{.Dow.percent}}) at {{.Dow.latest}}, {{.Sp500.name}}: {{.Sp500.change}} ({{.Sp500.percent}}) at {{.Sp500.latest}}, {{.Nasdaq.name}}: {{.Nasdaq.change}} ({{.Nasdaq.percent}}) at {{.Nasdaq.latest}} markup := `{{.Dow.name}}: {{.Dow.change}} ({{.Dow.percent}}) at {{.Dow.latest}}, {{.Sp500.name}}: {{.Sp500.change}} ({{.Sp500.percent}}) at {{.Sp500.latest}}, {{.Nasdaq.name}}: {{.Nasdaq.change}} ({{.Nasdaq.percent}}) at {{.Nasdaq.latest}}
{{.Advances.name}}: {{.Advances.nyse}} ({{.Advances.nysep}}) on NYSE and {{.Advances.nasdaq}} ({{.Advances.nasdaqp}}) on Nasdaq. {{.Declines.name}}: {{.Declines.nyse}} ({{.Declines.nysep}}) on NYSE and {{.Declines.nasdaq}} ({{.Declines.nasdaqp}}) on Nasdaq {{if .IsClosed}}<right>U.S. markets closed</right>{{end}} {{.Advances.name}}: {{.Advances.nyse}} ({{.Advances.nysep}}) on NYSE and {{.Advances.nasdaq}} ({{.Advances.nasdaqp}}) on Nasdaq. {{.Declines.name}}: {{.Declines.nyse}} ({{.Declines.nysep}}) on NYSE and {{.Declines.nasdaq}} ({{.Declines.nasdaqp}}) on Nasdaq {{if .IsClosed}}<right>U.S. markets closed</right>{{end}}
New highs: {{.Highs.nyse}} on NYSE and {{.Highs.nasdaq}} on Nasdaq. New lows: {{.Lows.nyse}} on NYSE and {{.Lows.nasdaq}} on Nasdaq.` New highs: {{.Highs.nyse}} on NYSE and {{.Highs.nasdaq}} on Nasdaq. New lows: {{.Lows.nyse}} on NYSE and {{.Lows.nasdaq}} on Nasdaq.`
@ -59,8 +63,8 @@ New highs: {{.Highs.nyse}} on NYSE and {{.Highs.nasdaq}} on Nasdaq. New lows: {{
} }
buffer := new(bytes.Buffer) buffer := new(bytes.Buffer)
highlight(m.Dow, m.Sp500, m.Nasdaq) highlight(market.Dow, market.Sp500, market.Nasdaq)
if err = template.Execute(buffer, m); err != nil { if err := template.Execute(buffer, market); err != nil {
panic(err) panic(err)
} }

@ -5,6 +5,7 @@
package mop package mop
import ( import (
`fmt`
`bytes` `bytes`
`io/ioutil` `io/ioutil`
`net/http` `net/http`
@ -12,8 +13,9 @@ import (
`strings` `strings`
) )
const url = `http://finance.yahoo.com/marketupdate/overview`
type Market struct { type Market struct {
regex *regexp.Regexp
IsClosed bool IsClosed bool
Dow map[string]string Dow map[string]string
Nasdaq map[string]string Nasdaq map[string]string
@ -23,6 +25,8 @@ type Market struct {
Unchanged map[string]string Unchanged map[string]string
Highs map[string]string Highs map[string]string
Lows map[string]string Lows map[string]string
regex *regexp.Regexp
errors string
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -36,6 +40,7 @@ func (self *Market) Initialize() *Market {
self.Unchanged = make(map[string]string) self.Unchanged = make(map[string]string)
self.Highs = make(map[string]string) self.Highs = make(map[string]string)
self.Lows = make(map[string]string) self.Lows = make(map[string]string)
self.errors = ``
const any = `\s*<.+?>` const any = `\s*<.+?>`
const some = `<.+?` const some = `<.+?`
@ -61,13 +66,19 @@ func (self *Market) Initialize() *Market {
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func (self *Market) Fetch() *Market { func (self *Market) Fetch() (this *Market) {
response, err := http.Get(`http://finance.yahoo.com/marketupdate/overview`) this = self // <-- This ensures we return correct self in case of panic attack.
defer func() {
if err := recover(); err != nil {
self.errors = fmt.Sprintf("Error fetching market data...\n%s", err)
}
}()
response, err := http.Get(url)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// Fetch response and get its body.
defer response.Body.Close() defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body) body, err := ioutil.ReadAll(response.Body)
if err != nil { if err != nil {
@ -83,6 +94,11 @@ func (self *Market) Format() string {
return new(Layout).Initialize().Market(self) return new(Layout).Initialize().Market(self)
} }
//-----------------------------------------------------------------------------
func (self *Market) Ok() (bool, string) {
return self.errors == ``, self.errors
}
// private // private
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func (self *Market) check_if_market_open(body []byte) []byte { func (self *Market) check_if_market_open(body []byte) []byte {
@ -107,15 +123,9 @@ func (self *Market) trim(body []byte) []byte {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
func (self *Market) extract(snippet []byte) *Market { func (self *Market) extract(snippet []byte) *Market {
matches := self.regex.FindAllStringSubmatch(string(snippet), -1) matches := self.regex.FindAllStringSubmatch(string(snippet), -1)
if len(matches) < 1 || len(matches[0]) < 37 {
// if len(matches) > 0 { panic(`Unable to parse ` + url)
// fmt.Printf("%d matches\n", len(matches[0])) }
// for i, str := range matches[0][1:] {
// fmt.Printf("%d) [%s]\n", i, str)
// }
// } else {
// println(`No matches`)
// }
self.Dow[`name`] = matches[0][1] self.Dow[`name`] = matches[0][1]
self.Dow[`latest`] = matches[0][2] self.Dow[`latest`] = matches[0][2]

Loading…
Cancel
Save