-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #117 from avaje/feature/extract-propertiesparser
Extract PropertiesParser (so that it is accessible to plugins)
- Loading branch information
Showing
21 changed files
with
393 additions
and
136 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 0 additions & 104 deletions
104
avaje-aws-appconfig/src/main/java/io/avaje/aws/appconfig/AppConfigPlugin.java
This file was deleted.
Oops, something went wrong.
4 changes: 2 additions & 2 deletions
4
...avaje/aws/appconfig/AppConfigFetcher.java → ...config/awsappconfig/AppConfigFetcher.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
142 changes: 142 additions & 0 deletions
142
avaje-aws-appconfig/src/main/java/io/avaje/config/awsappconfig/AwsAppConfigPlugin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package io.avaje.config.awsappconfig; | ||
|
||
import io.avaje.config.ConfigParser; | ||
import io.avaje.config.Configuration; | ||
import io.avaje.config.ConfigurationSource; | ||
|
||
import java.io.StringReader; | ||
import java.time.Instant; | ||
import java.util.Map; | ||
import java.util.concurrent.atomic.AtomicReference; | ||
import java.util.concurrent.locks.ReentrantLock; | ||
|
||
import static java.lang.System.Logger.Level.*; | ||
|
||
/** | ||
* Plugin that loads AWS AppConfig as Yaml or Properties. | ||
* <p> | ||
* By default, will periodically reload the configuration if it has changed. | ||
*/ | ||
public final class AwsAppConfigPlugin implements ConfigurationSource { | ||
|
||
private static final System.Logger log = System.getLogger("io.avaje.config.AwsAppConfig"); | ||
|
||
private Loader loader; | ||
|
||
@Override | ||
public void load(Configuration configuration) { | ||
if (!configuration.enabled("aws.appconfig.enabled", true)) { | ||
log.log(INFO, "AwsAppConfig plugin is disabled"); | ||
return; | ||
} | ||
loader = new Loader(configuration); | ||
loader.reload(); | ||
} | ||
|
||
@Override | ||
public void reload() { | ||
if (loader != null) { | ||
loader.reload(); | ||
} | ||
} | ||
|
||
static final class Loader { | ||
|
||
private final Configuration configuration; | ||
private final AppConfigFetcher fetcher; | ||
private final ConfigParser yamlParser; | ||
private final ConfigParser propertiesParser; | ||
private final ReentrantLock lock = new ReentrantLock(); | ||
private final AtomicReference<Instant> validUntil; | ||
private final long nextRefreshSeconds; | ||
|
||
private String currentVersion = "none"; | ||
|
||
Loader(Configuration configuration) { | ||
this.validUntil = new AtomicReference<>(Instant.now().minusSeconds(1)); | ||
this.configuration = configuration; | ||
this.propertiesParser = configuration.parser("properties").orElseThrow(); | ||
this.yamlParser = configuration.parser("yaml").orElse(null); | ||
if (yamlParser == null) { | ||
log.log(WARNING, "No Yaml parser registered"); | ||
} | ||
|
||
var app = configuration.get("aws.appconfig.application"); | ||
var env = configuration.get("aws.appconfig.environment"); | ||
var con = configuration.get("aws.appconfig.configuration", env + "-" + app); | ||
|
||
this.fetcher = AppConfigFetcher.builder() | ||
.application(app) | ||
.environment(env) | ||
.configuration(con) | ||
.build(); | ||
|
||
boolean pollEnabled = configuration.enabled("aws.appconfig.poll.enabled", true); | ||
long pollSeconds = configuration.getLong("aws.appconfig.poll.seconds", 45L); | ||
this.nextRefreshSeconds = configuration.getLong("aws.appconfig.refresh.seconds", pollSeconds - 1); | ||
if (pollEnabled) { | ||
configuration.schedule(pollSeconds * 1000L, pollSeconds * 1000L, this::reload); | ||
} | ||
} | ||
|
||
void reload() { | ||
if (reloadRequired()) { | ||
performReload(); | ||
} | ||
} | ||
|
||
private boolean reloadRequired() { | ||
return validUntil.get().isAfter(Instant.now()); | ||
} | ||
|
||
private void performReload() { | ||
lock.lock(); | ||
try { | ||
if (!reloadRequired()) { | ||
return; | ||
} | ||
AppConfigFetcher.Result result = fetcher.fetch(); | ||
if (currentVersion.equals(result.version())) { | ||
log.log(TRACE, "AwsAppConfig unchanged, version {0}", currentVersion); | ||
} else { | ||
String contentType = result.contentType(); | ||
if (log.isLoggable(TRACE)) { | ||
log.log(TRACE, "AwsAppConfig fetched version:{0} contentType:{1} body:{2}", result.version(), contentType, result.body()); | ||
} | ||
Map<String, String> keyValues = parse(result); | ||
configuration.eventBuilder("AwsAppConfig") | ||
.putAll(keyValues) | ||
.publish(); | ||
currentVersion = result.version(); | ||
debugLog(result, keyValues.size()); | ||
} | ||
// move the next valid until time | ||
validUntil.set(Instant.now().plusSeconds(nextRefreshSeconds)); | ||
|
||
} catch (Exception e) { | ||
log.log(ERROR, "Error fetching or processing AwsAppConfig", e); | ||
} finally { | ||
lock.unlock(); | ||
} | ||
} | ||
|
||
private Map<String, String> parse(AppConfigFetcher.Result result) { | ||
ConfigParser parser = parser(result.contentType()); | ||
return parser.load(new StringReader(result.body())); | ||
} | ||
|
||
private ConfigParser parser(String contentType) { | ||
if (contentType.endsWith("yaml")) { | ||
return yamlParser; | ||
} else { | ||
return propertiesParser; | ||
} | ||
} | ||
|
||
private static void debugLog(AppConfigFetcher.Result result, int size) { | ||
if (log.isLoggable(DEBUG)) { | ||
log.log(DEBUG, "AwsAppConfig loaded version {0} with {1} properties", result.version(), size); | ||
} | ||
} | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
...vaje/aws/appconfig/DAppConfigFetcher.java → ...onfig/awsappconfig/DAppConfigFetcher.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 3 additions & 2 deletions
5
.../java/io/avaje/aws/appconfig/DResult.java → ...io/avaje/config/awsappconfig/DResult.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
import io.avaje.aws.appconfig.AppConfigPlugin; | ||
import io.avaje.config.awsappconfig.AwsAppConfigPlugin; | ||
|
||
module io.avaje.aws.appconfig { | ||
module io.avaje.config.awsappconfig { | ||
|
||
exports io.avaje.aws.appconfig; | ||
exports io.avaje.config.awsappconfig; | ||
|
||
requires io.avaje.config; | ||
requires java.net.http; | ||
provides io.avaje.config.ConfigurationSource with AppConfigPlugin; | ||
provides io.avaje.config.ConfigurationSource with AwsAppConfigPlugin; | ||
} |
2 changes: 1 addition & 1 deletion
2
avaje-aws-appconfig/src/main/resources/META-INF/services/io.avaje.config.ConfigurationSource
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
io.avaje.aws.appconfig.AppConfigPlugin | ||
io.avaje.config.awsappconfig.AwsAppConfigPlugin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
avaje-config/src/main/java/io/avaje/config/CoreComponents.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package io.avaje.config; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
final class CoreComponents { | ||
|
||
private final ModificationEventRunner runner; | ||
private final ConfigurationLog log; | ||
private final Parsers parsers; | ||
private final List<ConfigurationSource> sources; | ||
|
||
CoreComponents(ModificationEventRunner runner, ConfigurationLog log, Parsers parsers, List<ConfigurationSource> sources) { | ||
this.runner = runner; | ||
this.log = log; | ||
this.parsers = parsers; | ||
this.sources = sources; | ||
} | ||
|
||
CoreComponents() { | ||
this.runner = new CoreConfiguration.ForegroundEventRunner(); | ||
this.log = new DefaultConfigurationLog(); | ||
this.parsers = new Parsers(); | ||
this.sources = Collections.emptyList(); | ||
} | ||
|
||
Parsers parsers() { | ||
return parsers; | ||
} | ||
|
||
ConfigurationLog log() { | ||
return log; | ||
} | ||
|
||
ModificationEventRunner runner() { | ||
return runner; | ||
} | ||
|
||
List<ConfigurationSource> sources() { | ||
return sources; | ||
} | ||
} |
Oops, something went wrong.