Skip to content

Uses SavedObjects API in Courier Saved Object#12407

Merged
tylersmalley merged 13 commits intoelastic:masterfrom
tylersmalley:saved-object-loader-api
Jun 29, 2017
Merged

Uses SavedObjects API in Courier Saved Object#12407
tylersmalley merged 13 commits intoelastic:masterfrom
tylersmalley:saved-object-loader-api

Conversation

@tylersmalley
Copy link
Member

@tylersmalley tylersmalley commented Jun 19, 2017

No description provided.

Copy link
Member Author

Choose a reason for hiding this comment

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

This change was made to maintain consistency with the fetch return format.

@jbudz
Copy link
Contributor

jbudz commented Jun 19, 2017

Karma failures look legitimate

Copy link
Contributor

Choose a reason for hiding this comment

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

thoughts on changing the 2000 to a constant to make it a little bit more clear? COLLECTION_TIME or similar.

Copy link
Contributor

Choose a reason for hiding this comment

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

2s is a noticeable wait, do you know if we can get away with a shorter time?

Copy link
Member Author

Choose a reason for hiding this comment

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

Left over from testing, should be 200.

Copy link
Contributor

Choose a reason for hiding this comment

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

do we not need the onUpdate chain under this anymore?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't see anywhere where we were leveraging this behavior.

Copy link
Contributor

Choose a reason for hiding this comment

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

can you add a comment on the underscore, is this meant to be a private endpoint?

Copy link
Member Author

Choose a reason for hiding this comment

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

Will do - the underscore can actually be removed. I had it simply to not conflict with any saved object key names, but that won't be an issue when we move to ID's.

@tylersmalley tylersmalley force-pushed the saved-object-loader-api branch 3 times, most recently from ccb5afc to 4d94db7 Compare June 21, 2017 16:00
@tylersmalley tylersmalley changed the title Uses SavedObjects API in Courier [WIP] Uses SavedObjects API in Courier Jun 21, 2017
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
@tylersmalley tylersmalley force-pushed the saved-object-loader-api branch 4 times, most recently from e53e9fa to 70d7cc8 Compare June 22, 2017 21:00
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
@tylersmalley tylersmalley force-pushed the saved-object-loader-api branch from 70d7cc8 to 455f1d3 Compare June 22, 2017 21:02
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
@tylersmalley tylersmalley changed the title [WIP] Uses SavedObjects API in Courier Uses SavedObjects API in Courier Saved Object Jun 23, 2017
});
}

}, BATCH_INTERVAL, { leading: false })

Choose a reason for hiding this comment

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

should have a ; at the end because it's an assignment (my intellij gives me a little complaining highlight)

* @param {integer} options.page - defaults to 1
* @param {integer} options.perPage - defaults to 20
* @param {array} option.fields - fields to be returned. Returns all unless defined
* @returns {promise}

Choose a reason for hiding this comment

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

Can you document what the promises will resolve or reject to for the functions in this file? I'm having a hard time figuring out when _type, _id _version and _attributes are used vs type, id, version and attributes. It looks like sometimes its either all _ or no underscore, but above there is a spot above that handles the response type from this call like this:

+              return {
 +                _id: resp.id,
 +                _type: resp.type,
 +                _source: _.cloneDeep(resp._attributes),
 +                found: resp._version ? true : false
 +              };

And I'm wondering why id and type don't have underscores but version and attributes too. Having the comments would help me track that down easier (if only we had interfaces and typescript!)

Copy link
Member Author

Choose a reason for hiding this comment

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

Added documentation to each of the methods.

The Saved Object API itself returns { id, type, attributes, version }. When it's passed to the SavedObject, attributes were previously private and had an underscore. I removed that since it's apparent it's not private. The only remaining thing private to that object is _version.

The code you referenced from the Courier SavedObject is slightly confusing since it's translating SavedObject format to the Elasticsearch format. I choose that as opposed to updating every reference to _source, found, '_id`, etc.

Choose a reason for hiding this comment

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

If we are truly moving to the airbnb styleguide we shouldn't be using the underscore prefix to denote privacy - https://github.com/airbnb/javascript#naming--leading-underscore

But I guess that's not official, and I know it's still in use here and there, so I'm fine if you wish to leave as is as well.

.then(resp => get(resp, 'data'))
.catch(resp => {
const respBody = resp.data || {};
const respBody = get(resp, 'data', {});

Choose a reason for hiding this comment

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

minor feedback (take it or leave it), but I think it'd be easier to read _.get than get because there is already a get function in this file

Actually, even better if we didn't use lodash at all in favor of native functionality (which I think is what we want to gravitate towards anyway). This is no different then

const respBody = resp.data || {};

right? for me, that is easier to mentally compute (though probably because I'm not very familliar with lodash).

also the line above could just be resp.data.

I guess the benefit of using the lodash get version is when you pass it long paths and anywhere along the path something is undefined, it won't crash and burn, but return the default value? If that's the only benefit, then doesn't seem necessary on a path only one attribute deep (unless it works if resp is also undefined?)

Copy link
Contributor

Choose a reason for hiding this comment

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

It is not identical: with the get it's using the default value if undefined, while with the || it's doing it if resp.data is falsy. As resp.data can't have any falsy values as "successful values" doing || is okey here. (I prefer get, though)

Copy link
Member Author

Choose a reason for hiding this comment

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

I updated the whole file to use _ instead of dereferencing the methods out to eliminate confusion.

Copy link
Contributor

@spalger spalger left a comment

Choose a reason for hiding this comment

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

Haven't gotten a chance to run this and verify the tests, but I have some early feedback.

* @param {string} type
* @param {object} body - { attributes: {}, id: myId }
* @param {object} options
* @param {boolean} options.overwrite - defaults to false
Copy link
Contributor

Choose a reason for hiding this comment

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

Pretty sure the correct JSDoc here would be:

* @param {object} [options={}]
* @property {boolean} [options.overwrite=false]

* @returns {promise}
*/
async create(type, body = {}, options = {}) {
const method = get(options, 'overwrite', false) ? 'index' : 'create';
Copy link
Contributor

Choose a reason for hiding this comment

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

no need for the overhead of get() here since options defaults to an empty object.


/**
* @param {object} options
* @param {string} options.type
Copy link
Contributor

Choose a reason for hiding this comment

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

LIke above, properties of an object param should be doc'd as @property {type} options.name

* @param {integer} options.version - ensures version matches that of persisted object
* @returns {promise}
*/
async update(type, id, attributes, { version } = {}) {
Copy link
Contributor

Choose a reason for hiding this comment

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

{ version } = {} is one of many different ways the options are read in this file, I'd love if they were all done the same way, preferably like so:

async method(/* ... */, options = {}) {
  const {
    version: false
  } = options;

  // ...
}

* @param {boolean} options.overwrite - defaults to false
* @returns {promise}
*/
async create(type, body = {}, options = {}) {
Copy link
Contributor

Choose a reason for hiding this comment

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

The body argument here feels out of place. Before we had the concept of attributes, body was used to describe the the same thing, the key/value pairs that define the contents of a saved object. Now it seems that body represents the API request body (more or less), which isn't really relevant to the SavedObjectsClient. I think we should update this to use the same call signature as savedObjectsClient.update(type, id, attributes, options);

Copy link
Member Author

Choose a reason for hiding this comment

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

For create, do you think we should provide ID as a parameter or accept it as an option? We're moving away from creating documents with ID's except for the import so it didn't feel right to promote as an argument.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, good question... I'd just making it optional. We won't ever be able to remove it

Copy link
Member Author

Choose a reason for hiding this comment

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

options now accepts an id. Let me know if this works for you

payload: Joi.object({
attributes: Joi.object().required()
attributes: Joi.object().required(),
id: Joi.string().allow(null)
Copy link
Contributor

Choose a reason for hiding this comment

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

I feels like the url is the right place to put the id: POST /api/saved_objects/{type}/{id}

import chrome from 'ui/chrome';
import { SavedObjectsClient } from 'ui/saved_objects';

uiModules.get('kibana').service('savedObjectsClient', function ($http, $q) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than relying on angular DI and ui/autoload/modules, can we just export a SavedObjectsClientProvider here and use Private(SavedObjectsClientProvider) to get the client?

Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
@tylersmalley tylersmalley force-pushed the saved-object-loader-api branch from 49629ee to 5d00b4f Compare June 26, 2017 21:33
@tylersmalley
Copy link
Member Author

Thanks @stacey-gammon and @spalger - all of your feedback should now be addressed.


/**
* Saves this object.
*

Choose a reason for hiding this comment

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

SaveOptions is no longer typedef'ed so I think this should be changed to:

* @param {object} [options={}]
* @property {boolean} options.confirmOverwrite - If true, attempts to create the source so it		
* can confirm an overwrite if a document with the id already exists.

Copy link
Member Author

Choose a reason for hiding this comment

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

👍 updated

@@ -302,14 +287,14 @@ export function SavedObjectProvider(esAdmin, kbnIndex, Promise, Private, Notifie
* @resolved {String} - The id of the doc

Choose a reason for hiding this comment

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

Does this still resolve to the id? According to the change below, it looks like it now returns a response object with an id property on it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Goot catch. It doesn't appear to have ever returned the id. doIndex is defined here, which calls sendToEs and resolves here

Updated the comment

Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
Uses the ES index action for create except when defing the _id_ without specifying options.overwrite=true
*/
async create(type, attributes = {}, options = {}) {
const method = options.overwrite ? 'index' : 'create';
const method = get(options, 'overwrite', false) === false && options.id ? 'create' : 'index';

Choose a reason for hiding this comment

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

Above it says "force id on creation, not recommended", but it looks like with these new changes, the only way to create an object is to supply options.id. Or does index handle the automatic id creation if it doesn't exist?

Copy link
Member Author

Choose a reason for hiding this comment

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

index handles automatic id creation, in addition, it allows for overwriting of a document when an ID is specified.

Copy link
Contributor

@spalger spalger left a comment

Choose a reason for hiding this comment

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

A couple minor nits, feel free to merge as is, LGTM!

};
});

sinon.stub(esAdmin, 'mget').returns(Promise.resolve({ docs: [ mockDocResponse ] }));
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we can put this off until we rid the frontend of esAdmin completely, but pretty sure we don't need esAdmin stuff here anymore.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch - I was able to remove this esAdmin stub, but still some work to be done to remove the remaining fieldMapping call.

* @returns {promise} - { id, type, version, attributes }
*/
async create(type, attributes = {}, options = {}) {
const method = get(options, 'overwrite', false) === false && options.id ? 'create' : 'index';
Copy link
Contributor

Choose a reason for hiding this comment

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

get(options, 'overwrite', false) === false && options.id

feels like a slightly more complicated way to write

options.id && !options.overwrite

Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
Copy link

@stacey-gammon stacey-gammon left a comment

Choose a reason for hiding this comment

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

🎉

@spalger
Copy link
Contributor

spalger commented Jun 29, 2017

jenkins, test this

@tylersmalley tylersmalley merged commit ead5754 into elastic:master Jun 29, 2017
tylersmalley added a commit to tylersmalley/kibana that referenced this pull request Jun 29, 2017
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
tylersmalley added a commit that referenced this pull request Jun 30, 2017
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
@tylersmalley
Copy link
Member Author

5.x: fa53e2e

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants