-
Notifications
You must be signed in to change notification settings - Fork 21
/
service_recovering.go
108 lines (90 loc) · 3.19 KB
/
service_recovering.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package template
import (
"context"
. "github.com/dave/jennifer/jen"
mstrings "github.com/devimteam/microgen/generator/strings"
"github.com/devimteam/microgen/generator/write_strategy"
"github.com/vetcher/go-astra/types"
)
const (
serviceRecoveringStructName = "recoveringMiddleware"
)
var ServiceRecoveringMiddlewareName = mstrings.ToUpperFirst(serviceRecoveringStructName)
type recoverTemplate struct {
info *GenerationInfo
}
func NewRecoverTemplate(info *GenerationInfo) Template {
return &recoverTemplate{
info: info,
}
}
func (t *recoverTemplate) Render(ctx context.Context) write_strategy.Renderer {
f := NewFile("service")
f.ImportAlias(t.info.SourcePackageImport, serviceAlias)
f.HeaderComment(t.info.FileHeader)
f.Comment(ServiceRecoveringMiddlewareName + " recovers panics from method calls, writes to provided logger and returns the error of panic as method error.").
Line().Func().Id(ServiceRecoveringMiddlewareName).Params(Id(_logger_).Qual(PackagePathGoKitLog, "Logger")).Params(Id(MiddlewareTypeName)).
Block(t.newRecoverBody(t.info.Iface))
f.Line()
// Render type logger
f.Type().Id(serviceRecoveringStructName).Struct(
Id(_logger_).Qual(PackagePathGoKitLog, "Logger"),
Id(_next_).Qual(t.info.SourcePackageImport, t.info.Iface.Name),
)
// Render functions
for _, signature := range t.info.Iface.Methods {
f.Line()
f.Add(t.recoverFunc(ctx, signature)).Line()
}
return f
}
func (recoverTemplate) DefaultPath() string {
return filenameBuilder(PathService, "recovering")
}
func (t *recoverTemplate) Prepare(ctx context.Context) error {
return nil
}
func (t *recoverTemplate) ChooseStrategy(ctx context.Context) (write_strategy.Strategy, error) {
return write_strategy.NewCreateFileStrategy(t.info.OutputFilePath, t.DefaultPath()), nil
}
func (t *recoverTemplate) newRecoverBody(i *types.Interface) *Statement {
return Return(Func().Params(
Id(_next_).Qual(t.info.SourcePackageImport, i.Name),
).Params(
Qual(t.info.SourcePackageImport, i.Name),
).BlockFunc(func(g *Group) {
g.Return(Op("&").Id(serviceRecoveringStructName).Values(
Dict{
Id(_logger_): Id(_logger_),
Id(_next_): Id(_next_),
},
))
}))
}
func (t *recoverTemplate) recoverFunc(ctx context.Context, signature *types.Function) *Statement {
return methodDefinition(ctx, serviceRecoveringStructName, signature).
BlockFunc(t.recoverFuncBody(signature))
}
func (t *recoverTemplate) recoverFuncBody(signature *types.Function) func(g *Group) {
return func(g *Group) {
if !t.info.AllowedMethods[signature.Name] {
s := &Statement{}
if len(signature.Results) > 0 {
s.Return()
}
s.Id(rec(serviceRecoveringStructName)).Dot(_next_).Dot(signature.Name).Call(paramNames(signature.Args))
g.Add(s)
return
}
g.Defer().Func().Params().Block(
If(Id("r").Op(":=").Recover(), Id("r").Op("!=").Nil()).Block(
Id(rec(serviceRecoveringStructName)).Dot(_logger_).Dot("Log").Call(
Lit("method"), Lit(signature.Name),
Lit("message"), Id("r"),
),
Id(nameOfLastResultError(signature)).Op("=").Qual(PackagePathFmt, "Errorf").Call(Lit("%v"), Id("r")),
),
).Call()
g.Return().Id(rec(serviceRecoveringStructName)).Dot(_next_).Dot(signature.Name).Call(paramNames(signature.Args))
}
}