[Core] Configuration IR Node
Currently, configuration of components is done by plugins in a relatively manual way, as described in #2
This issue proposes to introduce a configuration IRNode to Blueprint core. The IRNode would be similar to the Address IRNode, and it can either be used directly by plugins or extended.
Wiring and IR
The typical usage of a configuration IRNode would be to define the node at application scope. The configuration node can have a specific name that could either be given by the plugin opaquely, or explicitly given by the user (both are permissible). For example, for RPC timeout, a node would be created with a name "grpc.timeout" or something equivalent. Any other IRNode that depends on the configuration would have to Get the node.
Runtime
Namespace nodes would need to support config nodes in the generated code. Currently, namespace nodes must support the general idea of an argument being passed in, and the current implementation is simple -- it assumes anything passed in is (a) required; and (b) comes as a string:
func checkArg(name, value string) {
if value == "" {
slog.Error("No value set for required cmd line argument " + name)
os.Exit(1)
} else {
slog.Info(fmt.Sprintf("Arg %v = %v", name, value))
}
}
func main() {
a_grpc_addr := flag.String("a.grpc.addr", "", "Argument automatically generated from Blueprint IR: a.grpc.addr = GolangServerAddress()")
b_grpc_addr := flag.String("b.grpc.addr", "", "Argument automatically generated from Blueprint IR: b.grpc.addr = GolangServerAddress()")
flag.Parse()
checkArg("a.grpc.addr", *a_grpc_addr)
checkArg("b.grpc.addr", *b_grpc_addr)
graphArgs := map[string]string{
"a.grpc.addr": *a_grpc_addr,
"b.grpc.addr": *b_grpc_addr,
}
// .....
}
The code snippet above is generated by the goproc
plugin, and it would need to change in a couple of ways. During code generation, the plugin would typecheck all argNodes to see if they are of type configuration. If they are a configuration node, then they would be handled differently in the generated code. Unlike is currently implemented, a configuration node might be specified as required or optional (currently all args are required). And, it might be given a default value, which would be put into the flag.String
declaration (implying it is optional).
Special-casing
The above approach would enable us to selectively override configuration. For example, we could deploy all GRPC servers for all GRPC services with the same configuration value "grpc.timeout", but perhaps for a specific service "serviceB" we decide to deploy GRPC with a different timeout value, so we define a different configuration value "b.grpc.timeout".