Uses SavedObjects API in Courier Saved Object#12407
Uses SavedObjects API in Courier Saved Object#12407tylersmalley merged 13 commits intoelastic:masterfrom
Conversation
There was a problem hiding this comment.
This change was made to maintain consistency with the fetch return format.
|
Karma failures look legitimate |
There was a problem hiding this comment.
thoughts on changing the 2000 to a constant to make it a little bit more clear? COLLECTION_TIME or similar.
There was a problem hiding this comment.
2s is a noticeable wait, do you know if we can get away with a shorter time?
There was a problem hiding this comment.
Left over from testing, should be 200.
There was a problem hiding this comment.
do we not need the onUpdate chain under this anymore?
There was a problem hiding this comment.
I don't see anywhere where we were leveraging this behavior.
There was a problem hiding this comment.
can you add a comment on the underscore, is this meant to be a private endpoint?
There was a problem hiding this comment.
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.
ccb5afc to
4d94db7
Compare
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
e53e9fa to
70d7cc8
Compare
70d7cc8 to
455f1d3
Compare
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
| }); | ||
| } | ||
|
|
||
| }, BATCH_INTERVAL, { leading: false }) |
There was a problem hiding this comment.
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} |
There was a problem hiding this comment.
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!)
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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', {}); |
There was a problem hiding this comment.
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?)
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
I updated the whole file to use _ instead of dereferencing the methods out to eliminate confusion.
spalger
left a comment
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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'; |
There was a problem hiding this comment.
no need for the overhead of get() here since options defaults to an empty object.
|
|
||
| /** | ||
| * @param {object} options | ||
| * @param {string} options.type |
There was a problem hiding this comment.
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 } = {}) { |
There was a problem hiding this comment.
{ 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 = {}) { |
There was a problem hiding this comment.
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);
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Hmm, good question... I'd just making it optional. We won't ever be able to remove it
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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>
49629ee to
5d00b4f
Compare
|
Thanks @stacey-gammon and @spalger - all of your feedback should now be addressed. |
|
|
||
| /** | ||
| * Saves this object. | ||
| * |
There was a problem hiding this comment.
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.
| @@ -302,14 +287,14 @@ export function SavedObjectProvider(esAdmin, kbnIndex, Promise, Private, Notifie | |||
| * @resolved {String} - The id of the doc | |||
There was a problem hiding this comment.
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.
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'; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
index handles automatic id creation, in addition, it allows for overwriting of a document when an ID is specified.
spalger
left a comment
There was a problem hiding this comment.
A couple minor nits, feel free to merge as is, LGTM!
| }; | ||
| }); | ||
|
|
||
| sinon.stub(esAdmin, 'mget').returns(Promise.resolve({ docs: [ mockDocResponse ] })); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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'; |
There was a problem hiding this comment.
get(options, 'overwrite', false) === false && options.idfeels like a slightly more complicated way to write
options.id && !options.overwriteSigned-off-by: Tyler Smalley <tyler.smalley@elastic.co>
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
|
jenkins, test this |
Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
|
5.x: fa53e2e |
No description provided.