Beginning of better error handling.

This commit is contained in:
Cody Soyland 2014-04-08 16:17:38 -05:00
parent fcb287103b
commit 483f4d22ca
6 changed files with 60 additions and 30 deletions

View file

@ -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)
}

View file

@ -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
}
}

View file

@ -25,5 +25,5 @@ type Executorer interface {
Close()
Run()
NewJob(*db.Message)
RunPQL(string, string) interface{}
RunPQL(string, string) (interface{}, error)
}

View file

@ -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)
})
}

View file

@ -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()

View file

@ -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 {