Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for Expression Resolver #143

Merged
merged 12 commits into from
Jan 25, 2023

Conversation

ankitk-me
Copy link
Contributor

fix #91

@ankitk-me ankitk-me self-assigned this Jan 9, 2023
@@ -99,7 +99,7 @@ public class EngineConfiguration extends Configuration
ENGINE_CREDITOR_CHILD_CLEANUP_LINGER_MILLIS = config.property("child.cleanup.linger", SECONDS.toMillis(5L));
ENGINE_VERBOSE = config.property("verbose", false);
ENGINE_WORKERS = config.property("workers", Runtime.getRuntime().availableProcessors());
ENGINE_CONFIG_SYNTAX_MUSTACHE = config.property("config.syntax.mustache", false);
ENGINE_CONFIG_SYNTAX_MUSTACHE = config.property("config.syntax.mustache", true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also rename this to something like config.resolve.expressions and change the constant name and method name accordingly.

for (String context: expressionResolver.names())
{
configText = expressionResolver.resolve(context, configText);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do this in a single pass instead of a loop, no need to pass each context separately.

public class EnvironmentResolverSpi implements ExpressionResolverSpi
{

private static final Pattern MUSTACHE_PATTERN = Pattern.compile("\\$\\{\\{\\s*env\\.([^\\s\\}]*)\\s*\\}\\}");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to EXPRESSION_PATTERN instead.

Also, this can be moved to the ExpressionResolver itself, match the pattern, extract the context, then use the appropriate ExpressionResolverSpi to resolve the value.

Each ExpressionResolverSpi implementation should be as simple as possible to avoid duplication when we extend to support more contexts.

return MUSTACHE_PATTERN
.matcher(config)
.replaceAll(r -> Optional.ofNullable(env.apply(r.group(1))).orElse(""));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation can simplify to return System.getenv(var); where the String parameter represents the variable name, such as SASL_USERNAME in env.SASL_USERNAME.

return resolverSpis.keySet();
}

public ExpressionResolver(Map<String, ExpressionResolverSpi> resolverSpis)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a private constructor so that only instantiate is used to create a new instance via service loader.

public Iterable<String> names()
{
return resolverSpis.keySet();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably don't need this one exposed externally as lookup is happening inside resolve(...).


public String resolve(
String name,
String config)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a single argument, config needed here.

Applying the pattern to the config allows us to find each occurrence of ${{ context.var }} and then lookup the resolver SPI for context to resolve var.

return resolverSpi.resolve(config);
}

private static ExpressionResolver instantiate(ServiceLoader<ExpressionResolverSpi> resolvers)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check your indentation of method parameters (all methods), single indent, next line per parameter.

{
String name();

String resolve(String config);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename config to var.

@@ -0,0 +1,9 @@
package io.aklivity.zilla.runtime.engine.resolver;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please refactor package name to io.aklivity.zilla.runtime.engine.expression instead.

Copy link
Contributor

@jfallows jfallows left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a replacement test for what used to be MustacheTest now ExpressionResolverTest to verify behavior.

See BindingFactoryTest as an example.

public String resolve(
String config)
{
return EXPRESSION_PATTERN.matcher(config)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of recreating the Matcher on every call to resolve(config), suggest instead creating the matcher via EXPRESSION_MATCHER.matcher("") in constructor, then matcher.reset(config).replaceAll(...) in resolve method.

Also suggest changing parameter names from config to template, since config is just one possible usage of this expression resolver.

String var)
{
UnaryOperator<String> env = System::getenv;
return Optional.ofNullable(env.apply(var)).orElse("");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid object allocation of Optional on each call to resolve.
Return null if not found, default to "" is happening at caller ExpressionResolver.
Simplify to return System.getenv(var);.

{
configText = expressionResolver.resolve(context, configText);
}
ExpressionResolver resolver = ExpressionResolver.instantiate();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this instantiation to the constructor, so it is done once, even when detecting changed configuration (later).

Suggest calling it expressions so the code reads as expressions.resolve(...).

public String resolve(
String var)
{
return "PASSWORD".equals(var) ? "ACTUALPASSWORD" : "";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though it's just a test implementation, let's return null instead of "" as the defaulting will happen at the ExpressionResolver instead.

jfallows
jfallows previously approved these changes Jan 13, 2023
@jfallows jfallows merged commit fea4c69 into aklivity:develop Jan 25, 2023
@ankitk-me ankitk-me deleted the resolverSupport branch January 30, 2023 15:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support {{ mustache }} syntax in zilla.json
2 participants