3
0

Improve expr types, add r/w locking

This commit is contained in:
Denis Arh 2021-07-13 16:39:12 +02:00
parent d63f21c941
commit a7e2eec9fd
15 changed files with 795 additions and 304 deletions

View File

@ -12,13 +12,17 @@ import (
"context"
"fmt"
. "github.com/cortezaproject/corteza-server/pkg/expr"
"sync"
)
var _ = context.Background
var _ = fmt.Errorf
// EmailMessage is an expression type, wrapper for *emailMessage type
type EmailMessage struct{ value *emailMessage }
type EmailMessage struct {
value *emailMessage
mux sync.RWMutex
}
// NewEmailMessage creates new instance of EmailMessage expression type
func NewEmailMessage(val interface{}) (*EmailMessage, error) {
@ -29,16 +33,24 @@ func NewEmailMessage(val interface{}) (*EmailMessage, error) {
}
}
// Return underlying value on EmailMessage
func (t EmailMessage) Get() interface{} { return t.value }
// Get return underlying value on EmailMessage
func (t *EmailMessage) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on EmailMessage
func (t EmailMessage) GetValue() *emailMessage { return t.value }
// GetValue returns underlying value on EmailMessage
func (t *EmailMessage) GetValue() *emailMessage {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (EmailMessage) Type() string { return "EmailMessage" }
// Convert value to *emailMessage
// Cast converts value to *emailMessage
func (EmailMessage) Cast(val interface{}) (TypedValue, error) {
return NewEmailMessage(val)
}

View File

@ -416,10 +416,7 @@ func (svc *session) stateChangeHandler(ctx context.Context) wfexec.StateChangeHa
return
}
if ses.Stacktrace != nil || ses.Error != "" {
// Save stacktrace when we know we're tracing workflows OR whenever there is an error...
ses.Stacktrace = ses.RuntimeStacktrace
}
ses.CopyRuntimeStacktrace()
if err := svc.store.UpsertAutomationSession(ctx, ses); err != nil {
log.Error("failed to update session", zap.Error(err))

View File

@ -124,6 +124,9 @@ func (s *Session) GC() bool {
// WaitResults wait blocks until workflow session is completed or fails (or context is canceled) and returns resuts
func (s *Session) WaitResults(ctx context.Context) (*expr.Vars, wfexec.SessionStatus, Stacktrace, error) {
s.l.RLock()
defer s.l.RUnlock()
if err := s.session.WaitUntil(ctx, wfexec.SessionFailed, wfexec.SessionCompleted); err != nil {
return nil, -1, s.Stacktrace, err
}
@ -152,6 +155,16 @@ func (s *Session) Apply(ssp SessionStartParams) {
}
}
func (s *Session) CopyRuntimeStacktrace() {
s.l.Lock()
defer s.l.Unlock()
if s.Stacktrace != nil || s.Error != "" {
// Save stacktrace when we know we're tracing workflows OR whenever there is an error...
s.Stacktrace = s.RuntimeStacktrace
}
}
func (set *Stacktrace) Scan(value interface{}) error {
//lint:ignore S1034 This typecast is intentional, we need to get []byte out of a []uint8
switch value.(type) {

View File

@ -13,13 +13,17 @@ import (
"fmt"
"github.com/cortezaproject/corteza-server/compose/types"
. "github.com/cortezaproject/corteza-server/pkg/expr"
"sync"
)
var _ = context.Background
var _ = fmt.Errorf
// ComposeModule is an expression type, wrapper for *types.Module type
type ComposeModule struct{ value *types.Module }
type ComposeModule struct {
value *types.Module
mux sync.RWMutex
}
// NewComposeModule creates new instance of ComposeModule expression type
func NewComposeModule(val interface{}) (*ComposeModule, error) {
@ -30,16 +34,24 @@ func NewComposeModule(val interface{}) (*ComposeModule, error) {
}
}
// Return underlying value on ComposeModule
func (t ComposeModule) Get() interface{} { return t.value }
// Get return underlying value on ComposeModule
func (t *ComposeModule) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on ComposeModule
func (t ComposeModule) GetValue() *types.Module { return t.value }
// GetValue returns underlying value on ComposeModule
func (t *ComposeModule) GetValue() *types.Module {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (ComposeModule) Type() string { return "ComposeModule" }
// Convert value to *types.Module
// Cast converts value to *types.Module
func (ComposeModule) Cast(val interface{}) (TypedValue, error) {
return NewComposeModule(val)
}
@ -57,6 +69,8 @@ func (t *ComposeModule) Assign(val interface{}) error {
}
func (t *ComposeModule) AssignFieldValue(key string, val TypedValue) error {
t.mux.Lock()
defer t.mux.Unlock()
return assignToComposeModule(t.value, key, val)
}
@ -65,18 +79,24 @@ func (t *ComposeModule) AssignFieldValue(key string, val TypedValue) error {
// It allows gval lib to access ComposeModule's underlying value (*types.Module)
// and it's fields
//
func (t ComposeModule) SelectGVal(ctx context.Context, k string) (interface{}, error) {
func (t *ComposeModule) SelectGVal(ctx context.Context, k string) (interface{}, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return composeModuleGValSelector(t.value, k)
}
// Select is field accessor for *types.Module
//
// Similar to SelectGVal but returns typed values
func (t ComposeModule) Select(k string) (TypedValue, error) {
func (t *ComposeModule) Select(k string) (TypedValue, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return composeModuleTypedValueSelector(t.value, k)
}
func (t ComposeModule) Has(k string) bool {
func (t *ComposeModule) Has(k string) bool {
t.mux.RLock()
defer t.mux.RUnlock()
switch k {
case "ID", "moduleID":
return true
@ -195,7 +215,10 @@ func assignToComposeModule(res *types.Module, k string, val interface{}) error {
}
// ComposeNamespace is an expression type, wrapper for *types.Namespace type
type ComposeNamespace struct{ value *types.Namespace }
type ComposeNamespace struct {
value *types.Namespace
mux sync.RWMutex
}
// NewComposeNamespace creates new instance of ComposeNamespace expression type
func NewComposeNamespace(val interface{}) (*ComposeNamespace, error) {
@ -206,16 +229,24 @@ func NewComposeNamespace(val interface{}) (*ComposeNamespace, error) {
}
}
// Return underlying value on ComposeNamespace
func (t ComposeNamespace) Get() interface{} { return t.value }
// Get return underlying value on ComposeNamespace
func (t *ComposeNamespace) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on ComposeNamespace
func (t ComposeNamespace) GetValue() *types.Namespace { return t.value }
// GetValue returns underlying value on ComposeNamespace
func (t *ComposeNamespace) GetValue() *types.Namespace {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (ComposeNamespace) Type() string { return "ComposeNamespace" }
// Convert value to *types.Namespace
// Cast converts value to *types.Namespace
func (ComposeNamespace) Cast(val interface{}) (TypedValue, error) {
return NewComposeNamespace(val)
}
@ -233,6 +264,8 @@ func (t *ComposeNamespace) Assign(val interface{}) error {
}
func (t *ComposeNamespace) AssignFieldValue(key string, val TypedValue) error {
t.mux.Lock()
defer t.mux.Unlock()
return assignToComposeNamespace(t.value, key, val)
}
@ -241,18 +274,24 @@ func (t *ComposeNamespace) AssignFieldValue(key string, val TypedValue) error {
// It allows gval lib to access ComposeNamespace's underlying value (*types.Namespace)
// and it's fields
//
func (t ComposeNamespace) SelectGVal(ctx context.Context, k string) (interface{}, error) {
func (t *ComposeNamespace) SelectGVal(ctx context.Context, k string) (interface{}, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return composeNamespaceGValSelector(t.value, k)
}
// Select is field accessor for *types.Namespace
//
// Similar to SelectGVal but returns typed values
func (t ComposeNamespace) Select(k string) (TypedValue, error) {
func (t *ComposeNamespace) Select(k string) (TypedValue, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return composeNamespaceTypedValueSelector(t.value, k)
}
func (t ComposeNamespace) Has(k string) bool {
func (t *ComposeNamespace) Has(k string) bool {
t.mux.RLock()
defer t.mux.RUnlock()
switch k {
case "ID", "namespaceID":
return true
@ -363,7 +402,10 @@ func assignToComposeNamespace(res *types.Namespace, k string, val interface{}) e
}
// ComposeRecord is an expression type, wrapper for *types.Record type
type ComposeRecord struct{ value *types.Record }
type ComposeRecord struct {
value *types.Record
mux sync.RWMutex
}
// NewComposeRecord creates new instance of ComposeRecord expression type
func NewComposeRecord(val interface{}) (*ComposeRecord, error) {
@ -374,16 +416,24 @@ func NewComposeRecord(val interface{}) (*ComposeRecord, error) {
}
}
// Return underlying value on ComposeRecord
func (t ComposeRecord) Get() interface{} { return t.value }
// Get return underlying value on ComposeRecord
func (t *ComposeRecord) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on ComposeRecord
func (t ComposeRecord) GetValue() *types.Record { return t.value }
// GetValue returns underlying value on ComposeRecord
func (t *ComposeRecord) GetValue() *types.Record {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (ComposeRecord) Type() string { return "ComposeRecord" }
// Convert value to *types.Record
// Cast converts value to *types.Record
func (ComposeRecord) Cast(val interface{}) (TypedValue, error) {
return NewComposeRecord(val)
}
@ -400,7 +450,9 @@ func (t *ComposeRecord) Assign(val interface{}) error {
}
}
func (t ComposeRecord) Has(k string) bool {
func (t *ComposeRecord) Has(k string) bool {
t.mux.RLock()
defer t.mux.RUnlock()
switch k {
case "ID", "recordID":
return true
@ -551,7 +603,10 @@ func assignToComposeRecord(res *types.Record, k string, val interface{}) error {
}
// ComposeRecordValueErrorSet is an expression type, wrapper for *types.RecordValueErrorSet type
type ComposeRecordValueErrorSet struct{ value *types.RecordValueErrorSet }
type ComposeRecordValueErrorSet struct {
value *types.RecordValueErrorSet
mux sync.RWMutex
}
// NewComposeRecordValueErrorSet creates new instance of ComposeRecordValueErrorSet expression type
func NewComposeRecordValueErrorSet(val interface{}) (*ComposeRecordValueErrorSet, error) {
@ -562,16 +617,24 @@ func NewComposeRecordValueErrorSet(val interface{}) (*ComposeRecordValueErrorSet
}
}
// Return underlying value on ComposeRecordValueErrorSet
func (t ComposeRecordValueErrorSet) Get() interface{} { return t.value }
// Get return underlying value on ComposeRecordValueErrorSet
func (t *ComposeRecordValueErrorSet) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on ComposeRecordValueErrorSet
func (t ComposeRecordValueErrorSet) GetValue() *types.RecordValueErrorSet { return t.value }
// GetValue returns underlying value on ComposeRecordValueErrorSet
func (t *ComposeRecordValueErrorSet) GetValue() *types.RecordValueErrorSet {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (ComposeRecordValueErrorSet) Type() string { return "ComposeRecordValueErrorSet" }
// Convert value to *types.RecordValueErrorSet
// Cast converts value to *types.RecordValueErrorSet
func (ComposeRecordValueErrorSet) Cast(val interface{}) (TypedValue, error) {
return NewComposeRecordValueErrorSet(val)
}

View File

@ -98,6 +98,9 @@ var _ expr.DeepFieldAssigner = &ComposeRecord{}
// We need to reroute value assigning for record-value-sets because
// we loose the reference to record-value slice
func (t *ComposeRecord) AssignFieldValue(kk []string, val expr.TypedValue) error {
t.mux.Lock()
defer t.mux.Unlock()
switch kk[0] {
case "values":
return assignToComposeRecordValues(t.value, kk[1:], val)
@ -115,7 +118,10 @@ var _ gval.Selector = &ComposeRecord{}
// It allows gval lib to access Record's underlying value (*types.Record)
// and it's fields
//
func (t ComposeRecord) SelectGVal(_ context.Context, k string) (interface{}, error) {
func (t *ComposeRecord) SelectGVal(_ context.Context, k string) (interface{}, error) {
t.mux.RLock()
defer t.mux.RUnlock()
if t.value != nil && k == "values" {
if t.value.Values == nil {
t.value.Values = types.RecordValueSet{}
@ -134,7 +140,10 @@ func (t ComposeRecord) SelectGVal(_ context.Context, k string) (interface{}, err
// Select is field accessor for *types.ComposeRecord
//
// Similar to SelectGVal but returns typed values
func (t ComposeRecord) Select(k string) (expr.TypedValue, error) {
func (t *ComposeRecord) Select(k string) (expr.TypedValue, error) {
t.mux.RLock()
defer t.mux.RUnlock()
if t.value != nil && k == "values" {
if t.value.Values == nil {
t.value.Values = types.RecordValueSet{}

View File

@ -69,13 +69,13 @@ func TestRecordFieldValuesAccess(t *testing.T) {
// same as &ComposeRecord{value: &types.Record{}},
"validRecZero": &ComposeRecord{value: &types.Record{ID: 0, Values: types.RecordValueSet{}}},
"validRecValidID": &ComposeRecord{&types.Record{ID: 42, Values: types.RecordValueSet{}}},
"validRecValidID": &ComposeRecord{value: &types.Record{ID: 42, Values: types.RecordValueSet{}}},
// "record" (not really) set to nil
"fooRec": nil,
// record with id and value set (this was) fixme
"record": &ComposeRecord{&types.Record{ID: 99, Values: rawValues}},
"record": &ComposeRecord{value: &types.Record{ID: 99, Values: rawValues}},
})
)
@ -139,8 +139,8 @@ func TestRecordFieldValuesAccess(t *testing.T) {
e.SetEval(evaluable)
input, _ := expr.NewVars(map[string]expr.TypedValue{
"record": &ComposeRecord{inputRec},
"recordClone": &ComposeRecord{cloneRec},
"record": &ComposeRecord{value: inputRec},
"recordClone": &ComposeRecord{value: cloneRec},
})
output, err = (aTypes.ExprSet{e}).Eval(context.Background(), input)

View File

@ -11,6 +11,7 @@ package {{ .Package }}
import (
"context"
"fmt"
"sync"
{{- range .Imports }}
{{ normalizeImport . }}
{{- end }}
@ -25,7 +26,10 @@ var _ = fmt.Errorf
{{ range $exprType, $def := .Types }}
{{ if not $def.CustomType }}
// {{ $exprType }} is an expression type, wrapper for {{ $def.As }} type
type {{ $exprType }} struct{ value {{ $def.As }} }
type {{ $exprType }} struct{
value {{ $def.As }}
mux sync.RWMutex
}
// New{{ $exprType }} creates new instance of {{ $exprType }} expression type
func New{{ $exprType }}(val interface{}) (*{{ $exprType }}, error) {
@ -37,16 +41,24 @@ func New{{ $exprType }}(val interface{}) (*{{ $exprType }}, error) {
}
// Return underlying value on {{ $exprType }}
func (t {{ $exprType }}) Get() interface{} { return t.value }
// Get return underlying value on {{ $exprType }}
func (t *{{ $exprType }}) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on {{ $exprType }}
func (t {{ $exprType }}) GetValue() {{ $def.As }} { return t.value }
// GetValue returns underlying value on {{ $exprType }}
func (t *{{ $exprType }}) GetValue() {{ $def.As }} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func ({{ $exprType }}) Type() string { return "{{ $exprType }}" }
// Convert value to {{ $def.As }}
// Cast converts value to {{ $def.As }}
func ({{ $exprType }}) Cast(val interface{}) (TypedValue, error) {
return New{{ $exprType }}(val)
}
@ -67,6 +79,8 @@ func (t *{{ $exprType }}) Assign(val interface{}) (error) {
{{ if $def.Struct }}
{{ if not $def.CustomFieldAssigner }}
func (t *{{ $exprType }}) AssignFieldValue(key string, val TypedValue) error {
t.mux.Lock()
defer t.mux.Unlock()
return {{ $def.AssignerFn }}(t.value, key, val)
}
{{ end }}
@ -77,7 +91,9 @@ func (t *{{ $exprType }}) AssignFieldValue(key string, val TypedValue) error {
// It allows gval lib to access {{ $exprType }}'s underlying value ({{ $def.As }})
// and it's fields
//
func (t {{ $exprType }}) SelectGVal(ctx context.Context, k string) (interface{}, error) {
func (t *{{ $exprType }}) SelectGVal(ctx context.Context, k string) (interface{}, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return {{ unexport $exprType "GValSelector" }}(t.value, k)
}
{{ end }}
@ -86,12 +102,16 @@ func (t {{ $exprType }}) SelectGVal(ctx context.Context, k string) (interface{},
// Select is field accessor for {{ $def.As }}
//
// Similar to SelectGVal but returns typed values
func (t {{ $exprType }}) Select(k string) (TypedValue, error) {
func (t *{{ $exprType }}) Select(k string) (TypedValue, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return {{ unexport $exprType "TypedValueSelector" }}(t.value, k)
}
{{ end }}
func (t {{ $exprType }}) Has(k string) bool {
func (t *{{ $exprType }}) Has(k string) bool {
t.mux.RLock()
defer t.mux.RUnlock()
switch k {
{{- range $def.Struct }}
{{- if .ExprType }}

View File

@ -12,6 +12,7 @@ import (
"context"
"fmt"
"io"
"sync"
"time"
)
@ -19,7 +20,10 @@ var _ = context.Background
var _ = fmt.Errorf
// Any is an expression type, wrapper for interface{} type
type Any struct{ value interface{} }
type Any struct {
value interface{}
mux sync.RWMutex
}
// NewAny creates new instance of Any expression type
func NewAny(val interface{}) (*Any, error) {
@ -30,16 +34,24 @@ func NewAny(val interface{}) (*Any, error) {
}
}
// Return underlying value on Any
func (t Any) Get() interface{} { return t.value }
// Get return underlying value on Any
func (t *Any) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on Any
func (t Any) GetValue() interface{} { return t.value }
// GetValue returns underlying value on Any
func (t *Any) GetValue() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (Any) Type() string { return "Any" }
// Convert value to interface{}
// Cast converts value to interface{}
func (Any) Cast(val interface{}) (TypedValue, error) {
return NewAny(val)
}
@ -57,7 +69,10 @@ func (t *Any) Assign(val interface{}) error {
}
// Array is an expression type, wrapper for []TypedValue type
type Array struct{ value []TypedValue }
type Array struct {
value []TypedValue
mux sync.RWMutex
}
// NewArray creates new instance of Array expression type
func NewArray(val interface{}) (*Array, error) {
@ -68,16 +83,24 @@ func NewArray(val interface{}) (*Array, error) {
}
}
// Return underlying value on Array
func (t Array) Get() interface{} { return t.value }
// Get return underlying value on Array
func (t *Array) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on Array
func (t Array) GetValue() []TypedValue { return t.value }
// GetValue returns underlying value on Array
func (t *Array) GetValue() []TypedValue {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (Array) Type() string { return "Array" }
// Convert value to []TypedValue
// Cast converts value to []TypedValue
func (Array) Cast(val interface{}) (TypedValue, error) {
return NewArray(val)
}
@ -95,7 +118,10 @@ func (t *Array) Assign(val interface{}) error {
}
// Boolean is an expression type, wrapper for bool type
type Boolean struct{ value bool }
type Boolean struct {
value bool
mux sync.RWMutex
}
// NewBoolean creates new instance of Boolean expression type
func NewBoolean(val interface{}) (*Boolean, error) {
@ -106,16 +132,24 @@ func NewBoolean(val interface{}) (*Boolean, error) {
}
}
// Return underlying value on Boolean
func (t Boolean) Get() interface{} { return t.value }
// Get return underlying value on Boolean
func (t *Boolean) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on Boolean
func (t Boolean) GetValue() bool { return t.value }
// GetValue returns underlying value on Boolean
func (t *Boolean) GetValue() bool {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (Boolean) Type() string { return "Boolean" }
// Convert value to bool
// Cast converts value to bool
func (Boolean) Cast(val interface{}) (TypedValue, error) {
return NewBoolean(val)
}
@ -133,7 +167,10 @@ func (t *Boolean) Assign(val interface{}) error {
}
// DateTime is an expression type, wrapper for *time.Time type
type DateTime struct{ value *time.Time }
type DateTime struct {
value *time.Time
mux sync.RWMutex
}
// NewDateTime creates new instance of DateTime expression type
func NewDateTime(val interface{}) (*DateTime, error) {
@ -144,16 +181,24 @@ func NewDateTime(val interface{}) (*DateTime, error) {
}
}
// Return underlying value on DateTime
func (t DateTime) Get() interface{} { return t.value }
// Get return underlying value on DateTime
func (t *DateTime) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on DateTime
func (t DateTime) GetValue() *time.Time { return t.value }
// GetValue returns underlying value on DateTime
func (t *DateTime) GetValue() *time.Time {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (DateTime) Type() string { return "DateTime" }
// Convert value to *time.Time
// Cast converts value to *time.Time
func (DateTime) Cast(val interface{}) (TypedValue, error) {
return NewDateTime(val)
}
@ -171,7 +216,10 @@ func (t *DateTime) Assign(val interface{}) error {
}
// Duration is an expression type, wrapper for time.Duration type
type Duration struct{ value time.Duration }
type Duration struct {
value time.Duration
mux sync.RWMutex
}
// NewDuration creates new instance of Duration expression type
func NewDuration(val interface{}) (*Duration, error) {
@ -182,16 +230,24 @@ func NewDuration(val interface{}) (*Duration, error) {
}
}
// Return underlying value on Duration
func (t Duration) Get() interface{} { return t.value }
// Get return underlying value on Duration
func (t *Duration) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on Duration
func (t Duration) GetValue() time.Duration { return t.value }
// GetValue returns underlying value on Duration
func (t *Duration) GetValue() time.Duration {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (Duration) Type() string { return "Duration" }
// Convert value to time.Duration
// Cast converts value to time.Duration
func (Duration) Cast(val interface{}) (TypedValue, error) {
return NewDuration(val)
}
@ -209,7 +265,10 @@ func (t *Duration) Assign(val interface{}) error {
}
// Float is an expression type, wrapper for float64 type
type Float struct{ value float64 }
type Float struct {
value float64
mux sync.RWMutex
}
// NewFloat creates new instance of Float expression type
func NewFloat(val interface{}) (*Float, error) {
@ -220,16 +279,24 @@ func NewFloat(val interface{}) (*Float, error) {
}
}
// Return underlying value on Float
func (t Float) Get() interface{} { return t.value }
// Get return underlying value on Float
func (t *Float) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on Float
func (t Float) GetValue() float64 { return t.value }
// GetValue returns underlying value on Float
func (t *Float) GetValue() float64 {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (Float) Type() string { return "Float" }
// Convert value to float64
// Cast converts value to float64
func (Float) Cast(val interface{}) (TypedValue, error) {
return NewFloat(val)
}
@ -247,7 +314,10 @@ func (t *Float) Assign(val interface{}) error {
}
// Handle is an expression type, wrapper for string type
type Handle struct{ value string }
type Handle struct {
value string
mux sync.RWMutex
}
// NewHandle creates new instance of Handle expression type
func NewHandle(val interface{}) (*Handle, error) {
@ -258,16 +328,24 @@ func NewHandle(val interface{}) (*Handle, error) {
}
}
// Return underlying value on Handle
func (t Handle) Get() interface{} { return t.value }
// Get return underlying value on Handle
func (t *Handle) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on Handle
func (t Handle) GetValue() string { return t.value }
// GetValue returns underlying value on Handle
func (t *Handle) GetValue() string {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (Handle) Type() string { return "Handle" }
// Convert value to string
// Cast converts value to string
func (Handle) Cast(val interface{}) (TypedValue, error) {
return NewHandle(val)
}
@ -285,7 +363,10 @@ func (t *Handle) Assign(val interface{}) error {
}
// ID is an expression type, wrapper for uint64 type
type ID struct{ value uint64 }
type ID struct {
value uint64
mux sync.RWMutex
}
// NewID creates new instance of ID expression type
func NewID(val interface{}) (*ID, error) {
@ -296,16 +377,24 @@ func NewID(val interface{}) (*ID, error) {
}
}
// Return underlying value on ID
func (t ID) Get() interface{} { return t.value }
// Get return underlying value on ID
func (t *ID) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on ID
func (t ID) GetValue() uint64 { return t.value }
// GetValue returns underlying value on ID
func (t *ID) GetValue() uint64 {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (ID) Type() string { return "ID" }
// Convert value to uint64
// Cast converts value to uint64
func (ID) Cast(val interface{}) (TypedValue, error) {
return NewID(val)
}
@ -323,7 +412,10 @@ func (t *ID) Assign(val interface{}) error {
}
// Integer is an expression type, wrapper for int64 type
type Integer struct{ value int64 }
type Integer struct {
value int64
mux sync.RWMutex
}
// NewInteger creates new instance of Integer expression type
func NewInteger(val interface{}) (*Integer, error) {
@ -334,16 +426,24 @@ func NewInteger(val interface{}) (*Integer, error) {
}
}
// Return underlying value on Integer
func (t Integer) Get() interface{} { return t.value }
// Get return underlying value on Integer
func (t *Integer) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on Integer
func (t Integer) GetValue() int64 { return t.value }
// GetValue returns underlying value on Integer
func (t *Integer) GetValue() int64 {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (Integer) Type() string { return "Integer" }
// Convert value to int64
// Cast converts value to int64
func (Integer) Cast(val interface{}) (TypedValue, error) {
return NewInteger(val)
}
@ -361,7 +461,10 @@ func (t *Integer) Assign(val interface{}) error {
}
// KV is an expression type, wrapper for map[string]string type
type KV struct{ value map[string]string }
type KV struct {
value map[string]string
mux sync.RWMutex
}
// NewKV creates new instance of KV expression type
func NewKV(val interface{}) (*KV, error) {
@ -372,16 +475,24 @@ func NewKV(val interface{}) (*KV, error) {
}
}
// Return underlying value on KV
func (t KV) Get() interface{} { return t.value }
// Get return underlying value on KV
func (t *KV) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on KV
func (t KV) GetValue() map[string]string { return t.value }
// GetValue returns underlying value on KV
func (t *KV) GetValue() map[string]string {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (KV) Type() string { return "KV" }
// Convert value to map[string]string
// Cast converts value to map[string]string
func (KV) Cast(val interface{}) (TypedValue, error) {
return NewKV(val)
}
@ -399,7 +510,10 @@ func (t *KV) Assign(val interface{}) error {
}
// KVV is an expression type, wrapper for map[string][]string type
type KVV struct{ value map[string][]string }
type KVV struct {
value map[string][]string
mux sync.RWMutex
}
// NewKVV creates new instance of KVV expression type
func NewKVV(val interface{}) (*KVV, error) {
@ -410,16 +524,24 @@ func NewKVV(val interface{}) (*KVV, error) {
}
}
// Return underlying value on KVV
func (t KVV) Get() interface{} { return t.value }
// Get return underlying value on KVV
func (t *KVV) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on KVV
func (t KVV) GetValue() map[string][]string { return t.value }
// GetValue returns underlying value on KVV
func (t *KVV) GetValue() map[string][]string {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (KVV) Type() string { return "KVV" }
// Convert value to map[string][]string
// Cast converts value to map[string][]string
func (KVV) Cast(val interface{}) (TypedValue, error) {
return NewKVV(val)
}
@ -437,7 +559,10 @@ func (t *KVV) Assign(val interface{}) error {
}
// Reader is an expression type, wrapper for io.Reader type
type Reader struct{ value io.Reader }
type Reader struct {
value io.Reader
mux sync.RWMutex
}
// NewReader creates new instance of Reader expression type
func NewReader(val interface{}) (*Reader, error) {
@ -448,16 +573,24 @@ func NewReader(val interface{}) (*Reader, error) {
}
}
// Return underlying value on Reader
func (t Reader) Get() interface{} { return t.value }
// Get return underlying value on Reader
func (t *Reader) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on Reader
func (t Reader) GetValue() io.Reader { return t.value }
// GetValue returns underlying value on Reader
func (t *Reader) GetValue() io.Reader {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (Reader) Type() string { return "Reader" }
// Convert value to io.Reader
// Cast converts value to io.Reader
func (Reader) Cast(val interface{}) (TypedValue, error) {
return NewReader(val)
}
@ -475,7 +608,10 @@ func (t *Reader) Assign(val interface{}) error {
}
// String is an expression type, wrapper for string type
type String struct{ value string }
type String struct {
value string
mux sync.RWMutex
}
// NewString creates new instance of String expression type
func NewString(val interface{}) (*String, error) {
@ -486,16 +622,24 @@ func NewString(val interface{}) (*String, error) {
}
}
// Return underlying value on String
func (t String) Get() interface{} { return t.value }
// Get return underlying value on String
func (t *String) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on String
func (t String) GetValue() string { return t.value }
// GetValue returns underlying value on String
func (t *String) GetValue() string {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (String) Type() string { return "String" }
// Convert value to string
// Cast converts value to string
func (String) Cast(val interface{}) (TypedValue, error) {
return NewString(val)
}
@ -513,7 +657,10 @@ func (t *String) Assign(val interface{}) error {
}
// UnsignedInteger is an expression type, wrapper for uint64 type
type UnsignedInteger struct{ value uint64 }
type UnsignedInteger struct {
value uint64
mux sync.RWMutex
}
// NewUnsignedInteger creates new instance of UnsignedInteger expression type
func NewUnsignedInteger(val interface{}) (*UnsignedInteger, error) {
@ -524,16 +671,24 @@ func NewUnsignedInteger(val interface{}) (*UnsignedInteger, error) {
}
}
// Return underlying value on UnsignedInteger
func (t UnsignedInteger) Get() interface{} { return t.value }
// Get return underlying value on UnsignedInteger
func (t *UnsignedInteger) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on UnsignedInteger
func (t UnsignedInteger) GetValue() uint64 { return t.value }
// GetValue returns underlying value on UnsignedInteger
func (t *UnsignedInteger) GetValue() uint64 {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (UnsignedInteger) Type() string { return "UnsignedInteger" }
// Convert value to uint64
// Cast converts value to uint64
func (UnsignedInteger) Cast(val interface{}) (TypedValue, error) {
return NewUnsignedInteger(val)
}
@ -551,7 +706,10 @@ func (t *UnsignedInteger) Assign(val interface{}) error {
}
// Vars is an expression type, wrapper for map[string]TypedValue type
type Vars struct{ value map[string]TypedValue }
type Vars struct {
value map[string]TypedValue
mux sync.RWMutex
}
// NewVars creates new instance of Vars expression type
func NewVars(val interface{}) (*Vars, error) {
@ -562,16 +720,24 @@ func NewVars(val interface{}) (*Vars, error) {
}
}
// Return underlying value on Vars
func (t Vars) Get() interface{} { return t.value }
// Get return underlying value on Vars
func (t *Vars) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on Vars
func (t Vars) GetValue() map[string]TypedValue { return t.value }
// GetValue returns underlying value on Vars
func (t *Vars) GetValue() map[string]TypedValue {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (Vars) Type() string { return "Vars" }
// Convert value to map[string]TypedValue
// Cast converts value to map[string]TypedValue
func (Vars) Cast(val interface{}) (TypedValue, error) {
return NewVars(val)
}

View File

@ -137,10 +137,10 @@ func Typify(in interface{}) (tv TypedValue, err error) {
if v, err := CastToVars(c); err != nil {
return nil, err
} else {
return &Vars{v}, nil
return &Vars{value: v}, nil
}
case map[string]TypedValue:
return &Vars{c}, nil
return &Vars{value: c}, nil
case map[string]string:
return &KV{value: c}, nil
case map[string][]string:

View File

@ -3,10 +3,11 @@ package expr
import (
"context"
"fmt"
"github.com/stretchr/testify/require"
"net/http"
"net/url"
"testing"
"github.com/stretchr/testify/require"
)
func Example_set_kv() {
@ -20,11 +21,11 @@ func Example_set_kv() {
)
eval(`set(kv, key, value)`, p)
fmt.Printf("\nOriginal KV should be %v", kv)
fmt.Printf("\nOriginal KV should be %v", kv.value)
// output:
// &{value:map[k1:v11]}
// Original KV should be &{map[]}
// map[k1:v11]
// Original KV should be map[]
}
func Example_merge_kv() {
@ -42,11 +43,11 @@ func Example_merge_kv() {
)
eval(`merge(kv, foo, bar)`, p)
fmt.Printf("\nOriginal KV should be %v", kv)
fmt.Printf("\nOriginal KV should be %v", kv.value)
// output:
// &{value:map[k1:v1 k2:v2]}
// Original KV should be &{map[]}
// map[k1:v1 k2:v2]
// Original KV should be map[]
}
func Example_filter_kv() {
@ -63,11 +64,11 @@ func Example_filter_kv() {
)
eval(`filter(kv, key1, key2)`, p)
fmt.Printf("\nOriginal KV should be %v", kv)
fmt.Printf("\nOriginal KV should be %v", kv.value)
// output:
// &{value:map[k1:v1]}
// Original KV should be &{map[k1:v1 k2:v2]}
// map[k1:v1]
// Original KV should be map[k1:v1 k2:v2]
}
func Example_omit_kv() {
@ -85,11 +86,11 @@ func Example_omit_kv() {
)
eval(`omit(kv, key1, key2)`, p)
fmt.Printf("\nOriginal KV should be %v", kv)
fmt.Printf("\nOriginal KV should be %v", kv.value)
// output:
// &{value:map[k2:v2]}
// Original KV should be &{map[k1:v1 k2:v2 k3:v3]}
// map[k2:v2]
// Original KV should be map[k1:v1 k2:v2 k3:v3]
}
func Example_set_kvv() {
@ -103,11 +104,11 @@ func Example_set_kvv() {
)
eval(`set(kvv, key, value)`, p)
fmt.Printf("\nOriginal KVV should be %v", kvv)
fmt.Printf("\nOriginal KVV should be %v", kvv.value)
// output:
// &{value:map[foo:[bar]]}
// Original KVV should be &{map[]}
// map[foo:[bar]]
// Original KVV should be map[]
}
func Example_merge_kvv() {
@ -126,11 +127,11 @@ func Example_merge_kvv() {
)
eval(`merge(kvv, foo, bar)`, p)
fmt.Printf("\nOriginal KVV should be %v", kvv)
fmt.Printf("\nOriginal KVV should be %v", kvv.value)
// output:
// &{value:map[k1:[v1 v11] k2:[v2]]}
// Original KVV should be &{map[]}
// map[k1:[v1 v11] k2:[v2]]
// Original KVV should be map[]
}
func Example_filter_kvv() {
@ -147,11 +148,11 @@ func Example_filter_kvv() {
)
eval(`filter(kv, key1, key2)`, p)
fmt.Printf("\nOriginal KVV should be %v", kvv)
fmt.Printf("\nOriginal KVV should be %v", kvv.value)
// output:
// &{value:map[k1:[v1]]}
// Original KVV should be &{map[k1:[v1] k2:[v2]]}
// map[k1:[v1]]
// Original KVV should be map[k1:[v1] k2:[v2]]
}
func Example_omit_kvv() {
@ -169,11 +170,11 @@ func Example_omit_kvv() {
)
eval(`omit(kvv, key1, key2)`, p)
fmt.Printf("\nOriginal KVV should be %v", kvv)
fmt.Printf("\nOriginal KVV should be %v", kvv.value)
// output:
// &{value:map[k2:[v2]]}
// Original KVV should be &{map[k1:[v1] k2:[v2] k3:[v3]]}
// map[k2:[v2]]
// Original KVV should be map[k1:[v1] k2:[v2] k3:[v3]]
}
func TestTypedValueOperations(t *testing.T) {
@ -527,10 +528,10 @@ func TestArrayDecode(t *testing.T) {
req.NoError(err)
vars, err := NewVars(map[string]interface{}{
"strings": &Array{arr},
"strings": &Array{value: arr},
"iface": Must(NewString("typed")),
"typed": Must(NewString("typed")),
"values": &Array{arr},
"values": &Array{value: arr},
})
req.NoError(err)

View File

@ -103,6 +103,6 @@ func eval(e string, p interface{}) {
if err != nil {
fmt.Printf("error: %v", err)
} else {
fmt.Printf("%+v", result)
fmt.Printf("%+v", UntypedValue(result))
}
}

View File

@ -13,11 +13,17 @@ import (
"github.com/spf13/cast"
)
func (t Vars) Len() int {
func (t *Vars) Len() int {
t.mux.RLock()
defer t.mux.RUnlock()
return len(t.value)
}
func (t Vars) Select(k string) (TypedValue, error) {
func (t *Vars) Select(k string) (TypedValue, error) {
t.mux.RLock()
defer t.mux.RUnlock()
if v, is := t.value[k]; is {
return v, nil
} else {
@ -26,6 +32,9 @@ func (t Vars) Select(k string) (TypedValue, error) {
}
func (t *Vars) AssignFieldValue(key string, val TypedValue) (err error) {
t.mux.Lock()
defer t.mux.Unlock()
if t.value == nil {
t.value = make(map[string]TypedValue)
}
@ -35,7 +44,14 @@ func (t *Vars) AssignFieldValue(key string, val TypedValue) (err error) {
return err
}
func (t Vars) ResolveTypes(res func(typ string) Type) (err error) {
func (t *Vars) ResolveTypes(res func(typ string) Type) (err error) {
if t == nil {
return nil
}
t.mux.RLock()
defer t.mux.RUnlock()
for k, v := range t.value {
if u, is := v.(*Unresolved); is {
if res(u.Type()) == nil {
@ -61,28 +77,22 @@ func (t Vars) ResolveTypes(res func(typ string) Type) (err error) {
// Merge combines the given Vars(es) into Vars
// NOTE: It will return CLONE of the original Vars, if its called without any parameters
func (t *Vars) Merge(nn ...Iterator) (out TypedValue, err error) {
vars := EmptyVars()
nn = append([]Iterator{t}, nn...)
for _, i := range nn {
_ = i.Each(func(k string, v TypedValue) error {
vars.value[k] = v
return nil
})
}
return vars, nil
return t.MustMerge(nn...), nil
}
// MustMerge returns Vars after merging the given Vars(es) into it
func (t *Vars) MustMerge(nn ...Iterator) *Vars {
if t != nil {
t.mux.RLock()
defer t.mux.RUnlock()
nn = append([]Iterator{t}, nn...)
}
var (
out = &Vars{value: make(map[string]TypedValue)}
)
nn = append([]Iterator{t}, nn...)
for _, i := range nn {
_ = i.Each(func(k string, v TypedValue) error {
out.value[k] = v
@ -99,6 +109,13 @@ func (t *Vars) Copy(dst *Vars, kk ...string) {
return
}
t.mux.RLock()
defer t.mux.RUnlock()
if t == nil {
return
}
if dst.value == nil {
dst.value = make(map[string]TypedValue)
}
@ -119,6 +136,13 @@ func (t *Vars) HasAll(key string, kk ...string) bool {
return false
}
t.mux.RLock()
defer t.mux.RUnlock()
if t == nil {
return false
}
for _, key = range append([]string{key}, kk...) {
if _, has := t.value[key]; !has {
return false
@ -146,6 +170,9 @@ func (t *Vars) HasAny(key string, kk ...string) bool {
var _ gval.Selector = &Vars{}
func (t *Vars) Dict() map[string]interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
dict := make(map[string]interface{})
for k, v := range t.value {
switch v := v.(type) {
@ -177,6 +204,9 @@ func (t *Vars) Decode(dst interface{}) (err error) {
return nil
}
t.mux.RLock()
defer t.mux.RUnlock()
dstRef := reflect.ValueOf(dst)
if dstRef.Kind() != reflect.Ptr {
@ -234,10 +264,18 @@ func (t *Vars) Scan(value interface{}) error {
}
func (t *Vars) Value() (driver.Value, error) {
if t != nil {
t.mux.RLock()
defer t.mux.RUnlock()
}
return json.Marshal(t)
}
func (t Vars) SelectGVal(_ context.Context, k string) (interface{}, error) {
func (t *Vars) SelectGVal(_ context.Context, k string) (interface{}, error) {
t.mux.RLock()
defer t.mux.RUnlock()
val, err := t.Select(k)
switch c := val.(type) {
case gval.Selector:
@ -249,6 +287,9 @@ func (t Vars) SelectGVal(_ context.Context, k string) (interface{}, error) {
// UnmarshalJSON unmarshal JSON value into Vars
func (t *Vars) UnmarshalJSON(in []byte) (err error) {
t.mux.Lock()
defer t.mux.Unlock()
var (
aux = make(map[string]*typedValueWrap)
)
@ -275,7 +316,14 @@ func (t *Vars) UnmarshalJSON(in []byte) (err error) {
}
func (t *Vars) Each(fn func(k string, v TypedValue) error) (err error) {
if t == nil || t.value == nil {
if t == nil {
return nil
}
t.mux.RLock()
defer t.mux.RUnlock()
if t.value == nil {
return
}
@ -290,6 +338,9 @@ func (t *Vars) Each(fn func(k string, v TypedValue) error) (err error) {
// Set set/update the specific key value in KV
func (t *Vars) Set(k string, v interface{}) (err error) {
t.mux.RLock()
defer t.mux.RUnlock()
if t.value == nil {
t.value = make(map[string]TypedValue)
}
@ -299,7 +350,10 @@ func (t *Vars) Set(k string, v interface{}) (err error) {
}
// MarshalJSON returns JSON encoding of expression
func (t Vars) MarshalJSON() ([]byte, error) {
func (t *Vars) MarshalJSON() ([]byte, error) {
t.mux.RLock()
defer t.mux.RUnlock()
aux := make(map[string]*typedValueWrap)
for k, v := range t.value {
if v == nil {
@ -410,6 +464,9 @@ func CastToVars(val interface{}) (out map[string]TypedValue, err error) {
switch c := val.(type) {
case *Vars:
c.mux.RLock()
defer c.mux.RUnlock()
return c.value, nil
case map[string]TypedValue:
return c, nil
@ -430,6 +487,9 @@ func CastToVars(val interface{}) (out map[string]TypedValue, err error) {
// Filter take keys returns KV with only those key value pair
func (t *Vars) Filter(keys ...string) (out TypedValue, err error) {
t.mux.RLock()
defer t.mux.RUnlock()
if t.value == nil {
return
}
@ -447,6 +507,9 @@ func (t *Vars) Filter(keys ...string) (out TypedValue, err error) {
// Delete take keys returns KV without those key value pair
func (t *Vars) Delete(keys ...string) (out TypedValue, err error) {
t.mux.RLock()
defer t.mux.RUnlock()
if t.value == nil {
return
}

View File

@ -185,7 +185,7 @@ func NewSession(ctx context.Context, g *Graph, oo ...SessionOpt) *Session {
return s
}
func (s Session) Status() SessionStatus {
func (s *Session) Status() SessionStatus {
s.mux.RLock()
defer s.mux.RUnlock()
@ -207,14 +207,14 @@ func (s Session) Status() SessionStatus {
}
}
func (s Session) ID() uint64 {
func (s *Session) ID() uint64 {
s.mux.RLock()
defer s.mux.RUnlock()
return s.id
}
func (s Session) Idle() bool {
func (s *Session) Idle() bool {
return s.Status() != SessionActive
}
@ -514,7 +514,7 @@ func (s *Session) Stop() {
s.qErr <- nil
}
func (s Session) Suspended() bool {
func (s *Session) Suspended() bool {
defer s.mux.RUnlock()
s.mux.RLock()
return len(s.delayed) > 0

View File

@ -96,7 +96,7 @@ func TestSession_SplitAndMerge(t *testing.T) {
ctx = context.Background()
req = require.New(t)
wf = NewGraph()
ses = NewSession(ctx, wf)
ses = NewSession(ctx, wf, SetDumpStacktraceOnPanic(true))
start = &sesTestStep{name: "start"}
split1 = &sesTestStep{name: "split1"}

View File

@ -11,17 +11,20 @@ package automation
import (
"context"
"fmt"
. "github.com/cortezaproject/corteza-server/pkg/expr"
"github.com/cortezaproject/corteza-server/pkg/rbac"
"github.com/cortezaproject/corteza-server/system/types"
"sync"
)
var _ = context.Background
var _ = fmt.Errorf
// DocumentType is an expression type, wrapper for types.DocumentType type
type DocumentType struct{ value types.DocumentType }
type DocumentType struct {
value types.DocumentType
mux sync.RWMutex
}
// NewDocumentType creates new instance of DocumentType expression type
func NewDocumentType(val interface{}) (*DocumentType, error) {
@ -32,16 +35,24 @@ func NewDocumentType(val interface{}) (*DocumentType, error) {
}
}
// Return underlying value on DocumentType
func (t DocumentType) Get() interface{} { return t.value }
// Get return underlying value on DocumentType
func (t *DocumentType) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on DocumentType
func (t DocumentType) GetValue() types.DocumentType { return t.value }
// GetValue returns underlying value on DocumentType
func (t *DocumentType) GetValue() types.DocumentType {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (DocumentType) Type() string { return "DocumentType" }
// Convert value to types.DocumentType
// Cast converts value to types.DocumentType
func (DocumentType) Cast(val interface{}) (TypedValue, error) {
return NewDocumentType(val)
}
@ -59,7 +70,10 @@ func (t *DocumentType) Assign(val interface{}) error {
}
// QueueMessage is an expression type, wrapper for *types.QueueMessage type
type QueueMessage struct{ value *types.QueueMessage }
type QueueMessage struct {
value *types.QueueMessage
mux sync.RWMutex
}
// NewQueueMessage creates new instance of QueueMessage expression type
func NewQueueMessage(val interface{}) (*QueueMessage, error) {
@ -70,16 +84,24 @@ func NewQueueMessage(val interface{}) (*QueueMessage, error) {
}
}
// Return underlying value on QueueMessage
func (t QueueMessage) Get() interface{} { return t.value }
// Get return underlying value on QueueMessage
func (t *QueueMessage) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on QueueMessage
func (t QueueMessage) GetValue() *types.QueueMessage { return t.value }
// GetValue returns underlying value on QueueMessage
func (t *QueueMessage) GetValue() *types.QueueMessage {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (QueueMessage) Type() string { return "QueueMessage" }
// Convert value to *types.QueueMessage
// Cast converts value to *types.QueueMessage
func (QueueMessage) Cast(val interface{}) (TypedValue, error) {
return NewQueueMessage(val)
}
@ -97,6 +119,8 @@ func (t *QueueMessage) Assign(val interface{}) error {
}
func (t *QueueMessage) AssignFieldValue(key string, val TypedValue) error {
t.mux.Lock()
defer t.mux.Unlock()
return assignToQueueMessage(t.value, key, val)
}
@ -105,18 +129,24 @@ func (t *QueueMessage) AssignFieldValue(key string, val TypedValue) error {
// It allows gval lib to access QueueMessage's underlying value (*types.QueueMessage)
// and it's fields
//
func (t QueueMessage) SelectGVal(ctx context.Context, k string) (interface{}, error) {
func (t *QueueMessage) SelectGVal(ctx context.Context, k string) (interface{}, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return queueMessageGValSelector(t.value, k)
}
// Select is field accessor for *types.QueueMessage
//
// Similar to SelectGVal but returns typed values
func (t QueueMessage) Select(k string) (TypedValue, error) {
func (t *QueueMessage) Select(k string) (TypedValue, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return queueMessageTypedValueSelector(t.value, k)
}
func (t QueueMessage) Has(k string) bool {
func (t *QueueMessage) Has(k string) bool {
t.mux.RLock()
defer t.mux.RUnlock()
switch k {
case "Queue":
return true
@ -181,7 +211,10 @@ func assignToQueueMessage(res *types.QueueMessage, k string, val interface{}) er
}
// RbacResource is an expression type, wrapper for rbac.Resource type
type RbacResource struct{ value rbac.Resource }
type RbacResource struct {
value rbac.Resource
mux sync.RWMutex
}
// NewRbacResource creates new instance of RbacResource expression type
func NewRbacResource(val interface{}) (*RbacResource, error) {
@ -192,16 +225,24 @@ func NewRbacResource(val interface{}) (*RbacResource, error) {
}
}
// Return underlying value on RbacResource
func (t RbacResource) Get() interface{} { return t.value }
// Get return underlying value on RbacResource
func (t *RbacResource) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on RbacResource
func (t RbacResource) GetValue() rbac.Resource { return t.value }
// GetValue returns underlying value on RbacResource
func (t *RbacResource) GetValue() rbac.Resource {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (RbacResource) Type() string { return "RbacResource" }
// Convert value to rbac.Resource
// Cast converts value to rbac.Resource
func (RbacResource) Cast(val interface{}) (TypedValue, error) {
return NewRbacResource(val)
}
@ -219,7 +260,10 @@ func (t *RbacResource) Assign(val interface{}) error {
}
// RenderOptions is an expression type, wrapper for map[string]string type
type RenderOptions struct{ value map[string]string }
type RenderOptions struct {
value map[string]string
mux sync.RWMutex
}
// NewRenderOptions creates new instance of RenderOptions expression type
func NewRenderOptions(val interface{}) (*RenderOptions, error) {
@ -230,16 +274,24 @@ func NewRenderOptions(val interface{}) (*RenderOptions, error) {
}
}
// Return underlying value on RenderOptions
func (t RenderOptions) Get() interface{} { return t.value }
// Get return underlying value on RenderOptions
func (t *RenderOptions) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on RenderOptions
func (t RenderOptions) GetValue() map[string]string { return t.value }
// GetValue returns underlying value on RenderOptions
func (t *RenderOptions) GetValue() map[string]string {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (RenderOptions) Type() string { return "RenderOptions" }
// Convert value to map[string]string
// Cast converts value to map[string]string
func (RenderOptions) Cast(val interface{}) (TypedValue, error) {
return NewRenderOptions(val)
}
@ -257,7 +309,10 @@ func (t *RenderOptions) Assign(val interface{}) error {
}
// RenderedDocument is an expression type, wrapper for *renderedDocument type
type RenderedDocument struct{ value *renderedDocument }
type RenderedDocument struct {
value *renderedDocument
mux sync.RWMutex
}
// NewRenderedDocument creates new instance of RenderedDocument expression type
func NewRenderedDocument(val interface{}) (*RenderedDocument, error) {
@ -268,16 +323,24 @@ func NewRenderedDocument(val interface{}) (*RenderedDocument, error) {
}
}
// Return underlying value on RenderedDocument
func (t RenderedDocument) Get() interface{} { return t.value }
// Get return underlying value on RenderedDocument
func (t *RenderedDocument) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on RenderedDocument
func (t RenderedDocument) GetValue() *renderedDocument { return t.value }
// GetValue returns underlying value on RenderedDocument
func (t *RenderedDocument) GetValue() *renderedDocument {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (RenderedDocument) Type() string { return "RenderedDocument" }
// Convert value to *renderedDocument
// Cast converts value to *renderedDocument
func (RenderedDocument) Cast(val interface{}) (TypedValue, error) {
return NewRenderedDocument(val)
}
@ -295,6 +358,8 @@ func (t *RenderedDocument) Assign(val interface{}) error {
}
func (t *RenderedDocument) AssignFieldValue(key string, val TypedValue) error {
t.mux.Lock()
defer t.mux.Unlock()
return assignToRenderedDocument(t.value, key, val)
}
@ -303,18 +368,24 @@ func (t *RenderedDocument) AssignFieldValue(key string, val TypedValue) error {
// It allows gval lib to access RenderedDocument's underlying value (*renderedDocument)
// and it's fields
//
func (t RenderedDocument) SelectGVal(ctx context.Context, k string) (interface{}, error) {
func (t *RenderedDocument) SelectGVal(ctx context.Context, k string) (interface{}, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return renderedDocumentGValSelector(t.value, k)
}
// Select is field accessor for *renderedDocument
//
// Similar to SelectGVal but returns typed values
func (t RenderedDocument) Select(k string) (TypedValue, error) {
func (t *RenderedDocument) Select(k string) (TypedValue, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return renderedDocumentTypedValueSelector(t.value, k)
}
func (t RenderedDocument) Has(k string) bool {
func (t *RenderedDocument) Has(k string) bool {
t.mux.RLock()
defer t.mux.RUnlock()
switch k {
case "document":
return true
@ -393,7 +464,10 @@ func assignToRenderedDocument(res *renderedDocument, k string, val interface{})
}
// Role is an expression type, wrapper for *types.Role type
type Role struct{ value *types.Role }
type Role struct {
value *types.Role
mux sync.RWMutex
}
// NewRole creates new instance of Role expression type
func NewRole(val interface{}) (*Role, error) {
@ -404,16 +478,24 @@ func NewRole(val interface{}) (*Role, error) {
}
}
// Return underlying value on Role
func (t Role) Get() interface{} { return t.value }
// Get return underlying value on Role
func (t *Role) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on Role
func (t Role) GetValue() *types.Role { return t.value }
// GetValue returns underlying value on Role
func (t *Role) GetValue() *types.Role {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (Role) Type() string { return "Role" }
// Convert value to *types.Role
// Cast converts value to *types.Role
func (Role) Cast(val interface{}) (TypedValue, error) {
return NewRole(val)
}
@ -431,6 +513,8 @@ func (t *Role) Assign(val interface{}) error {
}
func (t *Role) AssignFieldValue(key string, val TypedValue) error {
t.mux.Lock()
defer t.mux.Unlock()
return assignToRole(t.value, key, val)
}
@ -439,18 +523,24 @@ func (t *Role) AssignFieldValue(key string, val TypedValue) error {
// It allows gval lib to access Role's underlying value (*types.Role)
// and it's fields
//
func (t Role) SelectGVal(ctx context.Context, k string) (interface{}, error) {
func (t *Role) SelectGVal(ctx context.Context, k string) (interface{}, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return roleGValSelector(t.value, k)
}
// Select is field accessor for *types.Role
//
// Similar to SelectGVal but returns typed values
func (t Role) Select(k string) (TypedValue, error) {
func (t *Role) Select(k string) (TypedValue, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return roleTypedValueSelector(t.value, k)
}
func (t Role) Has(k string) bool {
func (t *Role) Has(k string) bool {
t.mux.RLock()
defer t.mux.RUnlock()
switch k {
case "ID", "roleID":
return true
@ -569,7 +659,10 @@ func assignToRole(res *types.Role, k string, val interface{}) error {
}
// Template is an expression type, wrapper for *types.Template type
type Template struct{ value *types.Template }
type Template struct {
value *types.Template
mux sync.RWMutex
}
// NewTemplate creates new instance of Template expression type
func NewTemplate(val interface{}) (*Template, error) {
@ -580,16 +673,24 @@ func NewTemplate(val interface{}) (*Template, error) {
}
}
// Return underlying value on Template
func (t Template) Get() interface{} { return t.value }
// Get return underlying value on Template
func (t *Template) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on Template
func (t Template) GetValue() *types.Template { return t.value }
// GetValue returns underlying value on Template
func (t *Template) GetValue() *types.Template {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (Template) Type() string { return "Template" }
// Convert value to *types.Template
// Cast converts value to *types.Template
func (Template) Cast(val interface{}) (TypedValue, error) {
return NewTemplate(val)
}
@ -607,6 +708,8 @@ func (t *Template) Assign(val interface{}) error {
}
func (t *Template) AssignFieldValue(key string, val TypedValue) error {
t.mux.Lock()
defer t.mux.Unlock()
return assignToTemplate(t.value, key, val)
}
@ -615,18 +718,24 @@ func (t *Template) AssignFieldValue(key string, val TypedValue) error {
// It allows gval lib to access Template's underlying value (*types.Template)
// and it's fields
//
func (t Template) SelectGVal(ctx context.Context, k string) (interface{}, error) {
func (t *Template) SelectGVal(ctx context.Context, k string) (interface{}, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return templateGValSelector(t.value, k)
}
// Select is field accessor for *types.Template
//
// Similar to SelectGVal but returns typed values
func (t Template) Select(k string) (TypedValue, error) {
func (t *Template) Select(k string) (TypedValue, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return templateTypedValueSelector(t.value, k)
}
func (t Template) Has(k string) bool {
func (t *Template) Has(k string) bool {
t.mux.RLock()
defer t.mux.RUnlock()
switch k {
case "ID", "templateID":
return true
@ -809,7 +918,10 @@ func assignToTemplate(res *types.Template, k string, val interface{}) error {
}
// TemplateMeta is an expression type, wrapper for types.TemplateMeta type
type TemplateMeta struct{ value types.TemplateMeta }
type TemplateMeta struct {
value types.TemplateMeta
mux sync.RWMutex
}
// NewTemplateMeta creates new instance of TemplateMeta expression type
func NewTemplateMeta(val interface{}) (*TemplateMeta, error) {
@ -820,16 +932,24 @@ func NewTemplateMeta(val interface{}) (*TemplateMeta, error) {
}
}
// Return underlying value on TemplateMeta
func (t TemplateMeta) Get() interface{} { return t.value }
// Get return underlying value on TemplateMeta
func (t *TemplateMeta) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on TemplateMeta
func (t TemplateMeta) GetValue() types.TemplateMeta { return t.value }
// GetValue returns underlying value on TemplateMeta
func (t *TemplateMeta) GetValue() types.TemplateMeta {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (TemplateMeta) Type() string { return "TemplateMeta" }
// Convert value to types.TemplateMeta
// Cast converts value to types.TemplateMeta
func (TemplateMeta) Cast(val interface{}) (TypedValue, error) {
return NewTemplateMeta(val)
}
@ -847,6 +967,8 @@ func (t *TemplateMeta) Assign(val interface{}) error {
}
func (t *TemplateMeta) AssignFieldValue(key string, val TypedValue) error {
t.mux.Lock()
defer t.mux.Unlock()
return assignToTemplateMeta(t.value, key, val)
}
@ -855,18 +977,24 @@ func (t *TemplateMeta) AssignFieldValue(key string, val TypedValue) error {
// It allows gval lib to access TemplateMeta's underlying value (types.TemplateMeta)
// and it's fields
//
func (t TemplateMeta) SelectGVal(ctx context.Context, k string) (interface{}, error) {
func (t *TemplateMeta) SelectGVal(ctx context.Context, k string) (interface{}, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return templateMetaGValSelector(t.value, k)
}
// Select is field accessor for types.TemplateMeta
//
// Similar to SelectGVal but returns typed values
func (t TemplateMeta) Select(k string) (TypedValue, error) {
func (t *TemplateMeta) Select(k string) (TypedValue, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return templateMetaTypedValueSelector(t.value, k)
}
func (t TemplateMeta) Has(k string) bool {
func (t *TemplateMeta) Has(k string) bool {
t.mux.RLock()
defer t.mux.RUnlock()
switch k {
case "short":
return true
@ -925,7 +1053,10 @@ func assignToTemplateMeta(res types.TemplateMeta, k string, val interface{}) err
}
// User is an expression type, wrapper for *types.User type
type User struct{ value *types.User }
type User struct {
value *types.User
mux sync.RWMutex
}
// NewUser creates new instance of User expression type
func NewUser(val interface{}) (*User, error) {
@ -936,16 +1067,24 @@ func NewUser(val interface{}) (*User, error) {
}
}
// Return underlying value on User
func (t User) Get() interface{} { return t.value }
// Get return underlying value on User
func (t *User) Get() interface{} {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return underlying value on User
func (t User) GetValue() *types.User { return t.value }
// GetValue returns underlying value on User
func (t *User) GetValue() *types.User {
t.mux.RLock()
defer t.mux.RUnlock()
return t.value
}
// Return type name
// Type return type name
func (User) Type() string { return "User" }
// Convert value to *types.User
// Cast converts value to *types.User
func (User) Cast(val interface{}) (TypedValue, error) {
return NewUser(val)
}
@ -963,6 +1102,8 @@ func (t *User) Assign(val interface{}) error {
}
func (t *User) AssignFieldValue(key string, val TypedValue) error {
t.mux.Lock()
defer t.mux.Unlock()
return assignToUser(t.value, key, val)
}
@ -971,18 +1112,24 @@ func (t *User) AssignFieldValue(key string, val TypedValue) error {
// It allows gval lib to access User's underlying value (*types.User)
// and it's fields
//
func (t User) SelectGVal(ctx context.Context, k string) (interface{}, error) {
func (t *User) SelectGVal(ctx context.Context, k string) (interface{}, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return userGValSelector(t.value, k)
}
// Select is field accessor for *types.User
//
// Similar to SelectGVal but returns typed values
func (t User) Select(k string) (TypedValue, error) {
func (t *User) Select(k string) (TypedValue, error) {
t.mux.RLock()
defer t.mux.RUnlock()
return userTypedValueSelector(t.value, k)
}
func (t User) Has(k string) bool {
func (t *User) Has(k string) bool {
t.mux.RLock()
defer t.mux.RUnlock()
switch k {
case "ID", "userID":
return true