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

refactoring server routes in index management to use common code #30299

Merged
merged 3 commits into from
Feb 12, 2019

Conversation

bmcconaghy
Copy link
Contributor

This PR moves boilerplate code to x-pack/server/lib and refactors index management to use this new common code. Please look over the pattern and make sure this is a good way to do it. If we are happy with this, we can start refactoring all the management apps to use this new common code.

@bmcconaghy bmcconaghy added Feature:Index Management Index and index templates UI v8.0.0 Team:Kibana Management Dev Tools, Index Management, Upgrade Assistant, ILM, Ingest Node Pipelines, and more v7.2.0 labels Feb 6, 2019
@elasticmachine
Copy link
Contributor

Pinging @elastic/es-ui

@elasticmachine
Copy link
Contributor

💔 Build Failed

Copy link
Contributor

@sebelga sebelga left a comment

Choose a reason for hiding this comment

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

Like we talked briefly on Slack, I think that we could simplify one step further the approach.
I am concerned by 2 things:

  • Very deep traversal to access the registerRoute in many places
    (e.g.: import { registerRoute } from '../../../../../../server/lib/register_route';)
  • A lot of duplicate "pluginId" and "server" passed around that we could abstract for the api route consumer.

What I would suggest is that the registerRoute become a registerRouter and be something like (not tested)

export const registerRouter = (server, pluginId, apiBasePath = '') => {
  const isEsError = isEsErrorFactory(server);
  const licensePreRouting = licensePreRoutingFactory(server, pluginId);

  const requestHandler = (handler) => async (request, h) => {
    const callWithRequest = callWithRequestFactory(server, request);
    try {
      return handler(request, callWithRequest, h);
    } catch (err) {
      if (isEsError(err)) {
        throw wrapEsError(err);
      }

      throw wrapUnknownError(err);
    }
  };

  return (['get', 'post', 'put', 'delete', 'patch'].reduce((router, method) => {
    router[method] = (path, handler) => {
      server.route({
        path: apiBasePath + path,
        method,
        handler: requestHandler(handler),
        config: { pre: [ licensePreRouting ] }
      });
    };
    return router;
  }, {}));
};

Then we only have 1 place to import that factory (in the index_management/index.js)

...
import { registerRouter } from '../../server/lib/register_route'; // only 2 level traversal

export function indexManagement(kibana)  {
  return new kibana.Plugin({
    ...
    init: function (server) {
      server.expose('addIndexManagementDataEnricher', addIndexManagementDataEnricher);
      const router = registerRouter(server, PLUGIN.ID, '/api/index_management');
      registerLicenseChecker(router);
      registerIndicesRoutes(router);
      registerSettingsRoutes(router);
      registerStatsRoute(router);
      registerMappingRoute(router);
    }
  });
}

Finally, the consumer would simply receive the router (no more import) and call its methods

// register_freeze_route.js

const handler = async (request, callWithRequest, h) => {
  const { indices = [] } = request.payload;
  const params = {
    path: `/${encodeURIComponent(indices.join(','))}/_freeze`,
    method: 'POST',
  };

  await callWithRequest('transport.request', params);
  return h.response();
};

export function registerFreezeRoute(router) {
  router.post('/indices/freeze', handler);
}

@bmcconaghy bmcconaghy force-pushed the refactor_server_routes branch from f29783f to 079d610 Compare February 11, 2019 13:45
@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Copy link
Contributor

@cjcenizal cjcenizal left a comment

Choose a reason for hiding this comment

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

This is awesome. I love all the code reduction. I do find Seb's suggestion easier to follow. I also had a suggestion for making error-handling more transparent to the consumer.

method,
handler: async (request, h) => {
const callWithRequest = callWithRequestFactory(server, request);
try {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm concerned about the inflexibility of hardcoding our error-handling this way. There are edge cases to the way we handle our errors, e.g. rollups, so I'd find value in a solution that makes it easier to handle the default case, but still allows for custom logic. For example, something like this:

const handler = async ({ request, callWithRequest, h, handleDefaultError }) => {
  try {
    const { indices = [] } = request.payload;
    const params = {
      path: `/${encodeURIComponent(indices.join(','))}/_freeze`,
      method: 'POST',
    };

    await callWithRequest('transport.request', params);
    return h.response();
  } catch (err) {
    throw handleDefaultError(err);
  }  
};

Copy link
Contributor

@cjcenizal cjcenizal Feb 11, 2019

Choose a reason for hiding this comment

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

I just realized that the existing proposal supports this already. The consumer just needs to put a try/catch in the handler to handle the edge-case, and re-throw the error if the edge-case condition isn't met. So you can ignore my comment above. 😄

@bmcconaghy
Copy link
Contributor Author

@cjcenizal @seb pushed a refactor per the comments.

Copy link
Contributor

@sebelga sebelga left a comment

Choose a reason for hiding this comment

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

LGTM! Awesome

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@bmcconaghy bmcconaghy merged commit ba1c40a into elastic:master Feb 12, 2019
bmcconaghy added a commit to bmcconaghy/kibana that referenced this pull request Feb 12, 2019
…stic#30299)

* refactoring server routes in index management to use common code

* streamlining per PR comments
@bmcconaghy bmcconaghy deleted the refactor_server_routes branch February 12, 2019 15:21
bmcconaghy added a commit that referenced this pull request Feb 13, 2019
) (#30843)

* refactoring server routes in index management to use common code

* streamlining per PR comments
@cjcenizal cjcenizal added the non-issue Indicates to automation that a pull request should not appear in the release notes label May 7, 2019
@rudolf rudolf mentioned this pull request Oct 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Index Management Index and index templates UI non-issue Indicates to automation that a pull request should not appear in the release notes Team:Kibana Management Dev Tools, Index Management, Upgrade Assistant, ILM, Ingest Node Pipelines, and more v7.2.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants