From 483f4d22ca8fe29cd8857e32c0a13526390eea8d Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Tue, 8 Apr 2014 16:17:38 -0500 Subject: [PATCH] Beginning of better error handling. --- core/http.go | 14 +++++++++++--- executor/executor.go | 32 +++++++++++++++++++++----------- interfaces/core.go | 2 +- query/parser_test.go | 5 +++++ query/planner_test.go | 12 ++++++++---- query/query.go | 25 ++++++++++++++----------- 6 files changed, 60 insertions(+), 30 deletions(-) diff --git a/core/http.go b/core/http.go index 3ed1d1b6e..ba3a8869f 100644 --- a/core/http.go +++ b/core/http.go @@ -161,12 +161,15 @@ func (self *WebService) HandleQuery(w http.ResponseWriter, r *http.Request) { return } - results := self.service.Executor.RunPQL(database_name, pql) + results, err := self.service.Executor.RunPQL(database_name, pql) + if err != nil { + http.Error(w, "Error running query: "+err.Error(), http.StatusInternalServerError) + } encoder := json.NewEncoder(w) err = encoder.Encode(results) if err != nil { - log.Fatal("Error encoding stats") + http.Error(w, "Error encoding: "+err.Error(), http.StatusInternalServerError) } } @@ -230,7 +233,12 @@ func (self *WebService) HandleSetBit(w http.ResponseWriter, r *http.Request) { filter := int(t) for bitmap_id := range bitmaps(frame, obj) { pql := fmt.Sprintf("set(%d, %s, %d, %d)", bitmap_id, frame, filter, profile_id) - results = append(results, self.service.Executor.RunPQL(db, pql)) + result, err := self.service.Executor.RunPQL(db, pql) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + results = append(results, result) // results = append(results, db+" "+pql) } diff --git a/executor/executor.go b/executor/executor.go index 7654d3196..9278299db 100644 --- a/executor/executor.go +++ b/executor/executor.go @@ -62,16 +62,19 @@ func (self *Executor) RunQueryTest(database_name string, pql string) string { return pql } -func (self *Executor) runQuery(database *db.Database, qry *query.Query) { +func (self *Executor) runQuery(database *db.Database, qry *query.Query) error { process, err := self.service.GetProcess() if err != nil { - spew.Dump(err) + return err } process_id := process.Id() fragment_id := util.SUUID(0) destination := db.Location{&process_id, fragment_id} - query_plan := query.QueryPlanForQuery(database, qry, &destination) + query_plan, err := query.QueryPlanForQuery(database, qry, &destination) + if err != nil { + return err + } // loop over the query steps and send to Transport for _, qs := range *query_plan { msg := new(db.Message) @@ -81,30 +84,34 @@ func (self *Executor) runQuery(database *db.Database, qry *query.Query) { self.service.Transport.Send(msg, step.GetLocation().ProcessId) } } + return nil } -func (self *Executor) RunPQL(database_name string, pql string) interface{} { +func (self *Executor) RunPQL(database_name string, pql string) (interface{}, error) { database := self.service.Cluster.GetOrCreateDatabase(database_name) // see if the outer query function is a custom query reserved_functions := stringSlice{"get", "set", "union", "intersect", "count", "top-n"} tokens, err := query.Lex(pql) if err != nil { - spew.Dump(err) + return nil, err } outer_token := tokens[0].Text if reserved_functions.pos(outer_token) != -1 { - qry := query.QueryForTokens(tokens) + qry, err := query.QueryForTokens(tokens) + if err != nil { + return nil, err + } go self.runQuery(database, qry) var final interface{} - final, err := self.service.Hold.Get(qry.Id, 10) + final, err = self.service.Hold.Get(qry.Id, 10) if err != nil { - spew.Dump(err) + return nil, err } - return final + return final, nil } else { plugins_dir := config.GetString("plugins") @@ -113,7 +120,10 @@ func (self *Executor) RunPQL(database_name string, pql string) interface{} { query_list := GetMacro(plugins_file, filter).(query.PqlList) for i, _ := range query_list { - qry := query.QueryForPQL(query_list[i].PQL) + qry, err := query.QueryForPQL(query_list[i].PQL) + if err != nil { + return nil, err + } go self.runQuery(database, qry) query_list[i].Id = qry.Id } @@ -128,7 +138,7 @@ func (self *Executor) RunPQL(database_name string, pql string) interface{} { final_result[query_list[i].Label] = final } - return final_result + return final_result, nil } } diff --git a/interfaces/core.go b/interfaces/core.go index 77d82aa1d..a705c4867 100644 --- a/interfaces/core.go +++ b/interfaces/core.go @@ -25,5 +25,5 @@ type Executorer interface { Close() Run() NewJob(*db.Message) - RunPQL(string, string) interface{} + RunPQL(string, string) (interface{}, error) } diff --git a/query/parser_test.go b/query/parser_test.go index d51b848fa..1801a713e 100644 --- a/query/parser_test.go +++ b/query/parser_test.go @@ -77,4 +77,9 @@ func TestQueryParser(t *testing.T) { So(query.Subqueries[0].Operation, ShouldEqual, "get") So(query.Subqueries[0].Args, ShouldResemble, map[string]interface{}{"id": uint64(10), "frame": "general"}) }) + Convey("Lists", t, func() { + tokens, err := Lex("wat(50)") + _, err = Parse(tokens) + So(err, ShouldBeNil) + }) } diff --git a/query/planner_test.go b/query/planner_test.go index e2bb09828..66503d0e1 100644 --- a/query/planner_test.go +++ b/query/planner_test.go @@ -83,7 +83,8 @@ func TestQueryPlanner(t *testing.T) { }) Convey("Get query plan - including parsing", t, func() { - query := QueryForPQL("get(10,general)") + query, err := QueryForPQL("get(10,general)") + So(err, ShouldEqual, nil) database, fragment1 := basic_database() @@ -108,7 +109,8 @@ func TestQueryPlanner(t *testing.T) { }) Convey("Union query plan - including parsing", t, func() { - query := QueryForPQL("union(get(10, general), get(20, general))") + query, err := QueryForPQL("union(get(10, general), get(20, general))") + So(err, ShouldEqual, nil) database, fragment1 := basic_database() @@ -148,7 +150,8 @@ func TestQueryPlanner(t *testing.T) { }) }) Convey("Set query plan - including parsing", t, func() { - query := QueryForPQL("set(10, general, 0, 100)") + query, err := QueryForPQL("set(10, general, 0, 100)") + So(err, ShouldEqual, nil) database, fragment1 := basic_database() @@ -163,7 +166,8 @@ func TestQueryPlanner(t *testing.T) { So(*(qp[0].(SetQueryStep).Bitmap), ShouldResemble, db.Bitmap{10, "general", 0}) }) Convey("Top-n query plan - including parsing", t, func() { - query := QueryForPQL("top-n(get(10, general), [1,2,3], 50)") + query, err := QueryForPQL("top-n(get(10, general), [1,2,3], 50)") + So(err, ShouldEqual, nil) database, fragment1 := basic_database() diff --git a/query/query.go b/query/query.go index bbe738241..a521b307c 100644 --- a/query/query.go +++ b/query/query.go @@ -28,40 +28,43 @@ type Query struct { Subqueries []Query } -func QueryPlanForPQL(database *db.Database, pql string, destination *db.Location) *QueryPlan { +func QueryPlanForPQL(database *db.Database, pql string, destination *db.Location) (*QueryPlan, error) { tokens, err := Lex(pql) if err != nil { - panic(err) + return nil, err } return QueryPlanForTokens(database, tokens, destination) } -func QueryForPQL(pql string) *Query { +func QueryForPQL(pql string) (*Query, error) { tokens, err := Lex(pql) if err != nil { - panic(err) + return nil, err } return QueryForTokens(tokens) } -func QueryForTokens(tokens []Token) *Query { +func QueryForTokens(tokens []Token) (*Query, error) { query, err := Parse(tokens) if err != nil { - panic(err) + return nil, err } - return query + return query, nil } -func QueryPlanForTokens(database *db.Database, tokens []Token, destination *db.Location) *QueryPlan { - query := QueryForTokens(tokens) +func QueryPlanForTokens(database *db.Database, tokens []Token, destination *db.Location) (*QueryPlan, error) { + query, err := QueryForTokens(tokens) + if err != nil { + return nil, err + } return QueryPlanForQuery(database, query, destination) } -func QueryPlanForQuery(database *db.Database, query *Query, destination *db.Location) *QueryPlan { +func QueryPlanForQuery(database *db.Database, query *Query, destination *db.Location) (*QueryPlan, error) { query_planner := QueryPlanner{Database: database, Query: query} id := uuid.RandomUUID() query_plan := query_planner.Plan(query, &id, destination) - return query_plan + return query_plan, nil } func TokensToString(tokens []Token) string {