Permalink
Browse files

Use gorm instead of raw sql

  • Loading branch information...
Smotko committed Apr 25, 2015
1 parent 44fdb88 commit af24a2e2fc0121e958008fcac36b74c6257d7d81
@@ -5,7 +5,7 @@ RUN echo $GOPATH
ENV PATH=$PATH:bin/:/go/gofetch/bin
ENV GOPATH=$GOPATH:/go:/go/gofetch
RUN go get github.com/tools/godep
RUN go get github.com/mattes/migrate
RUN go get github.com/jinzhu/gorm
WORKDIR /go/gofetch/src/gofetch/
ADD . /go/gofetch
@@ -3,17 +3,33 @@ package gofetch
import (
"database/sql"
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/lib/pq"
"os"
)
func db() *sql.DB {
var db = initDb()
func initDb() Db {
d := Db{}
d.Init()
return d
}
type Db struct {
session gorm.DB
}
func (db *Db) Init() {
dbinfo := fmt.Sprintf("postgres://postgres:%s@%s:%s?sslmode=disable",
os.Getenv("DB_ENV_POSTGRES_PASSWORD"),
os.Getenv("DB_PORT_5432_TCP_ADDR"),
os.Getenv("DB_PORT_5432_TCP_PORT"))
db, err := sql.Open("postgres", dbinfo)
panicErr(err)
return db
conn, err := sql.Open("postgres", dbinfo)
panic(err)
db.session, err = gorm.Open("postgres", conn)
panic(err)
}
@@ -2,24 +2,18 @@ package gofetch
import "log"
func fatalErr(err error) {
func fatal(err error) {
if err != nil {
log.Fatal(err)
}
}
func panicErr(err error) {
func panic(err error) {
if err != nil {
log.Panic(err)
}
}
func printErr(err error) {
if err != nil {
log.Print(err)
}
}
func print(i ...interface{}) {
log.Printf("%s\n", i)
}
@@ -11,8 +11,8 @@ const (
func Fetch() string {
res, err := http.Get(URL)
panicErr(err)
panic(err)
data, err := ioutil.ReadAll(res.Body)
panicErr(err)
panic(err)
return string(data)
}
@@ -0,0 +1,69 @@
package gofetch
import (
"encoding/xml"
"github.com/jinzhu/gorm"
"time"
)
// Why I seem to need two almost identical structs:
//
// ISSUE 1: I have to use Time when unmarshaling, because time.Time
// failes to unmarshal 2015-04-24T23:02:50 with: `parsing time
// "2015-04-24T23:02:50" as "2006-01-02T15:04:05Z07:00": cannot parse
// "" as "Z07:00""`
// ISSUE 2: I have to use time.Time in the gorm struct, because I can't make
// it use Time to create & update db columns
// ISSUE 3: I have no idea how to get Rise, Set attrs without defining a Sun
// struct, this is the XML structure
// <forecast>
// <sun rise="2015-04-25T06:04:04" set="2015-04-25T20:01:20"/>
// </forecast>
type Forecast struct {
gorm.Model
LastUpdate time.Time
NextUpdate time.Time
Rise time.Time
Set time.Time
}
type ForecastXml struct {
LastUpdate Time `xml:"meta>lastupdate"`
NextUpdate Time `xml:"meta>nextupdate"`
Sun struct {
Rise Time `xml:"rise,attr"`
Set Time `xml:"set,attr"`
} `xml:"sun"`
}
// Helper function for converting ForecastXml -> Forecast
func (f *ForecastXml) ToForecast() Forecast {
fo := Forecast{}
fo.LastUpdate = f.LastUpdate.UTC()
fo.NextUpdate = f.NextUpdate.UTC()
fo.Rise = f.Sun.Rise.UTC()
fo.Set = f.Sun.Set.UTC()
return fo
}
// My Custom Time struct so that I can overwrite the default formatter
type Time struct {
time.Time
}
func (t *Time) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
// We don't really care about comments or unicorns
var v string
d.DecodeElement(&v, &start)
parse, err := time.Parse("2006-01-02T15:04:05", v)
panic(err)
*t = Time{parse}
return nil
}
func (t *Time) UnmarshalXMLAttr(attr xml.Attr) error {
parse, err := time.Parse("2006-01-02T15:04:05", attr.Value)
panic(err)
*t = Time{parse}
return nil
}

This file was deleted.

Oops, something went wrong.

This file was deleted.

Oops, something went wrong.
@@ -4,18 +4,9 @@ import (
"encoding/xml"
)
type Forecast struct {
LastUpdate string `xml:"meta>lastupdate"`
NextUpdate string `xml:"meta>nextupdate"`
Sun struct {
Rise string `xml:"rise,attr"`
Set string `xml:"set,attr"`
} `xml:"sun"`
}
func Parse(data string) Forecast {
f := Forecast{}
f := ForecastXml{}
err := xml.Unmarshal([]byte(data), &f)
panicErr(err)
return f
panic(err)
return f.ToForecast()
}
@@ -1,13 +1,18 @@
package gofetch
import (
"database/sql"
"time"
)
func Init() {
db.session.AutoMigrate(&Forecast{})
}
func Run() {
defer rerunOnPanic()
next_update := FindLatest(Parse(Fetch()))
forecast := Parse(Fetch())
db.session.FirstOrCreate(&forecast)
next_update := forecast.NextUpdate
duration := next_update.Sub(time.Now().Add(time.Hour * 2))
if duration.Minutes() < 5 {
duration = 5 * time.Minute
@@ -17,36 +22,6 @@ func Run() {
Run()
}
func insert(f Forecast) {
db := db()
defer db.Close()
str := "INSERT INTO readings (lid, last_update, next_update, sun_rise, sun_set) values ($1, $2, $3, $4, $5);"
stmt, err := db.Prepare(str)
defer stmt.Close()
panicErr(err)
_, err = stmt.Exec(1, f.LastUpdate, f.NextUpdate, f.Sun.Rise, f.Sun.Set)
panicErr(err)
print("Updated")
}
func FindLatest(f Forecast) time.Time {
db := db()
defer db.Close()
var next_update time.Time
err := db.QueryRow("SELECT next_update FROM readings WHERE last_update >= $1 ORDER BY last_update DESC LIMIT 1;", f.LastUpdate).Scan(&next_update)
if err == sql.ErrNoRows {
insert(f)
next_update, _ = time.Parse("2006-01-02T15:04:05", f.NextUpdate)
} else {
panicErr(err)
}
return next_update
}
func rerunOnPanic() {
if r := recover(); r != nil {
print("Recovering from panic, rerunning in 1 min")
@@ -5,5 +5,6 @@ import (
)
func main() {
gofetch.Init()
gofetch.Run()
}

0 comments on commit af24a2e

Please sign in to comment.