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

[Core] Don't expose Elasticsearch client as Observable #53267

Closed
rudolf opened this issue Dec 17, 2019 · 5 comments · Fixed by #53824
Closed

[Core] Don't expose Elasticsearch client as Observable #53267

rudolf opened this issue Dec 17, 2019 · 5 comments · Fixed by #53824
Assignees
Labels
Feature:New Platform Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc

Comments

@rudolf rudolf added Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc Feature:New Platform labels Dec 17, 2019
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-platform (Team:Platform)

@mshustov mshustov self-assigned this Dec 27, 2019
@mshustov
Copy link
Contributor

In this PR we can separate:

  • internal & public interfaces.
    That would allow us to continue using observables for request handler context.
    [RFC][skip-ci] Prevent plugins from blocking Kibana startup #45796 (comment)
    Do we want to follow this pattern? On the one hand, I'm confused that we handle scoped clients differently in API and context.
    If we assume that a plugin calling elasticsearch API couldn't be affected by ES client update, why it's so important for a request handler context?
interface ElasticsearchPublicInterface {
  createClient: (type: string, clientConfig?..) => ICustomClusterClient;
  adminClient: IClusterClient;
  dataClient: IClusterClient;
}
interface ElasticsearchInternalInterface {
  legacy: {config$: ..};
  adminClient$: Observable<IClusterClient>;
  dataClient$: Observable<IClusterClient>;
}
interface IClusterClient {
  callAsInternalUser: (...) => any;
  asScoped: (req) => IScopedClusterClient;
}

interface ICustomClusterClient extends IClusterClient{
  close: () => void;
}
// SetupContract before
adminClient: {
  callAsInternalUser(){...} ,
  asScoped(request) {
    return {
      callAsInternalUser(){...}
      callAsCurrentUser(){...}
    },
}
dataClient: {
  callAsInternalUser(){...} , 
  asScoped(request) {
    return {
      callAsInternalUser(){...}
      callAsCurrentUser(){...}
    },
}
// SetupContract after
  callAsInternalUser(){...}
  asScoped(request) {
    return {
      callAsInternalUser(){...}
      callAsCurrentUser(){...}
    }
  }

@rudolf
Copy link
Contributor Author

rudolf commented Jan 6, 2020

In this PR we can separate:

  • internal & public interfaces.
    That would allow us to continue using observables for request handler context.
    #45796 (comment)
    Do we want to follow this pattern? On the one hand, I'm confused that we handle scoped clients differently in API and context.
    If we assume that a plugin calling elasticsearch API couldn't be affected by ES client update, why it's so important for a request handler context?

I agree, I don't see any reason we should give a different client to the request context than what we give to plugins.

From context rfc:

  1. Functionality in a handler should be "fixed" for the life of that
    handler's context rather than changing configuration under the hood in
    mid-execution. For example, while Elasticsearch clients can technically
    be replaced throughout the course of the Kibana process, an HTTP route
    handler should be able to depend on their being a consistent client for its
    own shorter lifespan.

I think the reason this was specified was so that code in a context handler doesn't need to deal with observables or promises, a context handler should get a ready-to-use client. @joshdover what do you think?

interface ElasticsearchPublicInterface {
  createClient: (type: string, clientConfig?..) => ICustomClusterClient;
  adminClient: IClusterClient;
  dataClient: IClusterClient;
}
interface ElasticsearchInternalInterface {
  legacy: {config$: ..};
  adminClient$: Observable<IClusterClient>;
  dataClient$: Observable<IClusterClient>;
}
interface IClusterClient {
  callAsInternalUser: (...) => any;
  asScoped: (req) => IScopedClusterClient;
}

interface ICustomClusterClient extends IClusterClient{
  close: () => void;
}

I like this suggestion 👍

// SetupContract before
adminClient: {
  callAsInternalUser(){...} ,
  asScoped(request) {
    return {
      callAsInternalUser(){...}
      callAsCurrentUser(){...}
    },
}
dataClient: {
  callAsInternalUser(){...} , 
  asScoped(request) {
    return {
      callAsInternalUser(){...}
      callAsCurrentUser(){...}
    },
}
// SetupContract after
  callAsInternalUser(){...}
  asScoped(request) {
    return {
      callAsInternalUser(){...}
      callAsCurrentUser(){...}
    }
  }

As something low-priority, it's probably not worth doing if it's a lot of work, but it will reduce the code complexity, so if it's low effort it seems like a good bonus.

@mshustov
Copy link
Contributor

mshustov commented Jan 8, 2020

I agree, I don't see any reason we should give a different client to the request context than what we give to plugins.
I think the reason this was specified was so that code in a context handler doesn't need to deal with observables or promises, a context handler should get a ready-to-use client. @joshdover what do you think?

I merged the current implementation. We can remove the difference later.

@joshdover
Copy link
Contributor

If we assume that a plugin calling elasticsearch API couldn't be affected by ES client update, why it's so important for a request handler context?

Yeah I don't think the observable is important to the request handler context provider any more. However, I do think we should still have the request context provider to do the asScoped work for plugins, simply to provide for a safer default client for request handlers to reach for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:New Platform Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants