-
Notifications
You must be signed in to change notification settings - Fork 5
/
ir_workflowservice.go
153 lines (120 loc) · 4.48 KB
/
ir_workflowservice.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package workflow
import (
"fmt"
"strings"
"github.com/blueprint-uservices/blueprint/blueprint/pkg/coreplugins/service"
"github.com/blueprint-uservices/blueprint/blueprint/pkg/ir"
"github.com/blueprint-uservices/blueprint/plugins/golang"
"github.com/blueprint-uservices/blueprint/plugins/golang/gogen"
"github.com/blueprint-uservices/blueprint/plugins/workflow/workflowspec"
"golang.org/x/exp/slog"
)
// This Node represents a Golang Workflow spec service in the Blueprint IR.
type workflowNode struct {
// IR node types
golang.Service
InstanceName string // Name of this instance
ServiceType string // The short-name serviceType used to initialize this workflow service
// Details of the service, including its interface and constructor
ServiceInfo *workflowspec.Service
}
// The client-side of a workflow service
type workflowClient struct {
workflowNode
Wrapped ir.IRNode // The next client
}
// The server-side of a workflow service
type workflowHandler struct {
workflowNode
// IR Nodes of arguments that will be passed in to the generated code
Args []ir.IRNode
}
func initWorkflowNode[ServiceType any](n *workflowNode, name string) (err error) {
n.InstanceName = name
n.ServiceInfo, err = workflowspec.GetService[ServiceType]()
if err != nil {
return err
}
n.ServiceType = n.ServiceInfo.Iface.Name
return nil
}
func (node *workflowNode) Name() string {
return node.InstanceName
}
func (node *workflowNode) GetInterface(ctx ir.BuildContext) (service.ServiceInterface, error) {
return node.ServiceInfo.Iface.ServiceInterface(ctx), nil
}
// Both the client and the handler need to add interfaces to modules that use them.
func (node *workflowNode) AddInterfaces(builder golang.ModuleBuilder) error {
return node.ServiceInfo.AddToModule(builder)
}
// Client and handler side both need to add the service interface to the output
func (node *workflowNode) AddToWorkspace(builder golang.WorkspaceBuilder) error {
return golang.AddToWorkspace(builder, node.ServiceInfo.Iface.File.Package.Module)
}
// The handler node needs to add the constructor package to the output
func (node *workflowHandler) AddToWorkspace(builder golang.WorkspaceBuilder) error {
return node.ServiceInfo.AddToWorkspace(builder)
}
func (node *workflowHandler) AddInstantiation(builder golang.NamespaceBuilder) error {
// Only generate instantiation code for this instance once
if builder.Visited(node.InstanceName) {
return nil
}
slog.Info(fmt.Sprintf("Instantiating %v %v in %v/%v", node.ServiceType, node.InstanceName, builder.Info().Package.PackageName, builder.Info().FileName))
return builder.DeclareConstructor(node.InstanceName, node.ServiceInfo.Constructor.AsConstructor(), node.Args)
}
type workflowClientTemplateArgs struct {
ServiceType string
WrappedName string
}
func (node *workflowClient) AddInstantiation(builder golang.NamespaceBuilder) error {
// Only generate instantiation code for this instance once
if builder.Visited(node.InstanceName) {
return nil
}
template := `func(n *golang.Namespace) (any, error) {
// Auto-generated by the golang plugin workflow/ir_workflowservice.go
var client {{.ServiceType}}
err := n.Get("{{.WrappedName}}", &client)
return client, err
}`
templateArgs := &workflowClientTemplateArgs{
ServiceType: builder.ImportType(node.ServiceInfo.Iface.Type()),
WrappedName: node.Wrapped.Name(),
}
// template := fmt.Sprintf(`func(n *golang.Namespace) (any, error) {
// // Auto-generated by the golang plugin workflow/ir_workflowservice.go
// var client any
// return n.Get("%s")
// }`, node.Wrapped.Name())
slog.Info(fmt.Sprintf("Instantiating %v %v in %v/%v", node.ServiceType, node.InstanceName, builder.Info().Package.PackageName, builder.Info().FileName))
code, err := gogen.ExecuteTemplate("workflowClient.AddInstantiation", template, templateArgs)
if err != nil {
return err
}
return builder.Declare(node.InstanceName, code)
}
func (n *workflowClient) String() string {
var b strings.Builder
b.WriteString(n.InstanceName)
b.WriteString(" = ")
b.WriteString(n.Wrapped.Name())
return b.String()
}
func (n *workflowHandler) String() string {
var b strings.Builder
b.WriteString(n.InstanceName)
b.WriteString(" = ")
b.WriteString(n.ServiceInfo.Iface.Name)
var args []string
for _, arg := range n.Args {
args = append(args, arg.Name())
}
b.WriteString("(")
b.WriteString(strings.Join(args, ", "))
b.WriteString(")")
return b.String()
}
func (node *workflowNode) ImplementsGolangNode() {}
func (node *workflowNode) ImplementsGolangService() {}