Skip to content

Commit

Permalink
- refactor handler options
Browse files Browse the repository at this point in the history
- added path parameters
- remove special treating of "async" scope in session set
  • Loading branch information
adranwit committed Sep 5, 2024
1 parent 88f1afe commit 46211f2
Show file tree
Hide file tree
Showing 15 changed files with 95 additions and 41 deletions.
1 change: 1 addition & 0 deletions internal/inference/parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ func buildParameter(field *ast.Field, aTag *tags.Tag, types *xreflect.Types, emb
}
param.When = pTag.When
param.Scope = pTag.Scope
param.Cacheable = pTag.Cacheable
param.With = pTag.With
param.Async = pTag.Async
param.In = &state.Location{Name: pTag.In, Kind: state.Kind(pTag.Kind)}
Expand Down
4 changes: 4 additions & 0 deletions internal/translator/parser/declarations.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,10 @@ func (s *Declarations) parseShorthands(declaration *Declaration, cursor *parsly.
}
case "Output":
declaration.InOutput = true
case "Cacheable":
literal := strings.Trim(args[0], `"'`)
value, _ := strconv.ParseBool(literal)
declaration.Cacheable = &value
case "When":
declaration.When = strings.Trim(content, "'\"")
case "Scope":
Expand Down
30 changes: 27 additions & 3 deletions repository/contract/dispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import (
)

type (
//Path represents a path
//Options represents dispatcher options
Options struct {
Constants map[string]interface{}
Constants map[string]interface{}
PathParameters map[string]string
Form *hstate.Form
Request *http.Request
}
//Option represents a dispatcher option
Option func(o *Options)
Expand All @@ -27,7 +30,7 @@ func NewOptions(opts ...Option) *Options {
// Dispatcher represents a dispatcher
type Dispatcher interface {
//Dispatch dispatches request
Dispatch(ctx context.Context, path *Path, Request *http.Request, form *hstate.Form, options ...Option) (interface{}, error)
Dispatch(ctx context.Context, path *Path, options ...Option) (interface{}, error)
}

// WithConstants adds constants
Expand All @@ -36,3 +39,24 @@ func WithConstants(constants map[string]interface{}) Option {
o.Constants = constants
}
}

// WithPathParameters adds path parameters
func WithPathParameters(pathParameters map[string]string) Option {
return func(o *Options) {
o.PathParameters = pathParameters
}
}

// WithForm adds form
func WithForm(form *hstate.Form) Option {
return func(o *Options) {
o.Form = form
}
}

// WithRequest adds request
func WithRequest(request *http.Request) Option {
return func(o *Options) {
o.Request = request
}
}
24 changes: 13 additions & 11 deletions repository/locator/component/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ import (
)

type componentLocator struct {
custom []interface{}
dispatch contract.Dispatcher
constants map[string]interface{}
getRequest func() (*http.Request, error)
getForm func() *hstate.Form
custom []interface{}
dispatch contract.Dispatcher
constants map[string]interface{}
pathParameters map[string]string
getRequest func() (*http.Request, error)
getForm func() *hstate.Form
}

func (l *componentLocator) Names() []string {
Expand All @@ -34,7 +35,7 @@ func (l *componentLocator) Value(ctx context.Context, name string) (interface{},
return nil, false, err
}
form := l.getForm()
value, err := l.dispatch.Dispatch(ctx, &contract.Path{Method: method, URI: URI}, request, form, contract.WithConstants(l.constants))
value, err := l.dispatch.Dispatch(ctx, &contract.Path{Method: method, URI: URI}, contract.WithRequest(request), contract.WithForm(form), contract.WithConstants(l.constants), contract.WithPathParameters(l.pathParameters))
err = updateErrWithResponseStatus(err, value)
return value, err == nil, err
}
Expand Down Expand Up @@ -88,11 +89,12 @@ func newComponentLocator(opts ...locator.Option) (kind.Locator, error) {
}
dispatcher = options.Dispatcher
ret := &componentLocator{
custom: options.Custom,
dispatch: options.Dispatcher,
constants: options.Constants,
getRequest: options.GetRequest,
getForm: options.GetForm,
custom: options.Custom,
dispatch: options.Dispatcher,
constants: options.Constants,
getRequest: options.GetRequest,
getForm: options.GetForm,
pathParameters: options.PathParameters,
}
return ret, nil
}
Expand Down
18 changes: 13 additions & 5 deletions repository/locator/component/dispatcher/disptacher.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,40 @@ package dispatcher

import (
"context"
"fmt"
"github.com/viant/datly/repository"
"github.com/viant/datly/repository/contract"
"github.com/viant/datly/service/operator"
"github.com/viant/datly/service/session"
"github.com/viant/datly/view/state/kind/locator"
hstate "github.com/viant/xdatly/handler/state"
"net/http"
)

type Dispatcher struct {
registry *repository.Registry
service *operator.Service
}

func (d *Dispatcher) Dispatch(ctx context.Context, path *contract.Path, request *http.Request, form *hstate.Form, opts ...contract.Option) (interface{}, error) {
func (d *Dispatcher) Dispatch(ctx context.Context, path *contract.Path, opts ...contract.Option) (interface{}, error) {
//TODO maybe extract and pass session cache value
aComponent, err := d.registry.Lookup(ctx, path)
if err != nil {
return nil, err
}
unmarshal := aComponent.UnmarshalFunc(request)
var options = aComponent.LocatorOptions(request, form, unmarshal)
cOptions := contract.NewOptions(opts...)
request := cOptions.Request
if request == nil {
return nil, fmt.Errorf("failed to dispatch %v %v request was empty", path.Method, path.URI)
}

unmarshal := aComponent.UnmarshalFunc(request)
var options = aComponent.LocatorOptions(request, cOptions.Form, unmarshal)
if cOptions.Constants != nil {
options = append(options, locator.WithConstants(cOptions.Constants))
}
if cOptions.PathParameters != nil {
options = append(options, locator.WithPathParameters(cOptions.PathParameters))
}

aSession := session.New(aComponent.View, session.WithLocatorOptions(options...))
ctx = aSession.Context(ctx, true)
value, err := d.service.Operate(ctx, aSession, aComponent)
Expand Down
4 changes: 4 additions & 0 deletions service/executor/handler/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,12 @@ func newSqlxIterator(toExecute []interface{}) *sqlxIterator {
var items []interface{}
exec := newExecutions()
for _, item := range toExecute {

switch actual := item.(type) {
case *expand.Executable:
if actual.Executed() {
continue
}
exec.add(actual.Table, actual.Data, actual.ExecType)
continue
}
Expand Down
1 change: 0 additions & 1 deletion service/executor/handler/sqlx.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ func (s *Service) Flush(ctx context.Context, tableName string) error {
}, options...); err != nil {
return err
}

return nil
}

Expand Down
2 changes: 1 addition & 1 deletion service/executor/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func (e *Executor) execData(ctx context.Context, sess *dbSession, data interface
return nil
}

defer actual.MarkAsExecuted()
actual.MarkAsExecuted()
switch actual.ExecType {
case expand2.ExecTypeInsert:
return e.handleInsert(ctx, sess, actual, db)
Expand Down
4 changes: 2 additions & 2 deletions service/session/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ func (s *Session) SetState(ctx context.Context, parameters state.Parameters, aSt
wg := sync.WaitGroup{}
for i, _ := range group { //populate non data view parameters first
parameter := group[i]
if parameter.Scope != opts.scope && !(parameter.Scope == "async" && opts.scope == "") {
if parameter.Scope != opts.scope {
continue
}
wg.Add(1)
Expand Down Expand Up @@ -632,7 +632,7 @@ func (s *Session) LoadState(parameters state.Parameters, aState interface{}) err
inputState := sType.WithValue(aState)
ptr := xunsafe.AsPointer(aState)
for _, parameter := range parameters {
if parameter.Scope != "" || parameter.Scope == "async" {
if parameter.Scope != "" {
continue
}
selector, _ := inputState.Selector(parameter.Name)
Expand Down
23 changes: 14 additions & 9 deletions service/session/stater.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,34 @@ func (s *Session) Into(ctx context.Context, dest interface{}, opts ...hstate.Opt

hOptions := hstate.NewOptions(opts...)
aState := stateType.Type().WithValue(dest)
var stateOptions []locator.Option

var locatorsToRemove = []state.Kind{state.KindComponent}
if hOptions.Constants() != nil {
stateOptions = append(stateOptions, locator.WithConstants(hOptions.Constants()))
s.locatorOptions = append(s.locatorOptions, locator.WithConstants(hOptions.Constants()))
s.kindLocator.RemoveLocators(state.KindConst)
s.kindLocator.RemoveLocators(state.KindComponent)
locatorsToRemove = append(locatorsToRemove, state.KindConst)
}
if hOptions.Form() != nil {
stateOptions = append(stateOptions, locator.WithForm(hOptions.Form()))
s.locatorOptions = append(s.locatorOptions, locator.WithForm(hOptions.Form()))
s.kindLocator.RemoveLocators(state.KindForm)
s.kindLocator.RemoveLocators(state.KindComponent)
locatorsToRemove = append(locatorsToRemove, state.KindConst, state.KindForm, state.KindComponent)
}
if len(hOptions.PathParameters()) > 0 {
stateOptions = append(stateOptions, locator.WithPathParameters(hOptions.PathParameters()))
s.locatorOptions = append(s.locatorOptions, locator.WithPathParameters(hOptions.PathParameters()))
s.kindLocator.RemoveLocators(state.KindPath)
locatorsToRemove = append(locatorsToRemove, state.KindPath)
}
if hOptions.HttpRequest() != nil {
stateOptions = append(stateOptions, locator.WithRequest(hOptions.HttpRequest()))
s.locatorOptions = append(s.locatorOptions, locator.WithRequest(hOptions.HttpRequest()))
s.kindLocator.RemoveLocators(state.KindForm, state.KindRequest, state.KindQuery)
s.kindLocator.RemoveLocators(state.KindComponent)
locatorsToRemove = append(locatorsToRemove, state.KindForm, state.KindRequest, state.KindQuery)
}
var stateOptions []locator.Option

s.kindLocator.RemoveLocators(locatorsToRemove...)
if s.view != nil {
viewOptions := s.ViewOptions(s.view, WithLocatorOptions())
stateOptions = viewOptions.kindLocator.Options()
stateOptions = append(viewOptions.kindLocator.Options(), stateOptions...)
}
options := s.Indirect(true, stateOptions...)
options.scope = hOptions.Scope()
Expand Down
3 changes: 3 additions & 0 deletions view/state/kind/locator/locators.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ type KindLocator struct {
}

func (l *KindLocator) RemoveLocators(kind ...state.Kind) {
if len(kind) == 0 {
return
}
l.RWMutex.Lock()
defer l.RWMutex.Unlock()
for _, k := range kind {
Expand Down
6 changes: 5 additions & 1 deletion view/state/parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ type (
)

func (p *Parameter) IsAsync() bool {
return p.Async || p.Scope == "async"
return p.Async
}

func (p *Parameter) IsUsedBy(text string) bool {
Expand Down Expand Up @@ -296,6 +296,10 @@ func (p *Parameter) inherit(param *Parameter) {
if p.Handler == nil {
p.Handler = param.Handler
}
if p.Cacheable == nil {
p.Cacheable = param.Cacheable
}

}

// Validate checks if parameter is valid
Expand Down
4 changes: 2 additions & 2 deletions view/state/parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ func (p *Parameter) buildTag(fieldName string) reflect.StructTag {
In: string(p.In.Name),
When: p.When,
Async: p.Async,
Cachable: p.Cacheable,
Cacheable: p.Cacheable,
Scope: p.Scope,
With: p.With,
ErrorCode: p.ErrorStatusCode,
Expand Down Expand Up @@ -711,7 +711,7 @@ func WithParameterSchema(schema *Schema) ParameterOption {
}
}

func WithCachable(flag bool) ParameterOption {
func WithCacheable(flag bool) ParameterOption {
return func(p *Parameter) {
p.Cacheable = &flag
}
Expand Down
2 changes: 1 addition & 1 deletion view/state/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func BuildParameter(field *reflect.StructField, fs *embed.FS, lookupType xreflec
result.Scope = pTag.Scope
result.When = pTag.When
result.Async = pTag.Async
result.Cacheable = pTag.Cachable
result.Cacheable = pTag.Cacheable
result.With = pTag.With
if pTag.ErrorCode != 0 {
result.ErrorStatusCode = pTag.ErrorCode
Expand Down
10 changes: 5 additions & 5 deletions view/tags/parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type Parameter struct {
DataType string `tag:"dataType,omitempty"` //parameter input type
With string `tag:"with,omitempty"` //optional auxiliary type name holding parameters
Required bool `tag:"required,omitempty"`
Cachable *bool `tag:"cachable,omitempty"`
Cacheable *bool `tag:"cacheable,omitempty"`
Async bool `tag:"async,omitempty"`
}

Expand All @@ -34,9 +34,9 @@ func (t *Tag) updatedParameter(key string, value string) (err error) {
tag.In = strings.Trim(strings.TrimSpace(value), "{}")
case "when":
tag.When = strings.TrimSpace(value)
case "cachable":
case "cacheable":
value := strings.TrimSpace(value) == "" || strings.ToLower(strings.TrimSpace(value)) == "true"
tag.Cachable = &value
tag.Cacheable = &value
case "async":
tag.Async = true
case "scope":
Expand All @@ -63,9 +63,9 @@ func (p *Parameter) Tag() *tags.Tag {
appendNonEmpty(builder, "kind", p.Kind)
appendNonEmpty(builder, "in", p.In)
appendNonEmpty(builder, "when", p.When)
if p.Cachable != nil {
if p.Cacheable != nil {
value := "false"
if *p.Cachable {
if *p.Cacheable {
value = "true"
}
appendNonEmpty(builder, "cachable", value)
Expand Down

0 comments on commit 46211f2

Please sign in to comment.