1
0
mirror of https://github.com/rancher/norman.git synced 2025-07-14 23:55:31 +00:00

Cleanup channels

This commit is contained in:
Darren Shepherd 2018-01-16 21:46:20 -07:00
parent 67264fa498
commit 6f8ed342d9
4 changed files with 56 additions and 47 deletions

View File

@ -33,26 +33,7 @@ func Handler(apiContext *types.APIContext) error {
return err return err
} }
func handler(apiContext *types.APIContext) error { func getMatchingSchemas(apiContext *types.APIContext) []*types.Schema {
c, err := upgrader.Upgrade(apiContext.Response, apiContext.Request, nil)
if err != nil {
return err
}
defer c.Close()
cancelCtx, cancel := context.WithCancel(apiContext.Request.Context())
apiContext.Request = apiContext.Request.WithContext(cancelCtx)
go func() {
for {
if _, _, err := c.NextReader(); err != nil {
cancel()
c.Close()
break
}
}
}()
apiVersions := apiContext.Request.URL.Query()["apiVersions"] apiVersions := apiContext.Request.URL.Query()["apiVersions"]
resourceTypes := apiContext.Request.URL.Query()["resourceTypes"] resourceTypes := apiContext.Request.URL.Query()["resourceTypes"]
@ -69,11 +50,35 @@ func handler(apiContext *types.APIContext) error {
} }
} }
return schemas
}
func handler(apiContext *types.APIContext) error {
schemas := getMatchingSchemas(apiContext)
if len(schemas) == 0 { if len(schemas) == 0 {
return httperror.NewAPIError(httperror.NotFound, "no resources types matched") return httperror.NewAPIError(httperror.NotFound, "no resources types matched")
} }
readerGroup, ctx := errgroup.WithContext(apiContext.Request.Context()) c, err := upgrader.Upgrade(apiContext.Response, apiContext.Request, nil)
if err != nil {
return err
}
defer c.Close()
cancelCtx, cancel := context.WithCancel(apiContext.Request.Context())
readerGroup, ctx := errgroup.WithContext(cancelCtx)
apiContext.Request = apiContext.Request.WithContext(ctx)
go func() {
for {
if _, _, err := c.NextReader(); err != nil {
cancel()
c.Close()
break
}
}
}()
events := make(chan map[string]interface{}) events := make(chan map[string]interface{})
for _, schema := range schemas { for _, schema := range schemas {
streamStore(ctx, readerGroup, apiContext, schema, events) streamStore(ctx, readerGroup, apiContext, schema, events)

View File

@ -1,6 +1,9 @@
package transform package transform
import "github.com/rancher/norman/types" import (
"github.com/rancher/norman/types"
"github.com/rancher/norman/types/convert"
)
type TransformerFunc func(apiContext *types.APIContext, data map[string]interface{}) (map[string]interface{}, error) type TransformerFunc func(apiContext *types.APIContext, data map[string]interface{}) (map[string]interface{}, error)
@ -36,18 +39,13 @@ func (t *Store) Watch(apiContext *types.APIContext, schema *types.Schema, opt *t
return t.StreamTransformer(apiContext, c) return t.StreamTransformer(apiContext, c)
} }
result := make(chan map[string]interface{}) return convert.Chan(c, func(data map[string]interface{}) map[string]interface{} {
go func() { item, err := t.Transformer(apiContext, data)
for item := range c { if err != nil {
item, err := t.Transformer(apiContext, item) return nil
if err == nil && item != nil {
result <- item
}
} }
close(result) return item
}() }), nil
return result, nil
} }
func (t *Store) List(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) ([]map[string]interface{}, error) { func (t *Store) List(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) ([]map[string]interface{}, error) {

View File

@ -3,6 +3,7 @@ package wrapper
import ( import (
"github.com/rancher/norman/httperror" "github.com/rancher/norman/httperror"
"github.com/rancher/norman/types" "github.com/rancher/norman/types"
"github.com/rancher/norman/types/convert"
) )
func Wrap(store types.Store) types.Store { func Wrap(store types.Store) types.Store {
@ -42,20 +43,11 @@ func (s *StoreWrapper) Watch(apiContext *types.APIContext, schema *types.Schema,
return nil, err return nil, err
} }
result := make(chan map[string]interface{}) return convert.Chan(c, func(data map[string]interface{}) map[string]interface{} {
go func() { return apiContext.FilterObject(&types.QueryOptions{
for item := range c { Conditions: apiContext.SubContextAttributeProvider.Query(apiContext, schema),
item = apiContext.FilterObject(&types.QueryOptions{ }, data)
Conditions: apiContext.SubContextAttributeProvider.Query(apiContext, schema), }), nil
}, item)
if item != nil {
result <- item
}
}
close(result)
}()
return result, nil
} }
func (s *StoreWrapper) Create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) { func (s *StoreWrapper) Create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) {

View File

@ -10,6 +10,20 @@ import (
"unicode" "unicode"
) )
func Chan(c <-chan map[string]interface{}, f func(map[string]interface{}) map[string]interface{}) chan map[string]interface{} {
result := make(chan map[string]interface{})
go func() {
for data := range c {
modified := f(data)
if modified != nil {
result <- modified
}
}
close(result)
}()
return result
}
func Singular(value interface{}) interface{} { func Singular(value interface{}) interface{} {
if slice, ok := value.([]string); ok { if slice, ok := value.([]string); ok {
if len(slice) == 0 { if len(slice) == 0 {