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

[data views] DataViewLazy implementation phase 1 #173948

Merged
merged 117 commits into from
Apr 3, 2024

Conversation

mattkime
Copy link
Contributor

@mattkime mattkime commented Dec 25, 2023

Summary

Part 1 of #178594

Initial implementation of DataViewLazy class - an alternative DataView implementation that doesn't load the full field list on initial creation.

Implements DataViewLazy (variations from DataView class)
- getFields ({ mapped = true, scripted = true, runtime = true, fieldName, forceRefresh = false, unmapped, indexFilter, metaFields = true }) => 
    Promise<{ getFieldMap: () => Record<string, DataViewField>; getFieldMapSorted: () => Record<string, DataViewField> }>
- getRuntimeFields({ fieldName = ['*'] }) => Record<string, DataViewField>
- getScriptedFields({ fieldName = ['*'] }) => Record<string, DataViewField>
- getFieldByName (string) => Promise<DataViewField>
- toSpec (same params as getFields) => Promise<DataViewSpec>

other notable changes using DataViewLazy over DataView
- won't throw if index pattern fails to match
- by default toSpec doesn't return fields, must pass in parameters for requested fields

---

DataViews service additions
- toDataView: (toDataView: DataViewLazy) => Promise<DataView>;
- toDataViewLazy: (dataView: DataView) => Promise<DataViewLazy>;
- getAllDataViewLazy: () => Promise<DataViewLazy[]>;
- getDataViewLazy: (id: string) => Promise<DataViewLazy>;
- createDataViewLazy: (spec: DataViewSpec) => Promise<DataViewLazy>;
- createAndSaveDataViewLazy: (spec: DataViewSpec, override?: boolean) => Promise<DataViewLazy>;
- getDefaultDataViewLazy: () => Promise<DataViewLazy | null>;

Closes #176426 and #167750

Copy link
Contributor

@jughosta jughosta left a comment

Choose a reason for hiding this comment

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

Great job, Matt!

Copy link
Contributor

@jughosta jughosta left a comment

Choose a reason for hiding this comment

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

LGTM 👍

Relying on tests here.

Copy link
Contributor

@davismcphee davismcphee left a comment

Choose a reason for hiding this comment

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

I haven't made it all the way through yet and will finish up my review tomorrow, but it's looking good overall! Just a few comments so far.

@jughosta
Copy link
Contributor

Sorry, merge conflicts are because of #178983 I introduced a new param to toMinimalSpec.

…me/kibana into data_views_async_fields_new_class
Copy link
Contributor

@davismcphee davismcphee left a comment

Choose a reason for hiding this comment

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

I made it through the rest of the code, and it's looking good overall! Left some feedback, mostly questions and a few minor suggestions.

@@ -1078,11 +1206,11 @@ export class DataViewsService {
overwrite,
})) as SavedObject<DataViewAttributes>;

const createdIndexPattern = await this.initFromSavedObject(response, displayErrors);
Copy link
Contributor

Choose a reason for hiding this comment

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

Just curious why we no longer need to call this anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We were recreating the dataview on save. instead, we're modifying the one we've been handed.

src/plugins/data_views/common/data_views/data_view_lazy.ts Outdated Show resolved Hide resolved
Comment on lines 130 to 134
if (cachedField) {
cachedField.runtimeField = field.runtimeField;
cachedField.spec.type = castEsToKbnFieldTypeName(field.type);
cachedField.spec.esTypes = [field.type];
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

Just curious, why do we update cachedField from the spec when we get runtime fields?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think you're right, this is unneeded.

}
);

return [field];
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we return an array from this method?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Its consistent with adding a composite runtime field which can return more than one field.

Comment on lines 382 to 384
if (fld) {
this.fieldCache.delete(field.name);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Also curious why we delete and re-add scripted fields to the cache when we get them?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Scripted fields override mapped fields. Added a comment to the code.

src/plugins/data_views/common/data_views/data_view_lazy.ts Outdated Show resolved Hide resolved
src/plugins/data_views/common/data_views/data_view_lazy.ts Outdated Show resolved Hide resolved
return field ? field.type === 'date_nanos' : false;
}

getTimeField = () => (this.timeFieldName ? this.getFieldByName(this.timeFieldName) : undefined);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
getTimeField = () => (this.timeFieldName ? this.getFieldByName(this.timeFieldName) : undefined);
getTimeField = async () => (this.timeFieldName ? this.getFieldByName(this.timeFieldName) : undefined);

It might be worth making this method async to return Promise<DataViewField | undefined> instead of Promise<DataViewField> | undefined which seems trickier for consumers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They're equivalent constructs. Awaiting non promises simply returns the item being awaited.

Copy link
Contributor

Choose a reason for hiding this comment

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

I was thinking more if a consumer is using promises since they'd have to conditionally call .then(), but it's a minor nit and also not breaking if we decided to change it later, so I think it's fine to leave as is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, good point

@mattkime
Copy link
Contributor Author

mattkime commented Apr 2, 2024

/ci

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
dataViews 53 55 +2

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
data 2601 2619 +18
dataViews 294 370 +76
total +94

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
dataViewEditor 48.6KB 48.6KB +1.0B

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
dataViews 49.9KB 61.5KB +11.6KB
Unknown metric groups

API count

id before after diff
data 3261 3283 +22
dataViews 976 1069 +93
total +115

References to deprecated APIs

id before after diff
dataViews 26 36 +10

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

cc @mattkime

Copy link
Contributor

@davismcphee davismcphee left a comment

Choose a reason for hiding this comment

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

The latest changes LGTM, I think this is ready to go 👍 Great work, and I'm excited to see this merged so we can start using it!

return field ? field.type === 'date_nanos' : false;
}

getTimeField = () => (this.timeFieldName ? this.getFieldByName(this.timeFieldName) : undefined);
Copy link
Contributor

Choose a reason for hiding this comment

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

I was thinking more if a consumer is using promises since they'd have to conditionally call .then(), but it's a minor nit and also not breaking if we decided to change it later, so I think it's fine to leave as is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting Feature:Data Views Data Views code and UI - index patterns before 8.0 release_note:skip Skip the PR/issue when compiling release notes Team:DataDiscovery Discover App Team (Document Explorer, Saved Search, Surrounding documents, Graph) v8.14.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[DataViews] Make use of DataViewLazy in DataViews API
8 participants