diff --git a/components/clp-package-utils/clp_package_utils/scripts/start_clp.py b/components/clp-package-utils/clp_package_utils/scripts/start_clp.py index c2cd0286f..8a0d386b0 100755 --- a/components/clp-package-utils/clp_package_utils/scripts/start_clp.py +++ b/components/clp-package-utils/clp_package_utils/scripts/start_clp.py @@ -16,6 +16,7 @@ ALL_TARGET_NAME, CLP_METADATA_TABLE_PREFIX, CLPConfig, + COMPRESSION_JOBS_TABLE_NAME, COMPRESSION_SCHEDULER_COMPONENT_NAME, COMPRESSION_WORKER_COMPONENT_NAME, CONTROLLER_TARGET_NAME, @@ -685,9 +686,10 @@ def start_webui(instance_id: str, clp_config: CLPConfig, mounts: CLPDockerMounts "SqlDbHost": clp_config.database.host, "SqlDbPort": clp_config.database.port, "SqlDbName": clp_config.database.name, - "SqlDbSearchJobsTableName": SEARCH_JOBS_TABLE_NAME, "SqlDbClpArchivesTableName": f"{CLP_METADATA_TABLE_PREFIX}archives", "SqlDbClpFilesTableName": f"{CLP_METADATA_TABLE_PREFIX}files", + "SqlDbCompressionJobsTableName": COMPRESSION_JOBS_TABLE_NAME, + "SqlDbSearchJobsTableName": SEARCH_JOBS_TABLE_NAME, }, "public": { "ClpStorageEngine": clp_config.package.storage_engine, diff --git a/components/webui/imports/api/ingestion/collections.js b/components/webui/imports/api/ingestion/collections.js index 2aee9b514..993831790 100644 --- a/components/webui/imports/api/ingestion/collections.js +++ b/components/webui/imports/api/ingestion/collections.js @@ -1,6 +1,10 @@ import {Mongo} from "meteor/mongo"; +const CompressionJobsCollection = new Mongo.Collection( + Meteor.settings.public.CompressionJobsCollectionName +); + /** * Enum representing the statistics collection IDs. * @@ -13,6 +17,7 @@ const STATS_COLLECTION_ID = Object.freeze({ const StatsCollection = new Mongo.Collection(Meteor.settings.public.StatsCollectionName); export { + CompressionJobsCollection, STATS_COLLECTION_ID, StatsCollection, }; diff --git a/components/webui/imports/api/ingestion/constants.js b/components/webui/imports/api/ingestion/constants.js new file mode 100644 index 000000000..8797e7849 --- /dev/null +++ b/components/webui/imports/api/ingestion/constants.js @@ -0,0 +1,63 @@ +/* eslint-disable sort-keys */ +/** + * Enum of the column names for the `compression_jobs` table. + * + * @enum {string} + */ +const COMPRESSION_JOBS_TABLE_COLUMN_NAMES = Object.freeze({ + ID: "id", + STATUS: "status", + STATUS_MSG: "status_msg", + CREATION_TIME: "creation_time", + START_TIME: "start_time", + DURATION: "duration", + ORIGINAL_SIZE: "original_size", + UNCOMPRESSED_SIZE: "uncompressed_size", + COMPRESSED_SIZE: "compressed_size", + NUM_TASKS: "num_tasks", + NUM_TASKS_COMPLETED: "num_tasks_completed", + CLP_BINARY_VERSION: "clp_binary_version", + CLP_CONFIG: "clp_config", +}); +/* eslint-enable sort-keys */ + +/** + * @typedef {number} CompressionJobStatus + */ +let enumCompressionJobStatus; +/** + * Enum of compression job statuses, matching the `CompressionJobStatus` class in + * `job_orchestration.scheduler.constants`. + * + * @enum {CompressionJobStatus} + */ +const COMPRESSION_JOB_STATUS = Object.freeze({ + PENDING: (enumCompressionJobStatus = 0), + RUNNING: ++enumCompressionJobStatus, + SUCCEEDED: ++enumCompressionJobStatus, + FAILED: ++enumCompressionJobStatus, +}); + +/** + * List of waiting states for a compression job. + * + * @see COMPRESSION_JOB_STATUS + */ +const COMPRESSION_JOB_WAITING_STATES = Object.freeze([ + COMPRESSION_JOB_STATUS.PENDING, + COMPRESSION_JOB_STATUS.RUNNING, +]); + +/** + * Names for the compression job statuses. + * + * @type {ReadonlyArray} + */ +const COMPRESSION_JOB_STATUS_NAMES = Object.freeze(Object.keys(COMPRESSION_JOB_STATUS)); + +export { + COMPRESSION_JOB_STATUS, + COMPRESSION_JOB_STATUS_NAMES, + COMPRESSION_JOB_WAITING_STATES, + COMPRESSION_JOBS_TABLE_COLUMN_NAMES, +}; diff --git a/components/webui/imports/api/ingestion/server/CompressionDbManager.js b/components/webui/imports/api/ingestion/server/CompressionDbManager.js new file mode 100644 index 000000000..bd0e47c0c --- /dev/null +++ b/components/webui/imports/api/ingestion/server/CompressionDbManager.js @@ -0,0 +1,76 @@ +import {COMPRESSION_JOBS_TABLE_COLUMN_NAMES} from "../constants"; + + +/** + * Class for retrieving compression jobs from the database. + */ +class CompressionDbManager { + #sqlDbConnPool; + + #compressionJobsTableName; + + /** + * @param {import("mysql2/promise").Pool} sqlDbConnPool + * @param {object} tableNames + * @param {string} tableNames.compressionJobsTableName + */ + constructor (sqlDbConnPool, {compressionJobsTableName}) { + this.#sqlDbConnPool = sqlDbConnPool; + this.#compressionJobsTableName = compressionJobsTableName; + } + + /** + * Retrieves the last `limit` number of jobs and the ones with the given + * job IDs. + * + * @param {number} limit + * @param {number[]} jobIds + * @return {Promise} Job objects with fields with the names in + * `COMPRESSION_JOBS_TABLE_COLUMN_NAMES` + */ + async getCompressionJobs (limit, jobIds) { + const queries = []; + + queries.push(` + WITH SelectedColumns AS ( + SELECT + id as _id, + ${COMPRESSION_JOBS_TABLE_COLUMN_NAMES.STATUS}, + ${COMPRESSION_JOBS_TABLE_COLUMN_NAMES.STATUS_MSG}, + ${COMPRESSION_JOBS_TABLE_COLUMN_NAMES.START_TIME}, + ${COMPRESSION_JOBS_TABLE_COLUMN_NAMES.DURATION}, + ${COMPRESSION_JOBS_TABLE_COLUMN_NAMES.UNCOMPRESSED_SIZE}, + ${COMPRESSION_JOBS_TABLE_COLUMN_NAMES.COMPRESSED_SIZE} + FROM ${this.#compressionJobsTableName} + ) + ( + SELECT * + FROM SelectedColumns + ORDER BY _id DESC + LIMIT ${limit} + ) + `); + + // The initial select may not include the jobs specified by `jobIds`, so we select + // them explicitly and then deduplicate the rows with a UNION DISTINCT clause. + jobIds.forEach((jobId) => { + queries.push(` + UNION DISTINCT + ( + SELECT * + FROM SelectedColumns + WHERE _id=${jobId} + ) + `); + }); + + queries.push("ORDER BY _id DESC;"); + + const queryString = queries.join("\n"); + const [results] = await this.#sqlDbConnPool.query(queryString); + + return results; + } +} + +export default CompressionDbManager; diff --git a/components/webui/imports/api/ingestion/server/publications.js b/components/webui/imports/api/ingestion/server/publications.js index 9fa9d00dd..7b59550fd 100644 --- a/components/webui/imports/api/ingestion/server/publications.js +++ b/components/webui/imports/api/ingestion/server/publications.js @@ -1,16 +1,32 @@ import {Meteor} from "meteor/meteor"; import {logger} from "/imports/utils/logger"; +import {MONGO_SORT_BY_ID} from "/imports/utils/mongo"; import { - STATS_COLLECTION_ID, - StatsCollection, + CompressionJobsCollection, STATS_COLLECTION_ID, StatsCollection, } from "../collections"; +import { + COMPRESSION_JOB_WAITING_STATES, COMPRESSION_JOBS_TABLE_COLUMN_NAMES, +} from "../constants"; +import CompressionDbManager from "./CompressionDbManager"; import StatsDbManager from "./StatsDbManager"; +const COMPRESSION_JOBS_REFRESH_INTERVAL_MILLIS = 1000; + +/** + * The maximum number of compression jobs to retrieve at a time. + */ +const COMPRESSION_MAX_RETRIEVE_JOBS = 5; + const STATS_REFRESH_INTERVAL_MILLIS = 5000; +/** + * @type {CompressionDbManager|null} + */ +let compressionDbManager = null; + /** * @type {StatsDbManager|null} */ @@ -19,7 +35,12 @@ let statsDbManager = null; /** * @type {number|null} */ -let refreshMeteorInterval = null; +let compressionJobsRefreshTimeout = null; + +/** + * @type {number|null} + */ +let statsRefreshInterval = null; /** * Updates the compression statistics in the StatsCollection. @@ -45,6 +66,95 @@ const refreshCompressionStats = async () => { await StatsCollection.updateAsync(filter, modifier, options); }; +/** + * Updates the compression jobs in the CompressionJobsCollection. + * + * @return {Promise} + */ +const refreshCompressionJobs = async () => { + if (null !== compressionJobsRefreshTimeout) { + // Clear the timeout in case this method is not called due to the timeout expiring. + Meteor.clearTimeout(compressionJobsRefreshTimeout); + compressionJobsRefreshTimeout = null; + } + if (0 === Meteor.server.stream_server.all_sockets().length) { + compressionJobsRefreshTimeout = Meteor.setTimeout( + refreshCompressionJobs, + COMPRESSION_JOBS_REFRESH_INTERVAL_MILLIS + ); + + return; + } + + const pendingJobIds = await CompressionJobsCollection.find({ + [COMPRESSION_JOBS_TABLE_COLUMN_NAMES.STATUS]: { + $in: COMPRESSION_JOB_WAITING_STATES, + }, + }) + .fetch() + .map((job) => ( + job._id + )); + + const jobs = await compressionDbManager.getCompressionJobs( + COMPRESSION_MAX_RETRIEVE_JOBS, + pendingJobIds + ); + + const operations = jobs.map((doc) => ({ + updateOne: { + filter: {_id: doc._id}, + update: {$set: doc}, + upsert: true, + }, + })); + + if (0 !== operations.length) { + await CompressionJobsCollection.rawCollection().bulkWrite(operations); + } + + // `refreshCompressionJobs()` shall not be run concurrently and therefore incurs no race + // condition. + // eslint-disable-next-line require-atomic-updates + compressionJobsRefreshTimeout = Meteor.setTimeout( + refreshCompressionJobs, + COMPRESSION_JOBS_REFRESH_INTERVAL_MILLIS + ); +}; + +/** + * Initializes the CompressionDbManager and starts a timeout timer (`compressionJobsRefreshTimeout`) + * for compression job updates. + * + * @param {import("mysql2/promise").Pool} sqlDbConnPool + * @param {object} tableNames + * @param {string} tableNames.compressionJobsTableName + * @throws {Error} on error. + */ +const initCompressionDbManager = (sqlDbConnPool, { + compressionJobsTableName, +}) => { + compressionDbManager = new CompressionDbManager(sqlDbConnPool, { + compressionJobsTableName, + }); + + compressionJobsRefreshTimeout = Meteor.setTimeout( + refreshCompressionJobs, + COMPRESSION_JOBS_REFRESH_INTERVAL_MILLIS + ); +}; + +/** + * De-initializes the CompressionDbManager by clearing the timeout timer for compression job + * updates (`refreshCompressionJobs`). + */ +const deinitCompressionDbManager = () => { + if (null !== compressionJobsRefreshTimeout) { + Meteor.clearTimeout(compressionJobsRefreshTimeout); + compressionJobsRefreshTimeout = null; + } +}; + /** * Initializes the StatsDbManager and starts an interval timer (`refreshMeteorInterval`) for * compression stats updates. @@ -64,7 +174,7 @@ const initStatsDbManager = (sqlDbConnPool, { clpFilesTableName, }); - refreshMeteorInterval = Meteor.setInterval( + statsRefreshInterval = Meteor.setInterval( refreshCompressionStats, STATS_REFRESH_INTERVAL_MILLIS ); @@ -75,12 +185,30 @@ const initStatsDbManager = (sqlDbConnPool, { * (`refreshMeteorInterval`). */ const deinitStatsDbManager = () => { - if (null !== refreshMeteorInterval) { - Meteor.clearInterval(refreshMeteorInterval); - refreshMeteorInterval = null; + if (null !== statsRefreshInterval) { + Meteor.clearInterval(statsRefreshInterval); + statsRefreshInterval = null; } }; +/** + * Updates and publishes compression job statuses. + * + * @param {string} publicationName + * @return {Mongo.Cursor} + */ +Meteor.publish(Meteor.settings.public.CompressionJobsCollectionName, async () => { + logger.debug(`Subscription '${Meteor.settings.public.CompressionJobsCollectionName}'`); + + await refreshCompressionJobs(); + + const findOptions = { + sort: [MONGO_SORT_BY_ID], + }; + + return CompressionJobsCollection.find({}, findOptions); +}); + /** * Updates and publishes compression statistics. * @@ -100,6 +228,8 @@ Meteor.publish(Meteor.settings.public.StatsCollectionName, async () => { }); export { + deinitCompressionDbManager, deinitStatsDbManager, + initCompressionDbManager, initStatsDbManager, }; diff --git a/components/webui/imports/api/ingestion/types.js b/components/webui/imports/api/ingestion/types.js index 6847704cf..d43b74457 100644 --- a/components/webui/imports/api/ingestion/types.js +++ b/components/webui/imports/api/ingestion/types.js @@ -1,3 +1,14 @@ +/** + * @typedef {object} CompressionJob + * @property {number} _id + * @property {number} status + * @property {string} status_msg + * @property {Date} start_time + * @property {number} duration + * @property {number} uncompressed_size + * @property {number} compressed_size + */ + /** * @typedef {object} CompressionStats * @property {number|null} begin_timestamp diff --git a/components/webui/imports/api/search/server/publications.js b/components/webui/imports/api/search/server/publications.js index a0f1d8d52..615008776 100644 --- a/components/webui/imports/api/search/server/publications.js +++ b/components/webui/imports/api/search/server/publications.js @@ -1,10 +1,13 @@ import {Meteor} from "meteor/meteor"; import {logger} from "/imports/utils/logger"; +import { + MONGO_SORT_BY_ID, + MONGO_SORT_ORDER, +} from "/imports/utils/mongo"; import {SearchResultsMetadataCollection} from "../collections"; import { - MONGO_SORT_ORDER, SEARCH_MAX_NUM_RESULTS, SEARCH_RESULTS_FIELDS, } from "../constants"; @@ -58,7 +61,7 @@ Meteor.publish(Meteor.settings.public.SearchResultsCollectionName, ({ sort: [ /* eslint-disable @stylistic/js/array-element-newline */ [SEARCH_RESULTS_FIELDS.TIMESTAMP, MONGO_SORT_ORDER.DESCENDING], - [SEARCH_RESULTS_FIELDS.ID, MONGO_SORT_ORDER.DESCENDING], + MONGO_SORT_BY_ID, /* eslint-enable @stylistic/js/array-element-newline */ ], limit: SEARCH_MAX_NUM_RESULTS, diff --git a/components/webui/imports/ui/App.scss b/components/webui/imports/ui/App.scss index ae3d20594..759d18f68 100644 --- a/components/webui/imports/ui/App.scss +++ b/components/webui/imports/ui/App.scss @@ -14,4 +14,6 @@ body { #page-container { flex-grow: 1; + + overflow-y: auto; } diff --git a/components/webui/imports/ui/IngestView/IngestView.jsx b/components/webui/imports/ui/IngestView/IngestView.jsx index e6135a363..d3b2163f9 100644 --- a/components/webui/imports/ui/IngestView/IngestView.jsx +++ b/components/webui/imports/ui/IngestView/IngestView.jsx @@ -6,6 +6,7 @@ import Row from "react-bootstrap/Row"; import {StatsCollection} from "/imports/api/ingestion/collections"; import Details from "./panels/Details"; +import IngestionJobs from "./panels/IngestionJobs"; import SpaceSavings from "./panels/SpaceSavings"; import "./IngestView.scss"; @@ -40,6 +41,9 @@ const IngestView = () => { } + + + ); }; diff --git a/components/webui/imports/ui/IngestView/panels/IngestionJobs/IngestionJobRow.jsx b/components/webui/imports/ui/IngestView/panels/IngestionJobs/IngestionJobRow.jsx new file mode 100644 index 000000000..3c4fd2500 --- /dev/null +++ b/components/webui/imports/ui/IngestView/panels/IngestionJobs/IngestionJobRow.jsx @@ -0,0 +1,90 @@ +import OverlayTrigger from "react-bootstrap/OverlayTrigger"; +import Spinner from "react-bootstrap/Spinner"; +import Tooltip from "react-bootstrap/Tooltip"; + +import dayjs from "dayjs"; + +import { + faCheck, + faClock, + faExclamation, +} from "@fortawesome/free-solid-svg-icons"; +import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; + +import { + COMPRESSION_JOB_STATUS, + COMPRESSION_JOB_STATUS_NAMES, +} from "/imports/api/ingestion/constants"; +import {computeHumanSize} from "/imports/utils/misc"; + + +/** + * Icons corresponding to different compression job statuses. + * + * @type {{[key: CompressionJobStatus]: import("@fortawesome/react-fontawesome").IconProp}} + */ +const COMPRESSION_JOB_STATUS_ICONS = Object.freeze({ + [COMPRESSION_JOB_STATUS.PENDING]: faClock, + [COMPRESSION_JOB_STATUS.SUCCEEDED]: faCheck, + [COMPRESSION_JOB_STATUS.FAILED]: faExclamation, +}); + +/** + * Renders an ingestion job. + * + * @param {import("/imports/api/ingestion/types").CompressionJob} job The job object containing + * information about the compression job. + * @return {React.ReactElement} + */ +const IngestionJobRow = ({job}) => { + let speedText = ""; + let uncompressedSizeText = ""; + let compressedSizeText = ""; + + if (null === job.duration && null !== job.start_time) { + job.duration = dayjs.duration( + dayjs() - dayjs(job.start_time) + ).asSeconds(); + } + if (0 < job.duration) { + speedText = `${computeHumanSize(job.uncompressed_size / job.duration)}/s`; + uncompressedSizeText = computeHumanSize(job.uncompressed_size); + compressedSizeText = computeHumanSize(job.compressed_size); + } + + return ( + + + + {COMPRESSION_JOB_STATUS_NAMES[job.status]} + {job.status_msg && (` - ${job.status_msg}`)} + + } + > + {COMPRESSION_JOB_STATUS.RUNNING === job.status ? + : + } + + + + {job._id} + + + {speedText} + + + {uncompressedSizeText} + + + {compressedSizeText} + + + ); +}; + +export default IngestionJobRow; diff --git a/components/webui/imports/ui/IngestView/panels/IngestionJobs/index.jsx b/components/webui/imports/ui/IngestView/panels/IngestionJobs/index.jsx new file mode 100644 index 000000000..9bce43931 --- /dev/null +++ b/components/webui/imports/ui/IngestView/panels/IngestionJobs/index.jsx @@ -0,0 +1,62 @@ +import {useTracker} from "meteor/react-meteor-data"; +import Table from "react-bootstrap/Table"; + +import {faBarsProgress} from "@fortawesome/free-solid-svg-icons"; + +import {CompressionJobsCollection} from "/imports/api/ingestion/collections"; +import {MONGO_SORT_BY_ID} from "/imports/utils/mongo"; + +import Panel from "../../Panel"; +import IngestionJobRow from "./IngestionJobRow"; + + +/** + * Displays a table of ingestion jobs. + * + * @return {React.ReactElement} + */ +const IngestionJobs = () => { + const compressionJobs = useTracker(() => { + Meteor.subscribe(Meteor.settings.public.CompressionJobsCollectionName); + + const findOptions = { + sort: [MONGO_SORT_BY_ID], + }; + + return CompressionJobsCollection.find({}, findOptions).fetch(); + }, []); + + if (0 === compressionJobs.length) { + return <>; + } + + return ( + + + + + + + + + + + + + {compressionJobs.map((job, i) => ( + + ))} + +
StatusJob IDSpeedData IngestedCompressed Size
+
+ ); +}; + +export default IngestionJobs; diff --git a/components/webui/imports/ui/SearchView/SearchView.jsx b/components/webui/imports/ui/SearchView/SearchView.jsx index 7c8a5b11c..6e97b554e 100644 --- a/components/webui/imports/ui/SearchView/SearchView.jsx +++ b/components/webui/imports/ui/SearchView/SearchView.jsx @@ -10,7 +10,6 @@ import { import {CLP_STORAGE_ENGINES} from "/imports/api/constants"; import {SearchResultsMetadataCollection} from "/imports/api/search/collections"; import { - MONGO_SORT_ORDER, SEARCH_MAX_NUM_RESULTS, SEARCH_RESULTS_FIELDS, SEARCH_SIGNAL, @@ -21,6 +20,10 @@ import { expandTimeRangeToDurationMultiple, } from "/imports/utils/datetime"; import {unquoteString} from "/imports/utils/misc"; +import { + MONGO_SORT_BY_ID, + MONGO_SORT_ORDER, +} from "/imports/utils/mongo"; import {LOCAL_STORAGE_KEYS} from "../constants"; import SearchControls from "./SearchControls"; @@ -117,10 +120,7 @@ const SearchView = () => { fieldToSortBy.name, fieldToSortBy.direction, ], - [ - SEARCH_RESULTS_FIELDS.ID, - fieldToSortBy.direction, - ], + MONGO_SORT_BY_ID, ], }; diff --git a/components/webui/imports/utils/DbManager.js b/components/webui/imports/utils/DbManager.js index c03c615ec..81a232343 100644 --- a/components/webui/imports/utils/DbManager.js +++ b/components/webui/imports/utils/DbManager.js @@ -1,12 +1,13 @@ import mysql from "mysql2/promise"; -import {logger} from "/imports/utils/logger"; - import { + deinitCompressionDbManager, deinitStatsDbManager, + initCompressionDbManager, initStatsDbManager, -} from "../api/ingestion/server/publications"; -import {initSearchJobsDbManager} from "../api/search/server/methods"; +} from "/imports/api/ingestion/server/publications"; +import {initSearchJobsDbManager} from "/imports/api/search/server/methods"; +import {logger} from "/imports/utils/logger"; const DB_CONNECTION_LIMIT = 2; @@ -28,9 +29,10 @@ let dbConnPool = null; * @param {string} dbConfig.dbPassword * @param {string} dbConfig.dbUser * @param {object} tableNames - * @param {string} tableNames.searchJobsTableName * @param {string} tableNames.clpArchivesTableName * @param {string} tableNames.clpFilesTableName + * @param {string} tableNames.compressionJobsTableName + * @param {string} tableNames.searchJobsTableName * @return {Promise} * @throws {Error} on error. */ @@ -41,9 +43,10 @@ const initDbManagers = async ({ dbPassword, dbUser, }, { - searchJobsTableName, clpArchivesTableName, clpFilesTableName, + compressionJobsTableName, + searchJobsTableName, }) => { if (null !== dbConnPool) { throw Error("This method should not be called twice."); @@ -62,6 +65,7 @@ const initDbManagers = async ({ bigNumberStrings: true, supportBigNumbers: true, + timezone: "Z", connectionLimit: DB_CONNECTION_LIMIT, enableKeepAlive: true, @@ -69,6 +73,9 @@ const initDbManagers = async ({ maxIdle: DB_MAX_IDLE, }); + initCompressionDbManager(dbConnPool, { + compressionJobsTableName, + }); initSearchJobsDbManager(dbConnPool, { searchJobsTableName, }); @@ -89,6 +96,7 @@ const initDbManagers = async ({ * @throws {Error} on error. */ const deinitDbManagers = async () => { + deinitCompressionDbManager(); deinitStatsDbManager(); await dbConnPool.end(); diff --git a/components/webui/imports/utils/mongo.js b/components/webui/imports/utils/mongo.js new file mode 100644 index 000000000..8719f3d52 --- /dev/null +++ b/components/webui/imports/utils/mongo.js @@ -0,0 +1,24 @@ +/** + * Enum of Mongo Collection sort orders. + * + * @enum {string} + */ +const MONGO_SORT_ORDER = Object.freeze({ + ASCENDING: "asc", + DESCENDING: "desc", +}); + +/** + * The sort order for MongoDB queries using the "_id" field. + * + * @type {string[]} + */ +const MONGO_SORT_BY_ID = Object.freeze([ + "_id", + MONGO_SORT_ORDER.DESCENDING, +]); + +export { + MONGO_SORT_BY_ID, + MONGO_SORT_ORDER, +}; diff --git a/components/webui/server/main.js b/components/webui/server/main.js index 13941f0b8..93992d1d3 100644 --- a/components/webui/server/main.js +++ b/components/webui/server/main.js @@ -64,9 +64,10 @@ Meteor.startup(async () => { dbPassword: envVars.CLP_DB_PASS, dbUser: envVars.CLP_DB_USER, }, { - searchJobsTableName: Meteor.settings.private.SqlDbSearchJobsTableName, clpArchivesTableName: Meteor.settings.private.SqlDbClpArchivesTableName, clpFilesTableName: Meteor.settings.private.SqlDbClpFilesTableName, + compressionJobsTableName: Meteor.settings.private.SqlDbCompressionJobsTableName, + searchJobsTableName: Meteor.settings.private.SqlDbSearchJobsTableName, }); }); diff --git a/components/webui/settings.json b/components/webui/settings.json index 5df6e90c7..e55c5126b 100644 --- a/components/webui/settings.json +++ b/components/webui/settings.json @@ -3,13 +3,16 @@ "SqlDbHost": "localhost", "SqlDbPort": 3306, "SqlDbName": "clp-db", - "SqlDbSearchJobsTableName": "search_jobs", + "SqlDbClpArchivesTableName": "clp_archives", - "SqlDbClpFilesTableName": "clp_files" + "SqlDbClpFilesTableName": "clp_files", + "SqlDbCompressionJobsTableName": "compression_jobs", + "SqlDbSearchJobsTableName": "search_jobs" }, "public": { "AggregationResultsCollectionName": "aggregation-results", "ClpStorageEngine": "clp", + "CompressionJobsCollectionName": "compression-jobs", "SearchResultsCollectionName": "search-results", "SearchResultsMetadataCollectionName": "results-metadata", "StatsCollectionName": "stats"