diff --git a/main.go b/main.go
index ae30620..0a97761 100644
--- a/main.go
+++ b/main.go
@@ -273,6 +273,8 @@ func main() {
signal := NewSignal(nil, "abort")
signal.description = event_manager.root_event.ID()
SendUpdate(event_manager.root_event, signal)
+ time.Sleep(time.Second * 5)
+ pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
break
case update := <- arena_1_client.update:
arena_1_client.process_update(update)
@@ -287,10 +289,9 @@ func main() {
arena_2_client.games_done == 12 &&
arena_3_client.games_done == 12 &&
arena_4_client.games_done == 12 {
- signal := NewSignal(nil, "cancel")
- signal.description = event_manager.root_event.ID()
- SendUpdate(event_manager.root_event, signal)
- break
+ //signal := NewSignal(nil, "cancel")
+ //signal.description = event_manager.root_event.ID()
+ //SendUpdate(event_manager.root_event, signal)
}
}
}()
diff --git a/manager.go b/manager.go
index 4c7c82c..43c9225 100644
--- a/manager.go
+++ b/manager.go
@@ -3,11 +3,6 @@ package main
import (
"fmt"
"errors"
-
- "io"
- "net/http"
- "github.com/graphql-go/graphql"
- "github.com/graphql-go/handler"
)
type EventManager struct {
@@ -16,106 +11,6 @@ type EventManager struct {
aborts []chan error
}
-const graphiql_string string = `
-
-
-
-
- GraphiQL
-
-
-
-
-
-
-
-
-
-
-
- Loading...
-
-
-
-
-`
-
-func (manager * EventManager) GQL() error {
- fields := graphql.Fields{
- "hello": &graphql.Field{
- Type: graphql.String,
- Resolve: func(p graphql.ResolveParams)(interface{}, error) {
- return "world", nil
- },
- },
- }
- rootQuery := graphql.ObjectConfig{Name: "RootQuery", Fields: fields}
- schemaConfig := graphql.SchemaConfig{Query: graphql.NewObject(rootQuery)}
- schema, err := graphql.NewSchema(schemaConfig)
- if err != nil {
- return err
- }
-
- h := handler.New(&handler.Config{Schema: &schema, Pretty: true})
- mux := http.NewServeMux()
- mux.Handle("/gql", h)
- mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
- w.WriteHeader(http.StatusOK)
- io.WriteString(w, graphiql_string)
- })
-
- http.ListenAndServe(":8080", mux)
-
- return nil
-}
-
// root_event's requirements must be in dag_nodes, and dag_nodes must be ordered by dependency(children first)
func NewEventManager(root_event Event, dag_nodes []Resource) * EventManager {
diff --git a/resource.go b/resource.go
index 27b501c..0e3e4ad 100644
--- a/resource.go
+++ b/resource.go
@@ -2,8 +2,14 @@ package main
import (
"fmt"
+ "reflect"
"errors"
"sync"
+ "net/http"
+ "io"
+ "github.com/graphql-go/graphql"
+ "github.com/graphql-go/handler"
+ "context"
)
// Resources propagate update up to multiple parents, and not downwards
@@ -254,6 +260,76 @@ func NewResource(name string, description string, children []Resource) * BaseRes
return &resource
}
+const graphiql_string string = `
+
+
+
+
+ GraphiQL
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
+
+`
+
type GQLServer struct {
BaseResource
abort chan error
@@ -277,18 +353,163 @@ func (server * GQLServer) update(signal GraphSignal) {
server.BaseResource.update(signal)
}
+func GQLEventID(p graphql.ResolveParams) (interface{}, error) {
+ if event, ok := p.Source.(Event); ok {
+ return event.ID(), nil
+ }
+ return nil, errors.New("Failed to cast source to event")
+}
+
+func GQLEventChildren(p graphql.ResolveParams) (interface{}, error) {
+ if event, ok := p.Source.(Event); ok {
+ return event.Children(), nil
+ }
+ return nil, errors.New("Failed to cast source to event")
+}
+
+func (server * GQLServer) Schema() * graphql.Schema {
+ valid_events := map[reflect.Type]*graphql.Object{}
+ gql_interface_event := graphql.NewInterface(graphql.InterfaceConfig{
+ Name: "Event",
+ Fields: graphql.Fields{},
+ ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
+ for key, value := range(valid_events) {
+ if reflect.TypeOf(p.Value) == key {
+ return value
+ }
+ }
+ return nil
+ },
+ })
+ gql_type_event_list := graphql.NewList(gql_interface_event)
+ gql_interface_event.AddFieldConfig("ID", &graphql.Field{
+ Type: graphql.String,
+ })
+ gql_interface_event.AddFieldConfig("Children", &graphql.Field{
+ Type: gql_type_event_list,
+ })
+
+ gql_type_base_event := graphql.NewObject(graphql.ObjectConfig{
+ Name: "BaseEvent",
+ Interfaces: []*graphql.Interface{
+ gql_interface_event,
+ },
+ IsTypeOf: func(p graphql.IsTypeOfParams) bool {
+ _, ok := p.Value.(*BaseEvent)
+ return ok
+ },
+ Fields: graphql.Fields{},
+ })
+ valid_events[reflect.TypeOf((*BaseEvent)(nil))] = gql_type_base_event
+ gql_type_base_event.AddFieldConfig("ID", &graphql.Field{
+ Type: graphql.String,
+ Resolve: func(p graphql.ResolveParams) (interface{}, error) {
+ if event, ok := p.Source.(Event); ok {
+ return event.ID(), nil
+ }
+ return nil, errors.New("Failed to cast source to event")
+ },
+ })
+ gql_type_base_event.AddFieldConfig("Children", &graphql.Field{
+ Type: gql_type_event_list,
+ Resolve: func(p graphql.ResolveParams) (interface{}, error) {
+ if event, ok := p.Source.(Event); ok {
+ return event.Children(), nil
+ }
+ return nil, errors.New("Failed to cast source to event")
+ },
+ })
+
+ gql_type_event_queue := graphql.NewObject(graphql.ObjectConfig{
+ Name: "EventQueue",
+ Interfaces: []*graphql.Interface{
+ gql_interface_event,
+ },
+ IsTypeOf: func(p graphql.IsTypeOfParams) bool {
+ _, ok := p.Value.(*EventQueue)
+ return ok
+ },
+ Fields: graphql.Fields{},
+ })
+ valid_events[reflect.TypeOf((*EventQueue)(nil))] = gql_type_event_queue
+ gql_type_event_queue.AddFieldConfig("ID", &graphql.Field{
+ Type: graphql.String,
+ Resolve: GQLEventID,
+ })
+ gql_type_event_queue.AddFieldConfig("Children", &graphql.Field{
+ Type: gql_type_event_list,
+ Resolve: GQLEventChildren,
+ })
+
+ schemaConfig := graphql.SchemaConfig{
+ Types: []graphql.Type{gql_type_base_event, gql_type_event_queue},
+ Query: graphql.NewObject(graphql.ObjectConfig{
+ Name: "Query",
+ Fields: graphql.Fields{
+ "Event": &graphql.Field{
+ Type: gql_interface_event,
+ Resolve: func(p graphql.ResolveParams) (interface{}, error) {
+ server.lock_holder_lock.Lock()
+ defer server.lock_holder_lock.Unlock()
+
+ owner := server.Owner()
+
+ return owner, nil
+ },
+ },
+ },
+ }),
+ }
+
+ schema, err := graphql.NewSchema(schemaConfig)
+ if err != nil{
+ panic(err)
+ }
+
+ return &schema
+}
+
func (server * GQLServer) Init(abort chan error) bool {
go func(abort chan error) {
log.Logf("gql", "GOROUTINE_START for %s", server.ID())
+ h := handler.New(&handler.Config{Schema: server.Schema(), Pretty: true})
+
+ mux := http.NewServeMux()
+ mux.Handle("/gql", h)
+ mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ w.WriteHeader(http.StatusOK)
+ io.WriteString(w, graphiql_string)
+ })
+
+ srv := &http.Server{
+ Addr: server.listen,
+ Handler: mux,
+ }
+
+ http_done := &sync.WaitGroup{}
+ http_done.Add(1)
+ go func(srv *http.Server, http_done *sync.WaitGroup) {
+ defer http_done.Done()
+ err := srv.ListenAndServe()
+ if err != http.ErrServerClosed {
+ panic(fmt.Sprintf("Failed to start gql server: %s", err))
+ }
+ }(srv, http_done)
+
for true {
select {
case <-abort:
log.Logf("gql", "GOROUTINE_ABORT for %s", server.ID())
+ err := srv.Shutdown(context.Background())
+ if err != nil{
+ panic(fmt.Sprintf("Failed to shutdown gql server: %s", err))
+ }
+ http_done.Wait()
break
- case <-server.signal:
+ case signal:=<-server.signal:
+ log.Logf("gql", "GOROUTINE_SIGNAL fot %s: %+v", server.ID(), signal)
// Take signals to resource and send to GQL subscriptions
- case <-server.gql_channel:
- // Parse GQL query from channel and reply with resolved query
}
}
}(abort)