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

Remove usages of ComponentResolveMetadata #29123

Merged
merged 3 commits into from
May 15, 2024

Conversation

jvandort
Copy link
Member

The primary motivation here is to simplify LocalComponentMetadata (now renamed to LocalComponentGraphResolveMetadata), by reducing the type hierarchy. This will make it much easier to heavily modify the way local component metadata works.

ComponentResolveMetadata was a legacy type, previously used to represent a component when resolving artifacts. Now, the modern type, ComponentArtifactResolveMetadata, has been propagated to all prior places that used the legacy type.

All methods on the removed type have been moved to its remaining subinterface, ExternalComponentResolveMetadata. This subinterface is not heavily used, but removing it would cause more work than was desired for this change.

Reviewing cheatsheet

Before merging the PR, comments starting with

  • ❌ ❓must be fixed
  • 🤔 💅 should be fixed
  • 💭 may be fixed
  • 🎉 celebrate happy things

@jvandort jvandort self-assigned this May 13, 2024
@jvandort jvandort added this to the 8.9 RC1 milestone May 13, 2024
@jvandort jvandort force-pushed the jvandort/dm/delete-component-resolve-metadata branch from db2c87a to 54f5e71 Compare May 14, 2024 13:26
@jvandort
Copy link
Member Author

@bot-gradle test this

@bot-gradle
Copy link
Collaborator

I've triggered the following builds for you. Click here to see all build failures.

@jvandort jvandort marked this pull request as ready for review May 14, 2024 14:06
@jvandort jvandort requested review from a team as code owners May 14, 2024 14:06
@jvandort jvandort requested review from big-guy, bamboo, abstratt and tresat and removed request for a team and big-guy May 14, 2024 14:06
Copy link
Member

@tresat tresat left a comment

Choose a reason for hiding this comment

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

Overall seems good to me, I flagged some small problems and potential improvements.

Also: should ModuleComponentGraphResolveState#getModuleResolveMetadata() be @Deprecated as part of this?

Comment on lines 40 to 45
if (metadata instanceof IvyModuleResolveMetadata) {
IvyModuleResolveMetadata ivyMetadata = (IvyModuleResolveMetadata) metadata;
return new DefaultIvyComponentGraphResolveState(idGenerator.nextComponentId(), ivyMetadata, attributeDesugaring, idGenerator);
}

return new DefaultModuleComponentGraphResolveState(idGenerator.nextComponentId(), metadata, attributeDesugaring, idGenerator);
Copy link
Member

Choose a reason for hiding this comment

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

🤔 This seems backwards from an OOP point of view.

Why not:

public ModuleComponentGraphResolveState stateFor(ModuleComponentResolveMetadata metadata) {
   return metadata.buildResolveState(idGenerator, attributeDesugaring);
}

Copy link
Member Author

Choose a reason for hiding this comment

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

The intention is that the State types are mutable/stateful and track all the data for a given component while the Metadata types are fully immutable and track a subset of data for a given component.

Each component should have one state type, but that state type may track multiple metadata types as the state changes (we may learn about a component's variants through different network requests/operations compared to its artifacts). In that case we would have a metadata for the artifacts, a metadata for the variants, and some base metadata that describes the identity of the components and some other basic stuff that we know up-front about it.

Currently for external module components (and local components -- but I am working to change that), the Metadata type (ModuleComponentResolveMetadata in this file) is stateful and has a lot of logic that the State type that wraps it should do.

The point that I'm trying to make here is that the State type should be "in charge" of the Metadata type. It feels wrong to me for the metadata type to construct a state type for itself.

Copy link
Member

Choose a reason for hiding this comment

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

OK, I see your point. Can you add some of that to the Javadoc on this factory?

*
* @return Null if the configuration does not exist.
*/
@Nullable
Copy link
Member

Choose a reason for hiding this comment

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

❓ Why return null here? From the callers, looks like an empty list could signal just as well. Otherwise, there's Optional, which would even allow a slight simplification of the calling code via ifPresent.

Copy link
Member Author

Choose a reason for hiding this comment

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

I worry there is a slight difference between a Configuration existing with no artifacts and a configuration not existing. There is a lot of logic related to caching and stuff around here that I am not familiar with and would rather not subtly change.

Specifically, this method is called by resolveJavadocArtifacts and resolveSourceArtifacts. In the prior code it only called resolved if the configuration exists -- regardless if that configuration had artifacts or not.

Using an empty list instead of null (or optional) would mean we call resolved if there was a configuration AND it had artifacts.

Copy link
Member

Choose a reason for hiding this comment

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

Optional with ifPresent then to remove the null. I know you like functional coding paradigms. 😄

Comment on lines 44 to 52
@Override
public ModuleComponentResolveMetadata getModuleResolveMetadata() {
return getMetadata();
}

@Override
public IvyComponentArtifactResolveMetadata getResolveMetadata() {
return new DefaultIvyComponentArtifactResolveMetadata(getArtifactMetadata());
}
Copy link
Member

Choose a reason for hiding this comment

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

💭 This bit is quite confusing. I don't have any concrete suggestions to improve it, just a lot of different kinds of metadata in play.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah I 100% agree there are way too many interfaces involved here. This whole part of the code is in a middle-ground state right now and this change hopes to be a small part of that.

In practice, it makes sense to have a different metadata/state type for ivy components compared to other components, because ivy components have configurations -- while other components do not (local Gradle components do have configurations for now, but this PR is the start of the work to remove the concept of configurations from local components from a DM perspective).

Copy link
Member

Choose a reason for hiding this comment

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

I realize it's in an intermediate state and things will get better, but can anything be done to clarify the distinctions between these methods? Can the names be made more specific? If I'm a client trying to determine which of these methods I need to call, is there anyway other than trial-and-error to get it right?

The primary motivation here is to simplify LocalComponentMetadata (now renamed to LocalComponentGraphResolveMetadata),
by reducing the type hierarchy. This will make it much easier to heavily modify the way local component metadata works.

ComponentResolveMetadata was a legacy type, previously used to represent a component when resolving artifacts. Now,
the modern type, ComponentArtifactResolveMetadata, has been propogated to all prior places that used the legacy type.

All methods on the removed type have been moved to its remaining subinterface, ExternalComponentResolveMetadata. This
subinterface is not heavily used, but removing it would cause more work than was desired for this change.
@jvandort jvandort force-pushed the jvandort/dm/delete-component-resolve-metadata branch from 18a5a14 to 8333a20 Compare May 15, 2024 00:21
* ArtifactMetadata on the component graph resolve state and the module resolve metadata were always the same instance.
* Creating the new artifact metadata (ComponentArtifactResolveMetadata) relied on data from the legacy metadata anyways
* Remove getSources from graph state since ModuleSources exposes how to fetch artifacts. getSources already existed on the new artifact metadata
* Introduce missing ExternalComponentGraphResolveState interface
* Add javaodc, improve method names
@jvandort
Copy link
Member Author

@bot-gradle test this

@gradle gradle deleted a comment from jvandort May 15, 2024
@bot-gradle
Copy link
Collaborator

I've triggered the following builds for you. Click here to see all build failures.

@jvandort jvandort added this pull request to the merge queue May 15, 2024
Merged via the queue into master with commit e75d4fb May 15, 2024
58 checks passed
@jvandort jvandort deleted the jvandort/dm/delete-component-resolve-metadata branch May 15, 2024 19:57
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.

None yet

3 participants