Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {
useEffect,
useMemo,
} from "react";

import type {PrestoSearchResult} from "../../../../../../../../common/index.js";
import VirtualTable from "../../../../../../components/VirtualTable";
import useSearchStore from "../../../../SearchState/index";
import {usePrestoSearchResults} from "./usePrestoSearchResults";
import {getPrestoSearchResultsTableColumns} from "./utils";


interface PrestoResultsVirtualTableProps {
tableHeight: number;
}

/**
* Renders Presto search results in a virtual table.
*
* @param props
* @param props.tableHeight
* @return
*/
const PrestoResultsVirtualTable = ({tableHeight}: PrestoResultsVirtualTableProps) => {
const {updateNumSearchResultsTable} = useSearchStore();
const prestoSearchResults = usePrestoSearchResults();

const columns = useMemo(
() => getPrestoSearchResultsTableColumns(prestoSearchResults || []),
[prestoSearchResults]
);

useEffect(() => {
const num = prestoSearchResults ?
prestoSearchResults.length :
0;

updateNumSearchResultsTable(num);
}, [
prestoSearchResults,
updateNumSearchResultsTable,
]);

return (
<VirtualTable<PrestoSearchResult>
columns={columns}
dataSource={prestoSearchResults || []}
pagination={false}
rowKey={(record) => record._id}
scroll={{y: tableHeight}}/>
);
};

export default PrestoResultsVirtualTable;
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type {PrestoSearchResult} from "../../../../../../../../common/index.js";
import MongoSocketCollection from "../../../../../../api/socket/MongoSocketCollection";
import {useCursor} from "../../../../../../api/socket/useCursor";
import useSearchStore, {SEARCH_STATE_DEFAULT} from "../../../../SearchState/index";
import {SEARCH_MAX_NUM_RESULTS} from "../../typings";


/**
* Custom hook to get Presto search results for the current searchJobId.
*
* @return
*/
const usePrestoSearchResults = () => {
const searchJobId = useSearchStore((state) => state.searchJobId);

const searchResultsCursor = useCursor<PrestoSearchResult>(
() => {
// If there is no active search job, there are no results to fetch. The cursor will
// return null.
if (searchJobId === SEARCH_STATE_DEFAULT.searchJobId) {
return null;
}

console.log(
`Subscribing to updates to Presto search results with job ID: ${searchJobId}`
);

// Retrieve 1k most recent results.
const options = {
sort: [
[
"_id",
"desc",
],
],
limit: SEARCH_MAX_NUM_RESULTS,
};

const collection = new MongoSocketCollection(searchJobId);
return collection.find({}, options);
},
[searchJobId]
);

return searchResultsCursor;
};

export {usePrestoSearchResults};
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {TableProps} from "antd";

import type {PrestoSearchResult} from "../../../../../../../../common/index.js";


/**
* Generates dynamic columns configuration for Presto query engine.
*
* @param data Array of Presto search results
* @return
*/
const getPrestoSearchResultsTableColumns = (
data: PrestoSearchResult[]
): NonNullable<TableProps<PrestoSearchResult>["columns"]> => {
if (0 === data.length ||
"undefined" === typeof data[0] ||
"undefined" === typeof data[0].row
) {
return [];
}

return Object.keys(data[0].row)
.map((key) => ({
dataIndex: [
"row",
key,
],
key: key,
title: key,
}));
};

export {getPrestoSearchResultsTableColumns};
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {useEffect} from "react";

import VirtualTable from "../../../../../components/VirtualTable";
import useSearchStore from "../../../SearchState/index";
import {
SearchResult,
searchResultsTableColumns,
} from "./typings";
import {useSearchResults} from "./useSearchResults";


interface SearchResultsVirtualTableProps {
tableHeight: number;
}

/**
* Renders search results in a virtual table.
*
* @param props
* @param props.tableHeight
* @return
*/
const SearchResultsVirtualTable = ({tableHeight}: SearchResultsVirtualTableProps) => {
const {updateNumSearchResultsTable} = useSearchStore();
const searchResults = useSearchResults();

useEffect(() => {
const num = searchResults ?
searchResults.length :
0;

updateNumSearchResultsTable(num);
}, [
searchResults,
updateNumSearchResultsTable,
]);

return (
<VirtualTable<SearchResult>
columns={searchResultsTableColumns}
dataSource={searchResults || []}
pagination={false}
rowKey={(record) => record._id.toString()}
scroll={{y: tableHeight}}/>
);
};

export default SearchResultsVirtualTable;
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {TableProps} from "antd";
import dayjs from "dayjs";

import {DATETIME_FORMAT_TEMPLATE} from "../../../../typings/datetime";
import {
CLP_STORAGE_ENGINES,
SETTINGS_STORAGE_ENGINE,
} from ".././../../../config";
import Message from "./Message";
import {getStreamId} from "./utils";
} from "../../../../../config";
import {DATETIME_FORMAT_TEMPLATE} from "../../../../../typings/datetime";
import Message from "../Message";
import {getStreamId} from "../utils";


/**
Expand All @@ -25,7 +25,7 @@ interface SearchResult {
}

/**
* Columns configuration for the seach results table.
* Columns configuration for the search results table.
*/
const searchResultsTableColumns: NonNullable<TableProps<SearchResult>["columns"]> = [
{
Expand Down Expand Up @@ -70,20 +70,5 @@ const searchResultsTableColumns: NonNullable<TableProps<SearchResult>["columns"]
},
];

/**
* Padding for the table to the bottom of the page.
*/
const TABLE_BOTTOM_PADDING = 75;

/**
* The maximum number of results to retrieve for a search.
*/
const SEARCH_MAX_NUM_RESULTS = 1000;


export type {SearchResult};
export {
SEARCH_MAX_NUM_RESULTS,
searchResultsTableColumns,
TABLE_BOTTOM_PADDING,
};
export {searchResultsTableColumns};
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import MongoSocketCollection from "../../../../api/socket/MongoSocketCollection";
import {useCursor} from "../../../../api/socket/useCursor";
import useSearchStore, {SEARCH_STATE_DEFAULT} from "../../SearchState/index";
import {
SEARCH_MAX_NUM_RESULTS,
SearchResult,
} from "./typings";
import MongoSocketCollection from "../../../../../api/socket/MongoSocketCollection";
import {useCursor} from "../../../../../api/socket/useCursor";
import useSearchStore, {SEARCH_STATE_DEFAULT} from "../../../SearchState/index";
import {SEARCH_MAX_NUM_RESULTS} from "../typings";
import {SearchResult} from "./typings";


/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import {
useState,
} from "react";

import VirtualTable from "../../../../components/VirtualTable";
import useSearchStore from "../../SearchState/index";
import {
SearchResult,
searchResultsTableColumns,
TABLE_BOTTOM_PADDING,
} from "./typings";
import {useSearchResults} from "./useSearchResults";
CLP_QUERY_ENGINES,
SETTINGS_QUERY_ENGINE,
} from "../../../../config";
import PrestoResultsVirtualTable from "./Presto/PrestoResultsVirtualTable";
import SearchResultsVirtualTable from "./SearchResultsVirtualTable";
import {TABLE_BOTTOM_PADDING} from "./typings";


/**
Expand All @@ -20,22 +19,9 @@ import {useSearchResults} from "./useSearchResults";
* @return
*/
const SearchResultsTable = () => {
const {updateNumSearchResultsTable} = useSearchStore();
const searchResults = useSearchResults();
const [tableHeight, setTableHeight] = useState<number>(0);
const containerRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const num = searchResults ?
searchResults.length :
0;

updateNumSearchResultsTable(num);
}, [
searchResults,
updateNumSearchResultsTable,
]);

// Antd table requires a fixed height for virtual scrolling. The effect sets a fixed height
// based on the window height, container top, and fixed padding.
useEffect(() => {
Expand All @@ -60,12 +46,13 @@ const SearchResultsTable = () => {
ref={containerRef}
style={{outline: "none"}}
>
<VirtualTable<SearchResult>
columns={searchResultsTableColumns}
dataSource={searchResults || []}
pagination={false}
rowKey={(record) => record._id.toString()}
scroll={{y: tableHeight}}/>
{CLP_QUERY_ENGINES.PRESTO === SETTINGS_QUERY_ENGINE ?
(
<PrestoResultsVirtualTable tableHeight={tableHeight}/>
) :
(
<SearchResultsVirtualTable tableHeight={tableHeight}/>
)}
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Padding for the table to the bottom of the page.
*/
const TABLE_BOTTOM_PADDING = 75;

/**
* The maximum number of results to retrieve for a search.
*/
const SEARCH_MAX_NUM_RESULTS = 1000;

export {
SEARCH_MAX_NUM_RESULTS,
TABLE_BOTTOM_PADDING,
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
CLP_STORAGE_ENGINES,
SETTINGS_STORAGE_ENGINE,
} from "../../../../config";
import type {SearchResult} from "./typings";
import type {SearchResult} from "./SearchResultsVirtualTable/typings";


/**
Expand Down
17 changes: 17 additions & 0 deletions components/webui/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,29 @@ interface SearchResultsMetadataDocument {
numTotalResults?: number;
queryEngine: CLP_QUERY_ENGINES;
}

/**
* Presto row wrapped in a `row` property to prevent conflicts with MongoDB's `_id` field.
*/
interface PrestoRowObject {
row: Record<string, unknown>;
}

/**
* Presto search result in MongoDB.
*/
interface PrestoSearchResult extends PrestoRowObject {
_id: string;
}

export {
CLP_QUERY_ENGINES,
PRESTO_SEARCH_SIGNAL,
SEARCH_SIGNAL,
};
export type {
PrestoRowObject,
PrestoSearchResult,
SearchResultsMetadataDocument,
ClientToServerEvents,
Err,
Expand Down
5 changes: 3 additions & 2 deletions components/webui/server/src/plugins/app/Presto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ClientOptions,
} from "presto-client";

import {CLP_QUERY_ENGINES} from "../../../../common/index.js";
import settings from "../../../settings.json" with {type: "json"};


Expand All @@ -29,7 +30,7 @@ declare module "fastify" {

export default fp(
(fastify) => {
if ("presto" !== settings.ClpQueryEngine) {
if (CLP_QUERY_ENGINES.PRESTO !== settings.ClpQueryEngine as CLP_QUERY_ENGINES) {
return;
}

Expand All @@ -40,7 +41,7 @@ export default fp(

fastify.log.info(
clientOptions,
"Initializing Presto"
"Initializing Presto client"
);
fastify.decorate("Presto", new Presto(clientOptions));
},
Expand Down
Loading