-
Notifications
You must be signed in to change notification settings - Fork 280
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
Untangle external reader code #776
base: main
Are you sure you want to change the base?
Conversation
import org.pkl.core.evaluatorSettings.PklEvaluatorSettings | ||
import org.pkl.core.externalreader.ModuleReaderSpec | ||
import org.pkl.core.externalreader.ReaderProcess | ||
import org.pkl.core.externalreader.ResourceReaderSpec |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that the resolver types are shared between the client readers and external readers, is org.pkl.core.externalreader really the right place for these types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
org.pkl.server
depending on externalreader
seems acceptable to me. These types couldn't stay in module
/resource
because that creates package cycles and is a layering violation: module
/resource
already export packagereader.ReaderProcess
, hence packagereader
shouldn't also depend on them.
pkl-core has serious modularity issues. I just tried to do some damage control in the few hours I had. I think I made a step in the right direction; perhaps you guys will find further improvements.
Thanks for the PR, and appreciate the help straightening this out! FYI--this is a little late to get into the 0.27 release. However, we can get this into the main branch once this release is out. We can also take some time to better look at the API of pkl-core and have a clear definition of what's public and what's not (and perhaps use JPMS). |
Just keep in mind that this PR makes breaking changes to APIs introduced in 0.27.
I'd appreciate this. It will likely take quite a while until pkl-core is ready for JPMS. But we can take one step at a time: define which packages are public, enforce at build time that they don't export private packages, etc. |
For the next release, could we create a release branch at least one week before the release, and merge only bugfixes from then on? |
Yeah, we should definitely add some more process here, including cut-off for features. We'll figure out what that should look like after we get 0.27 out and into the world. Apologies for the lack of structure right now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of these changes look good! Although, I think let's undo some of the name changes here.
import org.pkl.core.util.Nullable; | ||
|
||
/** An external process that reads Pkl modules and resources. */ | ||
public interface ExternalReaderProcess extends AutoCloseable { | ||
public interface ReaderProcess extends AutoCloseable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a public API as of 0.27, so, let's just keep the name as-is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume you mean just this interface? (There are quite a few breaking changes in this PR.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, the name of this interface!
return new Proxy(addressUri, noProxy); | ||
} | ||
|
||
@SuppressWarnings("unchecked") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either undo this change, or re-add and deprecate.
But, I think it's fine to just keep this method around; we don't gain much by inlining this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The motivation is to remove a method from the public API that doesn't belong there. I can add it back as deprecated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I don't fully understand; what makes Proxy.create()
not belong here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, my impression was that Proxy.create()
is an internal method used by Proxy.parse()
that accidentally became a public API.
I feel that regular Java code should just use new Proxy(new URI(...))
or new Proxy(URI.create(...))
. These will also throw more appropriate exceptions than PklException
, which is mainly thrown by the evaluator and doesn't seem ideal for regular Java APIs that don't evaluate Pkl code.
One more thing I noticed is that similar classes such as Release
and PklInfo
use java.lang.String
for pkl.base.Uri
. (They also don't have their own package.) A potential problem with using java.net.URI
for pkl.base.Uri
is that valid Pkl objects can't be represented in Java.
String scheme(); | ||
public interface ModuleResolver { | ||
static ModuleResolver of(MessageTransport transport, long evaluatorId) { | ||
return new ModuleResolverImpl(transport, evaluatorId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There aren't any layering violations here, are there?
Since we've now shipped this in 0.27, I think let's keep this as-is, and have org.pkl.core.externalreader.ModuleReaderSpec
implement interface Spec
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ModuleReaderSpec
is a simple record, and callers of ModuleKeys.externalResolver
may need to instantiate it.
I think the ModuleResolver.Spec
interface has no value (at least not anymore) and just obfuscates the public API.
This PR already makes breaking API changes. If it's important to make this particular change less breaking, record ModuleReaderSpec
could be renamed to ModuleResolver.Spec
. However, I doubt this trade of breaking changes has much benefit.
I prefer the name ModuleReaderSpec
over ModuleResolver.Spec
because it makes more sense in the ReaderProcess
interface:
interface ReaderProcess {
// used to return ModuleResolver.Spec, which I found confusing
ModuleReaderSpec getModuleReaderSpec(String scheme) throws IOException;
// used to return ResourceResolver.Spec, which I found confusing
ResourceReaderSpec getResourceReaderSpec(String scheme) throws IOException;
}
String scheme(); | ||
public interface ResourceResolver { | ||
static ResourceResolver of(MessageTransport transport, long evaluatorId) { | ||
return new ResourceResolverImpl(transport, evaluatorId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment; let's keep this class as-is, and have ResourceReaderSpec
implement this interface
- move the following classes into package externalreader: - ExternalModuleResolver - ExternalResourceResolver - MessageTransportModuleResolver (renamed to ExternalModuleResolverImpl, made package-private) - MessageTransportResourceResolver (renamed to ExternalResourceResolverImpl, made package-private) - replace interface ExternalModuleResolver.Spec with record ExternalModuleReaderSpec - replace interface ExternalResourceResolver.Spec with record ExternalResourceReaderSpec - translate between messaging.ResourceReaderSpec and ExternalResourceReaderSpec (eliminates dependency from messaging on higher layer) - translate between messaging.ResourceResolverSpec and ExternalResourceResolverSpec (eliminates dependency from messaging on higher layer) - add ServerMessages.ExternalReader and translate between this message component and the PklEvaluatorSettings.ExternalReader API - add ServerMessages.Proxy and translate between this message component and the PklEvaluatorSettings.Proxy API - change type of CreateEvaluatorRequest.allowedModules/allowedResources from List<Pattern>? to List<String>? - removes a lot of code - should not need to create a Pattern object to send a message - remove public method evaluatorSettings.PklEvaluatorSettings.Proxy.create() - only seems useful internally, inlined
- class names were too long/repetitive - package name provides sufficient context
See commit messages for details. Second commit is a pure rename refactoring.