Skip to content

Commit a773d5d

Browse files
committed
refactor: move SigChecker,Guard to dsl/ops/util package
1 parent 538dc42 commit a773d5d

File tree

6 files changed

+83
-65
lines changed

6 files changed

+83
-65
lines changed

dsl/ops/func_do.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package ops
33
import (
44
"context"
55

6+
"github.com/vim-volt/volt/dsl/ops/util"
67
"github.com/vim-volt/volt/dsl/types"
78
)
89

@@ -30,7 +31,7 @@ func (*doOp) Bind(args ...types.Value) (*types.Expr, error) {
3031
for i := 0; i < len(args); i++ {
3132
sig = append(sig, types.AnyValue)
3233
}
33-
if err := signature(sig...).check(args); err != nil {
34+
if err := util.Signature(sig...).Check(args); err != nil {
3435
return nil, err
3536
}
3637
retType := args[len(args)-1].Type()
@@ -50,15 +51,15 @@ func (*doOp) InvertExpr(args []types.Value) (types.Value, error) {
5051
}
5152

5253
func (*doOp) Execute(ctx context.Context, args []types.Value) (val types.Value, rollback func(), err error) {
53-
g := funcGuard(DoOp.String())
54-
defer func() { err = g.rollback(recover()) }()
55-
rollback = g.rollbackForcefully
54+
g := util.FuncGuard(DoOp.String())
55+
defer func() { err = g.Rollback(recover()) }()
56+
rollback = g.RollbackForcefully
5657

5758
for i := range args {
5859
v, rbFunc, e := args[i].Eval(ctx)
59-
g.add(rbFunc)
60+
g.Add(rbFunc)
6061
if e != nil {
61-
err = g.rollback(e)
62+
err = g.Rollback(e)
6263
return
6364
}
6465
val = v

dsl/ops/guard.go

Lines changed: 0 additions & 54 deletions
This file was deleted.

dsl/ops/macro_eval.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package ops
33
import (
44
"context"
55

6+
"github.com/vim-volt/volt/dsl/ops/util"
67
"github.com/vim-volt/volt/dsl/types"
78
)
89

@@ -27,7 +28,7 @@ func (*evalOp) Bind(args ...types.Value) (*types.Expr, error) {
2728
}
2829

2930
func (*evalOp) Execute(ctx context.Context, args []types.Value) (types.Value, func(), error) {
30-
if err := signature(types.AnyValue).check(args); err != nil {
31+
if err := util.Signature(types.AnyValue).Check(args); err != nil {
3132
return nil, NoRollback, err
3233
}
3334
return args[0].Eval(context.Background())

dsl/ops/macro_invert.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package ops
33
import (
44
"context"
55

6+
"github.com/vim-volt/volt/dsl/ops/util"
67
"github.com/vim-volt/volt/dsl/types"
78
)
89

@@ -27,7 +28,7 @@ func (*invertOp) Bind(args ...types.Value) (*types.Expr, error) {
2728
}
2829

2930
func (*invertOp) Execute(ctx context.Context, args []types.Value) (types.Value, func(), error) {
30-
if err := signature(types.AnyValue).check(args); err != nil {
31+
if err := util.Signature(types.AnyValue).Check(args); err != nil {
3132
return nil, NoRollback, err
3233
}
3334
val, err := args[0].Invert()

dsl/ops/util/guard.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package util
2+
3+
import (
4+
"fmt"
5+
"github.com/pkg/errors"
6+
)
7+
8+
// Guard invokes "rollback functions" if Rollback method received non-nil value
9+
// (e.g. recover(), non-nil error).
10+
type Guard interface {
11+
// Rollback rolls back if v is non-nil.
12+
//
13+
// defer func() { err = g.Rollback(recover()) }()
14+
//
15+
// // or
16+
//
17+
// if e != nil {
18+
// err = g.Rollback(e)
19+
// err = g.Rollback(e) // this won't call rollback functions twice!
20+
// return
21+
// }
22+
Rollback(v interface{}) error
23+
24+
// RollbackForcefully calls rollback functions in reversed order
25+
RollbackForcefully()
26+
27+
// Add adds given rollback functions
28+
Add(f func())
29+
}
30+
31+
// FuncGuard returns Guard instance for function
32+
func FuncGuard(name string) Guard {
33+
return &guard{errMsg: fmt.Sprintf("function \"%s\" has an error", name)}
34+
}
35+
36+
type guard struct {
37+
errMsg string
38+
rbFuncs []func()
39+
}
40+
41+
func (g *guard) Rollback(v interface{}) error {
42+
var err error
43+
if e, ok := v.(error); ok {
44+
err = e
45+
} else if v != nil {
46+
err = fmt.Errorf("%s", v)
47+
}
48+
if err != nil {
49+
g.RollbackForcefully()
50+
}
51+
return errors.Wrap(err, g.errMsg)
52+
}
53+
54+
func (g *guard) RollbackForcefully() {
55+
for i := len(g.rbFuncs) - 1; i >= 0; i-- {
56+
g.rbFuncs[i]()
57+
}
58+
g.rbFuncs = nil // do not rollback twice
59+
}
60+
61+
func (g *guard) Add(f func()) {
62+
g.rbFuncs = append(g.rbFuncs, f)
63+
}

dsl/ops/sigcheck.go renamed to dsl/ops/util/sigcheck.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
1-
package ops
1+
package util
22

33
import (
44
"fmt"
55

66
"github.com/vim-volt/volt/dsl/types"
77
)
88

9-
func signature(argTypes ...types.Type) *sigChecker {
9+
// SigChecker checks if the type of args met given types to Signature()
10+
type SigChecker interface {
11+
Check(args []types.Value) error
12+
}
13+
14+
// Signature returns SigChecker for given types
15+
func Signature(argTypes ...types.Type) SigChecker {
1016
return &sigChecker{argTypes: argTypes}
1117
}
1218

1319
type sigChecker struct {
1420
argTypes []types.Type
1521
}
1622

17-
func (sc *sigChecker) check(args []types.Value) error {
23+
func (sc *sigChecker) Check(args []types.Value) error {
1824
if len(args) != len(sc.argTypes) {
1925
return fmt.Errorf("expected %d arity but got %d", len(sc.argTypes), len(args))
2026
}

0 commit comments

Comments
 (0)