Skip to content

Commit

Permalink
--wip--
Browse files Browse the repository at this point in the history
Signed-off-by: Joshua Li <joshuali925@gmail.com>
  • Loading branch information
joshuali925 committed Oct 3, 2023
1 parent e2e0f19 commit 65bf00a
Show file tree
Hide file tree
Showing 15 changed files with 94 additions and 98 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

### 📈 Features/Enhancements

- Add datasource selector to discover ([#5167](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5167))
- Add DataSource service and DataSourceSelector for multiple datasource support ([#5167](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5167))
- Add extension point in saved object management to register namespaces and show filter ([#2656](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2656))
- Add updated_at column to Saved Objects' tables ([#1218](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/1218))
- Change the links in the visualize plugin to use `href` rather than `onClick` ([#2395](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2395))
Expand Down
2 changes: 2 additions & 0 deletions config/opensearch_dashboards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,5 @@

# Set the value of this setting to true to enable plugin augmentation on Dashboard
# vis_augmenter.pluginAugmentationEnabled: true
opensearch.hosts: ["http://ec2-54-70-149-21.us-west-2.compute.amazonaws.com:8443"]
server.host: "0.0.0.0"
19 changes: 13 additions & 6 deletions src/plugins/data/public/data_sources/datasource/datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,21 @@
* DataSourceQueryResult: Represents the result from querying the data source.
*/

import { ConnectionStatus } from './types';
import {
ConnectionStatus,
IDataSetParams,
IDataSourceMetaData,
IDataSourceQueryParams,
IDataSourceQueryResult,
ISourceDataSet,
} from './types';

export abstract class DataSource<
DataSourceMetaData,
DataSetParams,
SourceDataSet,
DataSourceQueryParams,
DataSourceQueryResult
DataSourceMetaData extends IDataSourceMetaData = IDataSourceMetaData,
DataSetParams extends IDataSetParams = IDataSetParams,
SourceDataSet extends ISourceDataSet = ISourceDataSet,
DataSourceQueryParams extends IDataSourceQueryParams = IDataSourceQueryParams,
DataSourceQueryResult extends IDataSourceQueryResult = IDataSourceQueryResult
> {
constructor(
private readonly name: string,
Expand Down
40 changes: 26 additions & 14 deletions src/plugins/data/public/data_sources/datasource/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,25 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { DataSource } from '.';
import { DataSourceType } from '../datasource_services/types';

/**
* The DataSourceFactory is responsible for managing the registration and creation of data source classes.
* It serves as a registry for different data source types and provides a way to instantiate them.
*/

import { DataSourceType } from '../datasource_services';

export class DataSourceFactory {
// Holds the singleton instance of the DataSourceFactory.
private static factory: DataSourceFactory;

// A dictionary holding the data source type as the key and its corresponding class constructor as the value.
private dataSourceClasses: { [type: string]: new (config: any) => DataSourceType } = {};
private dataSources: {
[key: string]: {
dataSourceClass: new (config: any) => DataSource;
dataSourceType: DataSourceType;
};
} = {};

/**
* Private constructor to ensure only one instance of DataSourceFactory is created.
Expand All @@ -38,31 +44,37 @@ export class DataSourceFactory {
* Registers a new data source type with its associated class.
* If the type has already been registered, an error is thrown.
*
* @param {string} type - The identifier for the data source type.
* @param {new (config: any) => DataSourceType} dataSourceClass - The constructor of the data source class.
* @param {DataSourceType} type - The identifier for the data source type.
* @param {new (config: any) => DataSource} dataSourceClass - The constructor of the data source class.
* @throws {Error} Throws an error if the data source type has already been registered.
*/
registerDataSourceType(type: string, dataSourceClass: new (config: any) => DataSourceType): void {
if (this.dataSourceClasses[type]) {
registerDataSourceType(
dataSourceType: DataSourceType,
dataSourceClass: new (config: any) => DataSource
): void {
if (this.dataSources[dataSourceType.key]) {
throw new Error('This data source type has already been registered');
}
this.dataSourceClasses[type] = dataSourceClass;
this.dataSources[dataSourceType.key] = {
dataSourceClass,
dataSourceType,
};
}

/**
* Creates and returns an instance of the specified data source type with the given configuration.
* If the type hasn't been registered, an error is thrown.
*
* @param {string} type - The identifier for the data source type.
* @param {string} key - The identifier for the data source type.
* @param {any} config - The configuration for the data source instance.
* @returns {DataSourceType} An instance of the specified data source type.
* @returns {DataSource} An instance of the specified data source type.
* @throws {Error} Throws an error if the data source type is not supported.
*/
getDataSourceInstance(type: string, config: any): DataSourceType {
const DataSourceClass = this.dataSourceClasses[type];
if (!DataSourceClass) {
getDataSourceInstance(key: string, config: any): DataSource {
const dataSource = this.dataSources[key];
if (!dataSource) {
throw new Error('Unsupported data source type');
}
return new DataSourceClass(config);
return new dataSource.dataSourceClass(config);
}
}
4 changes: 2 additions & 2 deletions src/plugins/data/public/data_sources/datasource/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { DataSource } from '.';
import { IndexPattern } from '../../index_patterns';
import { DataSourceType } from '../datasource_services';

export interface IDataSourceMetaData {
name: string;
Expand All @@ -15,7 +15,7 @@ export interface IDataSourceGroup {
}

export interface ISourceDataSet {
ds: DataSourceType;
ds: DataSource;
data_sets: string[] | IndexPattern;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import React from 'react';
import { render, act } from '@testing-library/react';
import { DataSourceSelectable } from './datasource_selectable';
import { DataSourceType } from '../datasource_services';
import { DataSource } from '../datasource_services';

describe('DataSourceSelectable', () => {
let dataSourcesMock;
Expand All @@ -22,7 +22,7 @@ describe('DataSourceSelectable', () => {
getDataSet: jest.fn().mockResolvedValue([]),
getType: jest.fn().mockReturnValue('DEFAULT_INDEX_PATTERNS'),
getName: jest.fn().mockReturnValue('SomeName'),
} as unknown) as DataSourceType,
} as unknown) as DataSource,
];

dataSourceOptionListMock = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

import React, { useEffect } from 'react';
import { DataSourceSelector } from './datasource_selector';
import { DataSourceType } from '../datasource_services';
import { DataSourceGroup, DataSourceOption, DataSourceSelectableProps } from './types';
import { ISourceDataSet } from '../datasource/types';
import { IndexPattern } from '../../index_patterns';
import { DataSource } from '../..';

// Mapping between datasource type and its display name.
const DATASOURCE_TYPE_DISPLAY_NAME_MAP = {
Expand All @@ -31,7 +31,7 @@ export const DataSourceSelectable = ({
// This effect fetches datasets and prepares the datasource list for UI rendering.
useEffect(() => {
// Fetches datasets for a given datasource and returns it along with the source.
const fetchDataSetWithSource = async (ds: DataSourceType): Promise<ISourceDataSet> => {
const fetchDataSetWithSource = async (ds: DataSource): Promise<ISourceDataSet> => {
const dataSet = await ds.getDataSet();
return {
ds,
Expand All @@ -40,13 +40,13 @@ export const DataSourceSelectable = ({
};

// Map through all data sources and fetch their respective datasets.
const fetchDataSets = () => dataSources.map((ds: DataSourceType) => fetchDataSetWithSource(ds));
const fetchDataSets = () => dataSources.map((ds: DataSource) => fetchDataSetWithSource(ds));

const isIndexPatterns = (dataset: string | IndexPattern) =>
dataset.attributes?.title && dataset.id;

// Get the option format for the combo box from the dataSource and dataSet.
const getSourceOptions = (dataSource: DataSourceType, dataSet: DataSetType) => {
const getSourceOptions = (dataSource: DataSource, dataSet: DataSetType) => {
const optionContent = {
type: dataSource.getType(),
name: dataSource.getName(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import { OuiComboBoxOptionOption } from '@elastic/eui';
import { DataSourceType } from '../datasource_services';
import { DataSource } from '../..';

export interface DataSourceGroup {
label: string;
Expand All @@ -19,7 +19,7 @@ export interface DataSourceOption {
export type DataSourceOptionType = OuiComboBoxOptionOption<unknown>;

export interface DataSourceSelectableProps {
dataSources: DataSourceType[];
dataSources: DataSource[];
dataSourceOptionList: DataSourceGroup[];
selectedSources: DataSourceOption[];
onDataSourceSelect: (dataSourceOption: DataSourceOption[]) => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,20 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { forEach, isEmpty } from 'lodash';
import { BehaviorSubject } from 'rxjs';
import { isEmpty, forEach } from 'lodash';
import {
DataSource,
IDataSetParams,
IDataSourceMetaData,
IDataSourceQueryParams,
IDataSourceQueryResult,
ISourceDataSet,
} from '../datasource';
import { DataSource } from '../datasource';
import {
DataSourceRegistrationError,
IDataSourceFilters,
IDataSourceRegisterationResult,
DataSourceRegisterationError,
IDataSourceRegistrationResult,
} from './types';

export type DataSourceType = DataSource<
IDataSourceMetaData,
IDataSetParams,
ISourceDataSet,
IDataSourceQueryParams,
IDataSourceQueryResult
>;

export class DataSourceService {
private static dataSourceService: DataSourceService;
// A record to store all registered data sources, using the data source name as the key.
private dataSources: Record<string, DataSourceType> = {};
private _dataSourcesSubject: BehaviorSubject<Record<string, DataSourceType>>;
private dataSources: Record<string, DataSource> = {};
private _dataSourcesSubject: BehaviorSubject<Record<string, DataSource>>;

private constructor() {
this._dataSourcesSubject = new BehaviorSubject(this.dataSources);
Expand All @@ -51,8 +36,8 @@ export class DataSourceService {
* @returns An array of registration results, one for each data source.
*/
async registerMultipleDataSources(
datasources: DataSourceType[]
): Promise<IDataSourceRegisterationResult[]> {
datasources: DataSource[]
): Promise<IDataSourceRegistrationResult[]> {
return Promise.all(datasources.map((ds) => this.registerDataSource(ds)));
}

Expand All @@ -62,12 +47,12 @@ export class DataSourceService {
*
* @param ds - The data source to be registered.
* @returns A registration result indicating success or failure.
* @throws {DataSourceRegisterationError} Throws an error if a data source with the same name already exists.
* @throws {DataSourceRegistrationError} Throws an error if a data source with the same name already exists.
*/
async registerDataSource(ds: DataSourceType): Promise<IDataSourceRegisterationResult> {
async registerDataSource(ds: DataSource): Promise<IDataSourceRegistrationResult> {
const dsName = ds.getName();
if (dsName in this.dataSources) {
throw new DataSourceRegisterationError(
throw new DataSourceRegistrationError(
`Unable to register datasource ${dsName}, error: datasource name exists.`
);
} else {
Expand All @@ -76,7 +61,7 @@ export class DataSourceService {
[dsName]: ds,
};
this._dataSourcesSubject.next(this.dataSources);
return { success: true, info: '' } as IDataSourceRegisterationResult;
return { success: true, info: '' } as IDataSourceRegistrationResult;
}
}

Expand All @@ -91,9 +76,9 @@ export class DataSourceService {
* @param filters - An optional object with filter criteria (e.g., names of data sources).
* @returns A record of filtered data sources.
*/
getDataSources(filters?: IDataSourceFilters): Record<string, DataSourceType> {
getDataSources(filters?: IDataSourceFilters): Record<string, DataSource> {
if (!filters || isEmpty(filters.names)) return this.dataSources;
const filteredDataSources: Record<string, DataSourceType> = {};
const filteredDataSources: Record<string, DataSource> = {};
forEach(filters.names, (dsName) => {
if (dsName in this.dataSources) {
filteredDataSources[dsName] = this.dataSources[dsName];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
export { DataSourceService } from './datasource_service';
export {
IDataSourceFilters,
IDataSourceRegisterationResult,
DataSourceRegisterationError,
DataSourceType,
IDataSourceRegistrationResult as IDataSourceRegisterationResult,
DataSourceRegistrationError as DataSourceRegisterationError,
} from './types';
29 changes: 10 additions & 19 deletions src/plugins/data/public/data_sources/datasource_services/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,19 @@
* SPDX-License-Identifier: Apache-2.0
*/

import {
DataSource,
DataSourceFactory,
IDataSetParams,
IDataSourceMetaData,
IDataSourceQueryParams,
IDataSourceQueryResult,
ISourceDataSet,
} from '../datasource';
import { DataSourceFactory } from '../datasource';
import { DataSourceService } from './datasource_service';

export interface IDataSourceFilters {
names: string[];
}

export interface IDataSourceRegisterationResult {
export interface IDataSourceRegistrationResult {
success: boolean;
info: string;
}

export class DataSourceRegisterationError extends Error {
export class DataSourceRegistrationError extends Error {
success: boolean;
info: string;
constructor(message: string) {
Expand All @@ -33,15 +25,14 @@ export class DataSourceRegisterationError extends Error {
}
}

export interface DataSourceType {
key: string;
label: string;
// name used in backend that will not be displayed on UI
backendName: string;
}

export interface DataSourceStart {
dataSourceService: DataSourceService;
dataSourceFactory: DataSourceFactory;
}

export type DataSourceType = DataSource<
IDataSourceMetaData,
IDataSetParams,
ISourceDataSet,
IDataSourceQueryParams,
IDataSourceQueryResult
>;
1 change: 0 additions & 1 deletion src/plugins/data/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,6 @@ export {
export {
DataSourceRegisterationError,
DataSourceService,
DataSourceType,
IDataSourceFilters,
IDataSourceRegisterationResult,
} from './data_sources/datasource_services';
Expand Down
Loading

0 comments on commit 65bf00a

Please sign in to comment.