-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
ovsx-client: support multiple registries #12040
Conversation
47afd7a
to
88e688f
Compare
While there's benefits to having our main OpenVSX client do the routing between multiple registries, the "biggest" problem ended up to find a way to properly merge the search results, as the order somewhat matters. In its current shape this PR doesn't do a great merging job: I just interleave results from each registries. In most situations this is less than perfect, but I'm not sure what we should do. Surprisingly, it doesn't seem to be that big of a deal in practice. Using the mock OpenVSX server it seems relatively easy to list plugins from both registries, and the more specific your search term is and the more relevant the list seems to become. Tell me what you think of the current state of this feature, and please suggest improvements if you have any! |
While this could serve us for now, I think Theia's plugin system needs to be refactored in a more plugin-type-agnostic way while supporting multiple plugin providers. The extension view would list extensions based on the provider, as this will avoid the issues I had here when trying to find a way to merge everything into a single meaningful list. This can be done later as it will be much more involving. |
46c0e0d
to
d8793f9
Compare
Note to self (and Paul): I'm looking at this today 👍 |
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 change looks mostly good to me. What I couldn't figure out was whether the merging of results deals with duplicate entries (so multiple registries yielding the same extension) as expected. Would the extension view should them as duplicates or is only one shown?
d8793f9
to
ff90526
Compare
I have tested this, it brings value to Theia. The order of plug-ins is not logical, but this is an issue that I can live with. Patches are welcome on that. |
I'm fine with the change, but I still have an open question. |
@msujew Application makers have to make sure to write their configuration in such a way that there are no duplicates returned by the router client. I don't know what the |
I am dragging @ghuntley in... This is something that may be of interest for https://github.com/coder/code-marketplace Also vscode has the similar issue 21839 |
ff90526
to
2f04717
Compare
dev-packages/ovsx-client/README.md
Outdated
// Filters applied to the request before being issued to the registry/ies. | ||
"requests": [ | ||
{ | ||
"someConditionName": "condition expression", |
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.
It will be nice to have a description of supported conditions.
const registryUri = new URI(await this.registryUri); | ||
if (this.downloadUrl) { | ||
const downloadUri = new URI(this.downloadUrl); | ||
if (downloadUri.authority !== registryUri.authority) { |
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 not clear for me, sorry. Consider a case when two repositories are configured, one which URL is the same as configured registryUri
, and the other repository is from different URL. All the extensions for the second registry will generate the error on this method, and it is not clear why error should be generated for them.
@@ -48,7 +48,8 @@ export class VSXExtensionsContribution extends AbstractViewContribution<VSXExten | |||
@inject(LabelProvider) protected readonly labelProvider: LabelProvider; | |||
@inject(ClipboardService) protected readonly clipboardService: ClipboardService; | |||
@inject(PreferenceService) protected readonly preferenceService: PreferenceService; | |||
@inject(OVSXClientProvider) protected readonly clientProvider: OVSXClientProvider; | |||
@inject(OVSXClientProvider) protected clientProvider: OVSXClientProvider; |
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.
It is not clear why clientProvider
and vsxApiFilter
are not read-only. Are they going to be changed somewhere?
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 somewhat accidentally removed the readonly
modifier as I was dealing with these fields.
FWIW I think it's a mistake to make injected fields readonly. I don't see how it prevents any kind of issue. It actually prevents manual field injection when testing as we cannot assign values to the readonly
fields.
I'll remove the readonly
modifiers on injected fields in this class to make it more consistent then.
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.
As an old server-side developer I would prefer to have readonly
everywhere it could be placed :) I would propose to do vice versa, to add readonly
and configure the tests via tiny Inversify snippets. What do you think about it?
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.
Not to be mean but I don't see how being a "server-side dev" is relevant to this? I consider myself a code rat and I might care too much about code quality but I still think that the readonly
keyword is wrong when used for injected fields. It doesn't fix any kind of issue and actually prevent valid re-assignments by downstream users should they want to override those fields with custom logic.
I like immutability as much as the next functional dev but classes as we're using it are meant to be mutable, even more so with the property injection pattern.
If you're still not convinced then I can add readonly
everywhere even if I disagree.
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.
To add to my case, consider the following snippet:
interface MyImmutableService {
readonly fieldA: object
readonly fieldB: object
someMethod(): void
otherMethod(): void
}
declare const service: MyImmutableService
service.fieldA = {} // error as expected
service.someMethod = () => {} // TS is fine here!
If you want the methods to be readonly too you need to write things like:
interface MyImmutableService {
readonly fieldA: object
readonly fieldB: object
readonly someMethod: () => void
readonly otherMethod: () => void
}
But at this point you really denature service interface definition...
Long story short: I don't think we should care about making readonly
fields in services while it may still make sense for "data-objects" that may be returned and passed around by APIs.
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 wrote about server-side for exact reasons you mentioned above: more immutability is better. If something could be made immutable, or at least declared immutable, I consider it is good. readonly
, as far as I understand, should prevent somebody from assigning a value to a field accidentally in the code. And also it says to the reader "this field is not supposed to be changed after it is assigned". But please take all my arguments with a grain of salt, my Theia and TS experience should be considered as basic at this stage.
And just as a side note, for me the ability to create an instance of interface and start assigning its fields is quite crazy :) I understand why it works like this, but still...
As for readonly
for DI fields, I would propose to make it a bit wider topic than a particular review. If there are any coding guidelines for Theia, what do they say about it? If nothing, I would propose to decide in a group (next meeting, maybe?) and then make it a guideline. And then write new code and rework old one, when there is an opportunity, according to the guideline. What do you think about it?
About presenting the results of search from several repositories, why not to add a feature to a repository to expose some metadata about itself? For example, a display name and icon. Then the extension list could show an icon of the repository it originates from as a decoration in some corner or something. A sorting of the results according to the repository of the origin could also be possible. OpenVSX-style repository could implement it as |
2f04717
to
d35da04
Compare
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.
LGTM
The question about readonly
could be addressed separately, I think.
d35da04
to
d668563
Compare
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.
Alright, looks good to me 👍 Don't forget to rebase before merging :)
42c2e18
to
a9394a8
Compare
Refactors the `OVSXClient` into a simple interface that can easily be implemented by components such as `OVSXHttpClient` or others. Add a new `OVSXRouterClient` that may route OpenVSX queries to different registries based on an `OVSXRouteConfig` configuration. The path to the configuration file can be specified when starting the backend using the `--ovsx-router-config` CLI param. When this configuration is not specified, we default to the previously configured OpenVSX registry. The goal of these changes was to minimally impact Theia's plugin code base by simply replacing the client interfaces we use to communicate with an OpenVSX registry. This proved more difficult than expected, especially when merging search results: pagination may currently be broken when dealing with multiple registries. Add a sample mock OpenVSX server running as part of Theia's backend. You can find the plugins served by this mock server under `examples/api-samples/plugins-db`. This mock is there to allow easier testing of the multi-registry feature.
a9394a8
to
7fea930
Compare
Refactors the
OVSXClient
into a simple interface that can easily be implemented by components such asOVSXHttpClient
or others.Add a new
OVSXRouterClient
that may route OpenVSX queries to different registries based on anOVSXRouteConfig
configuration. The path to the configuration file can be specified when starting the backend using the--ovsx-router-config
CLI param. When this configuration is not specified, we default to the previously configured OpenVSX registry.The goal of these changes was to minimally impact Theia's plugin code base by simply replacing the client interfaces we use to communicate with an OpenVSX registry. This proved more difficult than expected, especially when merging search results: pagination may currently be broken when dealing with multiple registries.
Add a sample mock OpenVSX server running as part of Theia's backend. You can find the plugins served by this mock server under
examples/api-samples/plugins-db
. This mock is there to allow easier testing of the multi-registry feature.How to test
--ovsx-router-config
CLI argument should just queryopen-vsx.org
for plugins.sample-namespace
: It should only emit a request to the mock OpenVSX server and show its resultssample-namespac
: It should emit the request to both (mock, openvsx) registries.Review checklist
Reminder for reviewers