Split integrations.ts into handlers & data#40685
Split integrations.ts into handlers & data#40685jfsiii merged 11 commits intoelastic:feature-integrations-managerfrom jfsiii:split-up-integrations
Conversation
Essentially a mechanical refactor for now. Will work on reducing the work done in the handlers in later commits/PRs.
Behavior should be unchanged.
| export type IntegrationList = IntegrationListItem[]; | ||
|
|
||
| export type IntegrationListItem = Installed<RegistryListItem> | NotInstalled<RegistryListItem>; | ||
| export type IntegrationListItem = Installable<RegistryListItem>; |
There was a problem hiding this comment.
So you don’t have to do the | each time. Went with Installable over Maybe*, Either*, etc.
| import { SAVED_OBJECT_TYPE } from '../../common/constants'; | ||
| import * as Registry from '../registry'; | ||
|
|
||
| export async function getIntegrations(client: SavedObjectsClientContract) { |
There was a problem hiding this comment.
These functions all accept a saved object client. Mainly because we get the client from the request, but it also means we can inject a client. Figure we’ll come back to this over time and when the client lands in core .
There was a problem hiding this comment.
So happy to have TS here...
| } | ||
| } | ||
|
|
||
| function createInstallableFrom<T>(from: T, savedObject?: InstallationSavedObject): Installable<T> { |
There was a problem hiding this comment.
Dropped all the overloads
💔 Build Failed |
💚 Build Succeeded |
This is consistent with other registry functions. Returned to nested for loops internally.
| if (asset === 'dashboard') { | ||
| const client = getClient(req); | ||
| const object = await installAssets(client, pkgkey, asset); | ||
| const object = await installAssets(client, pkgkey, (entry: ArchiveEntry) => { |
There was a problem hiding this comment.
Use a filter function like other registry functions
| const { path, buffer } = entry; | ||
| paths.push(path); | ||
| const { file } = pathParts(path); | ||
| if (!file) return; |
There was a problem hiding this comment.
Don’t add directories to the paths. Only files.
| collectReferences(map, { path, desiredType }); | ||
| return map; | ||
| }, new Map()); | ||
| export async function getObjects( |
There was a problem hiding this comment.
Condensed getObjects & collectReferences into one function. Added a ton of comments.
Went with nested fors vs several map, reduce calls and flatten. For context, these might be the first for loops I’ve written in 5 years. I’m not overly concerned with performance but would like to skip the garbage creation/collection of traversing & transforming as much as possible. I also find this the most clear way to express what we’re doing.
There was a problem hiding this comment.
Love these comments. Totally fine with the for loops, I don't love mutating objects that get passed to other functions, so having this all in one function really helps follow that mutation thread for me.
There was a problem hiding this comment.
This feels like a function I'd love to have tests for. Can we log a ticket to do that soon, if not now? Not concerned about 100% coverage or anything but testing a few of these functions would be a great start.
There was a problem hiding this comment.
For sure. Created this very minimal issue but feel free to add any others you think of.
| if (!asset.id) asset.id = file.replace('.json', ''); | ||
|
|
||
| return ensureJsonValues(asset); | ||
| } |
There was a problem hiding this comment.
Mind adding a few more comments on these two functions to explain the diff between getAsset and getObject? I think I follow but a little lost on what's coming out of the cache that needs to be toString-ified.
| } | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/no-empty-interface | ||
| interface DeleteAssetRequest extends InstallAssetRequest {} |
There was a problem hiding this comment.
Are we expecting these to diverge at some point?
There was a problem hiding this comment.
Not sure if I follow, but I made some changes here. Can you look at 13cef20 and let me know if you still have questions/suggestions?
| })); | ||
|
|
||
| const results = await client.bulkGet(searchObjects); | ||
| const savedObjects: InstallationSavedObject[] = results.saved_objects.filter(o => !o.error); // ignore errors for now |
There was a problem hiding this comment.
do you know if the saved object client takes a type generic for what its methods return? I like being able to do:
const results = await client.bulkGet<InstallationSavedObject>(searchObjects);and not having to explicitly type the return of the filter on the next line, if the client method handles that properly. Not a blocker just curious.
There was a problem hiding this comment.
I haven’t seen that before but, yeah, they do.
Or something quite similar
&kibana/src/core/server/saved_objects/service/saved_objects_client.ts
Lines 149 to 164 in 40a1bde
Take a look at 98dfac8. I updated all the client.* calls and removed the explicit typing of their return values.
💚 Build Succeeded |
| return integrationList; | ||
| } | ||
|
|
||
| export async function getIntegrationInfo(client: SavedObjectsClientContract, pkgkey: string) { |
There was a problem hiding this comment.
Is this the single resource version of getIntegrations?
There was a problem hiding this comment.
Yes, IIUC. It’s what’s used for the detail page. getIntegrations is what’s used for for the list view.
| } | ||
|
|
||
| export async function getInstallationObject( | ||
| client: SavedObjectsClientContract, |
There was a problem hiding this comment.
And this is "get the current install state for this one integration"?
| @@ -0,0 +1,109 @@ | |||
| /* | |||
There was a problem hiding this comment.
I think a few simple comments on top of each of the exported functions in this file to explain what they do in relationship to each other would go a long way in helping new folks understand the flow here, and then we can massage the actual names of the functions as we better understand how it all fits together or what we need for other cases, etc. Otherwise this is all really clear and clean.
There was a problem hiding this comment.
Agreed. Breaking this up helped me see some patterns.
If it’s OK with you, I’d like to hold off on that until I add another asset type (e.g. #38609) because I think that might influence things. Things don’t need to be “final” before I add the comments, just looking to get back to making after this refactoring then see how things fit together.
jasonrhodes
left a comment
There was a problem hiding this comment.
Looks good, had a few suggestions for clarifying via a few more comments, and I had a couple questions, but it's mergeable as-is.
Don't need a generic accessor (e.g. for docs, images, etc) yet. Will factor out when it's needed.
I think this is clearer. It also makes sure we don't loop over any keys other than the "root" ones we just matched (vs all that are in the map/accumulator).
💚 Build Succeeded |
💚 Build Succeeded |
Summary
200+ line
server/integrations.tssplit into{data,handlers}.tsaround 100 lines each. The logic/behavior is the same. Functions were just moved around and I think things are much more clear.handlersfunctions parse the requests and call the functions fromdata.datafunctions coordinate with the registry, saved objects, etc.