-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
add synchronous config access API #88981
add synchronous config access API #88981
Conversation
public async setSchema(path: ConfigPath, schema: Type<unknown>) { | ||
public setSchema(path: ConfigPath, schema: Type<unknown>) { |
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.
Method was async
for now reason. Also adapted the consumers
private readonly handledPaths: ConfigPath[] = []; | ||
private readonly handledPaths: Set<ConfigPath> = new Set(); |
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.
We were using an array instead of a set to store the used paths, meaning that we were eventually having duplicates. (Impact was minimal as we are using a shareReplay in the plugin context's config.create
observable, but still)
} | ||
|
||
private getDistinctConfig(path: ConfigPath) { | ||
this.markAsHandled(path); |
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.
We were flagging configurations as handled every time we called atPath
. That probably made sense in the initial implementation, but since we now validate the whole config at startups, there are now unnecessary calls.
The only calls to markAsHandled
remaining are the ones done during config validation, and when invoking isEnabledAtPath
to mark a disabled plugin's path as handled.
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.
Can we move validateAtPath
to perform validation only once on every config$
emit? Then we get rid of validation overhead on every config read operation. WDYT? Can be done in a separate PR.a
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.
Validating the config within the whole config obs
this.config$ = combineLatest([this.rawConfigProvider.getConfig$(), this.deprecations]).pipe(...
May be tricky because we would need to already prepare each child observable here, one per schema (we don't want this.config$
to error.).
In a similar way, ideally, atPathSync
should only validate the config once and memoize the error/validation result until next emission.
Also, as you said on slack, the timing between emissions and schema registration needs to be taken into account here. When registering a schema, we need to validate the associated part of the config.
PluginInitializerContext.config
is not an API that should be used a lot, even during plugin initialization (theoretically the config should only be read once, more or less, per plugin), so this should be minor.
I agree that this is still a performance improvement though, I will create an issue.
public atPathSync<TSchema>(path: ConfigPath) { | ||
if (!this.validated) { | ||
throw new Error('`atPathSync` called before config was validated'); | ||
} | ||
const configAtPath = this.lastConfig!.get(path); | ||
return this.validateAtPath(path, configAtPath) as TSchema; |
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.
During testing, directly calling atPathSync
after instantiating the service was causing errors because this.config$
has not emitted yet. Even if that would never occur in real scenarios, as we are awaiting for the config to validate before doing anything with it, I added an explicit rule requiring validate
to have been called before being able to use atPathSync
Pinging @elastic/kibana-core (Team:Core) |
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.
Code LGTM!
Syncing my discussion with pierre about this feature:
The observable based implementation was meant to allow users to reconfigure Kibana at runtime.
hotreload is not active at the moment. We are not emitting a new config to plugins, and manually calling loggingService.reload
instead.
Implementing hotreload will require a lot of effort and has several complexities like disabling a previously enabled plugin.
Sync lifecycle has its own benefits and cons but that was the compromise the team decided to take at some point.
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.
How are we going to communicate this change to the Solution teams? Should we create a meta issue to track migration progress for sync lifecycle methods?
* | ||
* @remarks This should only be used when synchronous access is an absolute necessity, such | ||
* as during the plugin's setup or start lifecycle. For all other usages, | ||
* {@link create} should be used instead. |
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.
Such an irony, considering that we are removing the only config value elasticsearch.logQueries
supporting reactivity.
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.
YAGNI 😉
} | ||
|
||
private getDistinctConfig(path: ConfigPath) { | ||
this.markAsHandled(path); |
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.
Can we move validateAtPath
to perform validation only once on every config$
emit? Then we get rid of validation overhead on every config read operation. WDYT? Can be done in a separate PR.a
💚 Build SucceededMetrics [docs]
History
To update your PR or re-run it, just comment with: |
* add synchronous config accessor * add `config.get` to plugin context and add tsdoc * remove useless markAsHandled calls * fix mocks * update generated docs * fix unit tests * add sync accessor for legacy config
Summary
Fix #82723
PR adds a new
PluginInitializerContext.config.get
API to retrieve the current value of the plugin's configuration synchronously.ConfigService.atPathSync
andPluginInitializerContext.config.get
PluginInitializerContext.config.createIfExists
APIConfigService
, mostly themarkAsHandled
logic (see review comment)PluginInitializerContext
Example
Checklist