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

[MRESOLVER-420] Cache prioritized components #348

Merged
merged 5 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,21 @@ public final class ConfigurationProperties {
*/
public static final boolean DEFAULT_IMPLICIT_PRIORITIES = false;

/**
* A flag indicating whether the created ordered components should be cached or not.
*
* @see #DEFAULT_CACHED_PRIORITIES
* @since TBD
*/
public static final String CACHED_PRIORITIES = PREFIX_PRIORITY + "cached";

/**
* The default caching of priority components if {@link #CACHED_PRIORITIES} isn't set. Default value is {@code true}.
*
* @since TBD
*/
public static final boolean DEFAULT_CACHED_PRIORITIES = true;

/**
* A flag indicating whether interaction with the user is allowed.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ private DeployResult deploy(SyncContext syncContext, RepositorySystemSession ses
private List<? extends MetadataGenerator> getMetadataGenerators(
RepositorySystemSession session, DeployRequest request) {
PrioritizedComponents<MetadataGeneratorFactory> factories =
Utils.sortMetadataGeneratorFactories(session, this.metadataFactories.values());
Utils.sortMetadataGeneratorFactories(session, metadataFactories);

List<MetadataGenerator> generators = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ private InstallResult install(SyncContext syncContext, RepositorySystemSession s
private List<? extends MetadataGenerator> getMetadataGenerators(
RepositorySystemSession session, InstallRequest request) {
PrioritizedComponents<MetadataGeneratorFactory> factories =
Utils.sortMetadataGeneratorFactories(session, this.metadataFactories.values());
Utils.sortMetadataGeneratorFactories(session, metadataFactories);

List<MetadataGenerator> generators = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,9 @@ public LocalRepositoryManager newLocalRepositoryManager(RepositorySystemSession
throws NoLocalRepositoryManagerException {
requireNonNull(session, "session cannot be null");
requireNonNull(repository, "repository cannot be null");
PrioritizedComponents<LocalRepositoryManagerFactory> factories = new PrioritizedComponents<>(session);
for (LocalRepositoryManagerFactory factory : this.localRepositoryManagerFactories.values()) {
factories.add(factory, factory.getPriority());
}

PrioritizedComponents<LocalRepositoryManagerFactory> factories = PrioritizedComponents.reuseOrCreate(
session, localRepositoryManagerFactories, LocalRepositoryManagerFactory::getPriority);

List<NoLocalRepositoryManagerException> errors = new ArrayList<>();
for (PrioritizedComponent<LocalRepositoryManagerFactory> factory : factories.getEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,10 @@ public RepositoryConnector newRepositoryConnector(RepositorySystemSession sessio
}
}

RemoteRepositoryFilter filter = remoteRepositoryFilterManager.getRemoteRepositoryFilter(session);

PrioritizedComponents<RepositoryConnectorFactory> factories = new PrioritizedComponents<>(session);
for (RepositoryConnectorFactory factory : this.connectorFactories.values()) {
factories.add(factory, factory.getPriority());
}
PrioritizedComponents<RepositoryConnectorFactory> factories = PrioritizedComponents.reuseOrCreate(
session, connectorFactories, RepositoryConnectorFactory::getPriority);

RemoteRepositoryFilter filter = remoteRepositoryFilterManager.getRemoteRepositoryFilter(session);
List<NoRepositoryConnectorException> errors = new ArrayList<>();
for (PrioritizedComponent<RepositoryConnectorFactory> factory : factories.getEnabled()) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,8 @@ public RepositoryLayout newRepositoryLayout(RepositorySystemSession session, Rem
requireNonNull(session, "session cannot be null");
requireNonNull(repository, "remote repository cannot be null");

PrioritizedComponents<RepositoryLayoutFactory> factories = new PrioritizedComponents<>(session);
for (RepositoryLayoutFactory factory : this.layoutFactories.values()) {
factories.add(factory, factory.getPriority());
}
PrioritizedComponents<RepositoryLayoutFactory> factories =
PrioritizedComponents.reuseOrCreate(session, layoutFactories, RepositoryLayoutFactory::getPriority);

List<NoRepositoryLayoutException> errors = new ArrayList<>();
for (PrioritizedComponent<RepositoryLayoutFactory> factory : factories.getEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,8 @@ public Transporter newTransporter(RepositorySystemSession session, RemoteReposit
requireNonNull(session, "session cannot be null");
requireNonNull(repository, "repository cannot be null");

PrioritizedComponents<TransporterFactory> factories = new PrioritizedComponents<>(session);
for (TransporterFactory factory : this.transporterFactories.values()) {
factories.add(factory, factory.getPriority());
}
PrioritizedComponents<TransporterFactory> factories =
PrioritizedComponents.reuseOrCreate(session, transporterFactories, TransporterFactory::getPriority);

List<NoTransporterException> errors = new ArrayList<>();
for (PrioritizedComponent<TransporterFactory> factory : factories.getEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import org.eclipse.aether.ConfigurationProperties;
import org.eclipse.aether.RepositorySystemSession;
Expand All @@ -31,6 +32,36 @@
* Helps to sort pluggable components by their priority.
*/
final class PrioritizedComponents<T> {
/**
* Reuses or creates and stores (if session data does not contain yet) prioritized components under this key into
* given session. Same session is used to configure prioritized components.
* <p>
* The {@code components} are expected to be Sisu injected {@link Map<String, C>}-like component maps. There is a
* simple "change detection" in place, as injected maps are dynamic, they are atomically expanded or contracted
* as components are dynamically discovered or unloaded.
*
* @since TBD
*/
@SuppressWarnings("unchecked")
public static <C> PrioritizedComponents<C> reuseOrCreate(
RepositorySystemSession session, Map<String, C> components, Function<C, Float> priorityFunction) {
boolean cached = ConfigUtils.getBoolean(
session, ConfigurationProperties.DEFAULT_CACHED_PRIORITIES, ConfigurationProperties.CACHED_PRIORITIES);
if (cached) {
String key = PrioritizedComponents.class.getName() + ".pc" + Integer.toHexString(components.hashCode());
return (PrioritizedComponents<C>)
session.getData().computeIfAbsent(key, () -> create(session, components, priorityFunction));
} else {
return create(session, components, priorityFunction);
}
}

private static <C> PrioritizedComponents<C> create(
RepositorySystemSession session, Map<String, C> components, Function<C, Float> priorityFunction) {
PrioritizedComponents<C> newInstance = new PrioritizedComponents<>(session);
components.values().forEach(c -> newInstance.add(c, priorityFunction.apply(c)));
return newInstance;
}

private static final String FACTORY_SUFFIX = "Factory";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
Expand All @@ -39,12 +40,8 @@
final class Utils {

public static PrioritizedComponents<MetadataGeneratorFactory> sortMetadataGeneratorFactories(
RepositorySystemSession session, Collection<? extends MetadataGeneratorFactory> factories) {
PrioritizedComponents<MetadataGeneratorFactory> result = new PrioritizedComponents<>(session);
for (MetadataGeneratorFactory factory : factories) {
result.add(factory, factory.getPriority());
}
return result;
RepositorySystemSession session, Map<String, MetadataGeneratorFactory> factories) {
return PrioritizedComponents.reuseOrCreate(session, factories, MetadataGeneratorFactory::getPriority);
}

public static List<Metadata> prepareMetadata(
Expand Down
1 change: 1 addition & 0 deletions src/site/markdown/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Option | Type | Description | Default Value | Supports Repo ID Suffix
`aether.metadataResolver.threads` | int | Number of threads to use in parallel for resolving metadata. | `4` | no
`aether.offline.protocols` | String | Comma-separated list of protocols which are supposed to be resolved offline. | - | no
`aether.offline.hosts` | String | Comma-separated list of hosts which are supposed to be resolved offline. | - | no
`aether.priority.cached` | boolean | Whether the created ordered list of components should be cached (in session) or not. | `true` | no
`aether.priority.<class>` | float | The priority to use for a certain extension class. `class` can either be the fully qualified name or the simple name stands for fully qualified class name. If the class name ends with `Factory` that suffix could optionally be left out. | - | no
`aether.priority.implicit` | boolean | Flag indicating whether the priorities of pluggable extensions are implicitly given by their iteration order such that the first extension has the highest priority. If set, an extension's built-in priority as well as any corresponding `aether.priority.<class>` configuration properties are ignored when searching for a suitable implementation among the available extensions. This priority mode is meant for cases where the application will present/inject extensions in the desired search order. | `false` | no
`aether.remoteRepositoryFilter.groupId` | boolean | Enable `groupId` remote repository filter. | `false` | no
Expand Down
Loading