Skip to content

Commit

Permalink
🔨 proto: add pre and locals
Browse files Browse the repository at this point in the history
  • Loading branch information
rjeczalik committed Jul 6, 2024
1 parent 5ce649f commit 5812f4e
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 40 deletions.
49 changes: 18 additions & 31 deletions pkg/plugin/builtin/event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ import (
"hookt.dev/cmd/pkg/trace"
)

type step struct {
c chan proto.Message
done chan struct{}
}

type Plugin struct {
wire.Config

Expand All @@ -27,6 +22,11 @@ type Plugin struct {
stop chan int
}

type step struct {
c chan proto.Message
done chan struct{}
}

func New(opts ...func(*Plugin)) *Plugin {
p := &Plugin{
mux: make(chan proto.Message),
Expand Down Expand Up @@ -184,21 +184,19 @@ func (s *Step) Run(ctx context.Context, c *check.S) error {
"fail", s.Fail,
)

tr := trace.ContextPattern(ctx)

match, err := s.p.p.Patterns(group(ctx, "match"), s.Match)
if err != nil {
return errors.New("failed to parse match pattern: %w", err)
}
var (
tr = trace.ContextPattern(ctx)
loc = new(Locals)
)

pass, err := s.p.p.Patterns(group(ctx, "pass"), s.Pass)
pre, err := s.p.MakeSensor(ctx, &s.p.Config.Pre, loc.opts()...)
if err != nil {
return errors.New("failed to parse pass pattern: %w", err)
return errors.New("failed to make pre sensor: %w", err)
}

fail, err := s.p.p.Patterns(group(ctx, "fail"), s.Fail)
sns, err := s.p.MakeSensor(ctx, &s.Step, loc.opts()...)
if err != nil {
return errors.New("failed to parse fail pattern: %w", err)
return errors.New("failed to make sensor: %w", err)
}

inactive := time.NewTimer(s.it)
Expand All @@ -224,36 +222,25 @@ func (s *Step) Run(ctx context.Context, c *check.S) error {

obj := msg.Object()

match, err := match.Match(group(ctxt, "match"), obj)
ok, err := pre.Do(ctxt, obj)
if err != nil {
return errors.New("failed to match on pattern: %w", err)
return errors.New("failed to match pre sensor: %w", err)
}

if !match {
if !ok {
if wg, ok := msg.(WaitMessage); ok {
wg.Done(false)
}
continue
}

fail, err := fail.Match(group(ctxt, "fail"), obj)
if err != nil {
return errors.New("failed to match fail pattern: %w", err)
}
if fail {
c.Fail()
return errors.New("failure pattern matched")
}

pass, err := pass.Match(group(ctxt, "pass"), obj)
pass, err := sns.Do(ctxt, obj)
if err != nil {
return errors.New("failed to match ok pattern: %w", err)
return errors.New("failed to match sensor: %w", err)
}
if wg, ok := msg.(WaitMessage); ok {
wg.Done(pass)
}
if pass {
c.OK()
return nil
}
}
Expand Down
91 changes: 91 additions & 0 deletions pkg/plugin/builtin/event/sensor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package event

import (
"context"
"text/template"

"hookt.dev/cmd/pkg/async"
"hookt.dev/cmd/pkg/errors"
"hookt.dev/cmd/pkg/plugin/builtin/event/wire"
"hookt.dev/cmd/pkg/proto"
)

type Locals struct {
async.Map
}

func (l *Locals) setlocal(name string, value any) any {
l.Map.Store(name, value)
return value
}

func (l *Locals) getlocal(name string) any {
value, _ := l.Map.Load(name)
return value
}

func (l *Locals) opts() []proto.TOption {
return []proto.TOption{
func(t *template.Template) *template.Template {
return t.Funcs(template.FuncMap{
"setlocal": l.setlocal,
"local": l.getlocal,
})
},
}
}

type Sensor struct {
Match proto.Patterns
Pass proto.Patterns
Fail proto.Patterns
}

func (p *Plugin) MakeSensor(ctx context.Context, step *wire.Step, opts ...proto.TOption) (*Sensor, error) {
var (
s Sensor
err error
)

s.Match, err = p.p.Patterns(group(ctx, "match"), step.Match, opts...)
if err != nil {
return nil, errors.New("failed to parse match pattern: %w", err)
}

s.Fail, err = p.p.Patterns(group(ctx, "fail"), step.Fail, opts...)
if err != nil {
return nil, errors.New("failed to parse fail pattern: %w", err)
}

s.Pass, err = p.p.Patterns(group(ctx, "pass"), step.Pass, opts...)
if err != nil {
return nil, errors.New("failed to parse pass pattern: %w", err)
}

return &s, nil
}

func (s *Sensor) Do(ctx context.Context, obj any) (bool, error) {
match, err := s.Match.Match(group(ctx, "match"), obj)
if err != nil {
return false, errors.New("failed to match on pattern: %w", err)
}
if !match {
return false, nil
}

fail, err := s.Fail.Match(group(ctx, "fail"), obj)
if err != nil {
return false, errors.New("failed to match fail pattern: %w", err)
}
if fail && len(s.Fail) != 0 {
return false, errors.New("failure pattern matched")
}

pass, err := s.Pass.Match(group(ctx, "pass"), obj)
if err != nil {
return false, errors.New("failed to match ok pattern: %w", err)
}

return pass, nil
}
1 change: 1 addition & 0 deletions pkg/plugin/builtin/event/wire/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Config struct {
Mode string `json:"mode,omitempty"`
Timeout string `json:"timeout,omitempty"`
InactiveTimeout string `json:"inactive_timeout,omitempty"`
Pre Step `json:"pre,omitempty"`
}

func (c Config) GetTimeout() time.Duration {
Expand Down
7 changes: 4 additions & 3 deletions pkg/proto/pattern.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,18 @@ func (p Patterns) Match(ctx context.Context, obj any) (bool, error) {
}
}

return len(p) != 0, nil
return true, nil
}

func pattern(ctx context.Context, name string) context.Context {
return trace.With(ctx, "pattern", name)
}

func (p *P) Patterns(ctx context.Context, obj wire.Object) (Patterns, error) {
func (p *P) Patterns(ctx context.Context, obj wire.Object, opts ...TOption) (Patterns, error) {
var (
pt = make(Patterns, 0, len(obj))
tr = trace.ContextPattern(ctx)
t = p.t.With(opts...)
err error
)

Expand Down Expand Up @@ -104,7 +105,7 @@ func (p *P) Patterns(ctx context.Context, obj wire.Object) (Patterns, error) {
return ok, nil
}
case string:
q.Match = p.t.Match(ctx, want)
q.Match = t.Match(ctx, want)
default:
q.Match = func(_ context.Context, got any) (bool, error) {
ok := cmpEqual(want, got)
Expand Down
2 changes: 1 addition & 1 deletion pkg/proto/proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ type P struct {

func New(opts ...func(*P)) *P {
p := &P{
t: &T{},
t: NewT(),
m: make(map[string]Interface),
}
for _, opt := range opts {
Expand Down
24 changes: 19 additions & 5 deletions pkg/proto/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"math/rand"
"os"
"slices"
"strings"
"text/template"

Expand All @@ -20,7 +21,13 @@ type TOption func(*template.Template) *template.Template

type T struct {
Options []TOption
Vars async.Map
Vars *async.Map
}

func NewT() *T {
return &T{
Vars: &async.Map{},
}
}

func (p *P) Evaluate(tmpl string, data any) ([]byte, error) {
Expand All @@ -38,6 +45,13 @@ func (p *P) Evaluate(tmpl string, data any) ([]byte, error) {
return buf.Bytes(), nil
}

func (t *T) With(opts ...TOption) *T {
return &T{
Options: append(slices.Clone(t.Options), opts...),
Vars: t.Vars,
}
}

func (t *T) Parse(name, data string) (*template.Template, error) {
tmpl := template.New(name).
Funcs(sprig.FuncMap()).
Expand All @@ -55,9 +69,9 @@ func (t *T) Parse(name, data string) (*template.Template, error) {
func (t *T) funcs() template.FuncMap {
return map[string]any{
"xrand": xrand,
"setvar": t.set,
"setvar": t.setvar,
"seterror": t.seterror,
"var": t.get,
"var": t.getvar,
"setenv": os.Setenv,
"env": os.Getenv,
}
Expand Down Expand Up @@ -102,12 +116,12 @@ func (t *T) Match(ctx context.Context, data string) func(context.Context, any) (
}
}

func (t *T) set(name string, value any) any {
func (t *T) setvar(name string, value any) any {
t.Vars.Store(name, value)
return value
}

func (t *T) get(name string) any {
func (t *T) getvar(name string) any {
value, _ := t.Vars.Load(name)
return value
}
Expand Down

0 comments on commit 5812f4e

Please sign in to comment.