From ed77c6c17b88c15c0850b24236cac846b9179c26 Mon Sep 17 00:00:00 2001 From: Benjamin Manns Date: Thu, 22 May 2014 11:59:11 -0700 Subject: [PATCH] Add -use-number flag that enables json.UseNumber(). Add deprecation warnings. --- README.md | 12 ++++++++++-- doc.go | 12 ++++++++++-- flags.go | 19 +++++++++++++++++++ poller.go | 8 +++++++- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fedfc07..a7c8ec3 100644 --- a/README.md +++ b/README.md @@ -94,18 +94,26 @@ goworker worker functions receive the queue they are serving and a slice of inte ```go // Expecting (int, string, float64) func myFunc(queue, args ...interface{}) error { - id, ok := args[0].(int) + idNum, ok := args[0].(json.Number) if !ok { return errorInvalidParam } + id, err := idNum.Int64() + if err != nil { + return errorInvalidParam + } name, ok := args[1].(string) if !ok { return errorInvalidParam } - weight, ok := args[2].(float64) + weightNum, ok := args[2].(json.Number) if !ok { return errorInvalidParam } + weight, err := weightNum.Float64() + if err != nil { + return errorInvalidParam + } doSomething(id, name, weight) return nil } diff --git a/doc.go b/doc.go index 8236371..e658800 100644 --- a/doc.go +++ b/doc.go @@ -76,18 +76,26 @@ // // // Expecting (int, string, float64) // func myFunc(queue, args ...interface{}) error { -// id, ok := args[0].(int) +// idNum, ok := args[0].(json.Number) // if !ok { // return errorInvalidParam // } +// id, err := idNum.Int64() +// if err != nil { +// return errorInvalidParam +// } // name, ok := args[1].(string) // if !ok { // return errorInvalidParam // } -// weight, ok := args[2].(float64) +// weightNum, ok := args[2].(json.Number) // if !ok { // return errorInvalidParam // } +// weight, err := weightNum.Float64() +// if err != nil { +// return errorInvalidParam +// } // doSomething(id, name, weight) // return nil // } diff --git a/flags.go b/flags.go index 9e554b6..0c77bf8 100644 --- a/flags.go +++ b/flags.go @@ -69,6 +69,14 @@ // with the time command to benchmark different // configurations. // +// -use-number=false +// — Uses json.Number when decoding numbers in the +// job payloads. This will avoid issues that +// occur when goworker and the json package decode +// large numbers as floats, which then get +// encoded in scientific notation, losing +// pecision. This will default to true soon. +// // You can also configure your own flags for use // within your workers. Be sure to set them // before calling goworker.Main(). It is okay to @@ -94,6 +102,7 @@ var ( namespace string exitOnComplete bool isStrict bool + useNumber bool ) // Namespace returns the namespace flag for goworker. You @@ -127,6 +136,8 @@ func init() { flag.StringVar(&namespace, "namespace", "resque:", "the Redis namespace") flag.BoolVar(&exitOnComplete, "exit-on-complete", false, "exit when the queue is empty") + + flag.BoolVar(&useNumber, "use-number", false, "use json.Number instead of float64 when decoding numbers in JSON. will default to true soon") } func flags() error { @@ -140,5 +151,13 @@ func flags() error { return err } isStrict = strings.IndexRune(queuesString, '=') == -1 + + if !useNumber { + logger.Warn("== DEPRECATION WARNING ==") + logger.Warn(" Currently, encoding/json decodes numbers as float64.") + logger.Warn(" This can cause numbers to lose precision as they are read from the Resque queue.") + logger.Warn(" Set the -use-numbers flag to use json.Number when decoding numbers and remove this warning.") + } + return nil } diff --git a/poller.go b/poller.go index 840ecde..635c955 100644 --- a/poller.go +++ b/poller.go @@ -1,6 +1,7 @@ package goworker import ( + "bytes" "encoding/json" "fmt" "time" @@ -35,7 +36,12 @@ func (p *poller) getJob(conn *RedisConn) (*job, error) { job := &job{Queue: queue} - if err := json.Unmarshal(reply.([]byte), &job.Payload); err != nil { + decoder := json.NewDecoder(bytes.NewReader(reply.([]byte))) + if useNumber { + decoder.UseNumber() + } + + if err := decoder.Decode(&job.Payload); err != nil { return nil, err } return job, nil