| /** |
| * Utility javascript functions used across the different CT FE pages. |
| */ |
| import { pad } from '../../infra-sk/modules/human'; |
| import { fromObject } from '../../infra-sk/modules/query'; |
| import { jsonOrThrow } from '../../infra-sk/modules/jsonOrThrow'; |
| import { errorMessage } from '../../elements-sk/modules/errorMessage'; |
| import { BenchmarksPlatformsResponse } from './json'; |
| |
| /** |
| * Converts the timestamp used in CTFE DB into a user friendly string. |
| */ |
| export function getFormattedTimestamp(timestamp: number): string { |
| if (!timestamp) { |
| return '<pending>'; |
| } |
| return getTimestamp(timestamp).toLocaleString(); |
| } |
| |
| /** |
| * Converts the timestamp used in CTFE DB into a Javascript timestamp. |
| */ |
| export function getTimestamp(timestamp: number): Date { |
| const date = new Date(); |
| if (!timestamp) { |
| return date; |
| } |
| // Timestamp is of the form YYYYMMDDhhmmss. |
| // Consume the pieces off the right to build the date. |
| const consumeDigits = (n: number) => { |
| const first_n_digits = timestamp % 10 ** n; |
| timestamp = (timestamp - first_n_digits) / 10 ** n; |
| return first_n_digits; |
| }; |
| date.setUTCSeconds(consumeDigits(2)); |
| date.setUTCMinutes(consumeDigits(2)); |
| date.setUTCHours(consumeDigits(2)); |
| date.setUTCDate(consumeDigits(2)); |
| date.setUTCMonth(consumeDigits(2) - 1); // Month is 0 based in JS. |
| date.setUTCFullYear(consumeDigits(4)); |
| return date; |
| } |
| |
| /** |
| * Convert from Javascript Date to timestamp recognized by CTFE DB. |
| */ |
| export function getCtDbTimestamp(d: Date): string { |
| const timestamp = |
| String(d.getUTCFullYear()) + |
| pad(d.getUTCMonth() + 1, 2) + |
| pad(d.getUTCDate(), 2) + |
| pad(d.getUTCHours(), 2) + |
| pad(d.getUTCMinutes(), 2) + |
| pad(d.getUTCSeconds(), 2); |
| return timestamp; |
| } |
| |
| /** |
| * Append gsPath with appropriate url to fetch from ct.skia.org. |
| */ |
| export function getGSLink(gsPath: string): string { |
| return `https://ct.skia.org/results/cluster-telemetry/${gsPath}`; |
| } |
| |
| /** |
| * Returns true if gsPath is not set or if the patch's SHA1 digest in the specified |
| * google storage path is for an empty string. |
| */ |
| export function isEmptyPatch(gsPath: string): boolean { |
| // Compare against empty string and against the SHA1 digest of an empty string. |
| return ( |
| gsPath === '' || |
| gsPath === 'patches/da39a3ee5e6b4b0d3255bfef95601890afd80709.patch' |
| ); |
| } |
| |
| /** |
| * Express numeric days in a readable format (e.g. 'Weekly'; 'Every 3 days') |
| */ |
| export function formatRepeatAfterDays(num: number): string { |
| if (num === 0) { |
| return 'N/A'; |
| } |
| if (num === 1) { |
| return 'Daily'; |
| } |
| if (num === 7) { |
| return 'Weekly'; |
| } |
| return `Every ${num} days`; |
| } |
| |
| /** |
| * Fetches benchmarks with doc links, and platforms with descriptions. |
| * |
| * @param {func<Object>} func - Function called with fetched benchmarks and |
| * platforms object. |
| */ |
| export function fetchBenchmarksAndPlatforms( |
| func: (json: BenchmarksPlatformsResponse) => void |
| ): void { |
| fetch('/_/benchmarks_platforms/', { |
| method: 'POST', |
| }) |
| .then(jsonOrThrow) |
| .then(func) |
| .catch(errorMessage); |
| } |
| |
| /** |
| * |
| * @param {Array<string>} descriptions - Array of CL descriptions, combined |
| * into a description string if at least one is noneempty. |
| * |
| * @returns string - Combined description. |
| */ |
| export function combineClDescriptions(descriptions: string[]): string { |
| const combinedDesc = descriptions |
| .filter(Boolean) |
| .reduce((str, desc) => (str += str === '' ? desc : ` and ${desc}`), ''); |
| return combinedDesc ? `Testing ${combinedDesc}` : ''; |
| } |
| |
| export function missingLiveSitesWithCustomWebpages( |
| customWebpages: string, |
| benchmarkArgs: string |
| ): boolean { |
| if (customWebpages && !benchmarkArgs.includes('--use-live-sites')) { |
| errorMessage( |
| 'Please specify --use-live-sites in benchmark arguments ' + |
| 'when using custom web pages.' |
| ); |
| return true; |
| } |
| return false; |
| } |
| |
| let activeTasks = 0; |
| /** |
| * Asynchronously queries the logged in user's active task count. |
| * This is best effort, so doesn't bother with returning a promise. |
| * |
| * @returns function() boolean : Whether or not the task count |
| * previously fetched is more than 3. |
| */ |
| export function moreThanThreeActiveTasksChecker(): () => boolean { |
| const queryParams = { |
| size: 1, |
| not_completed: true, |
| filter_by_logged_in_user: true, |
| }; |
| const queryStr = `?${fromObject(queryParams)}`; |
| |
| taskDescriptors.forEach((obj) => { |
| fetch(obj.get_url + queryStr, { |
| method: 'POST', |
| }) |
| .then(jsonOrThrow) |
| .then((json) => { |
| activeTasks += json.pagination.total; |
| }) |
| .catch(errorMessage); |
| }); |
| return () => { |
| if (activeTasks > 3) { |
| errorMessage( |
| `You have ${activeTasks} currently running tasks. Please wait` + |
| ' for them to complete before scheduling more CT tasks.' |
| ); |
| return true; |
| } |
| return false; |
| }; |
| } |
| |
| /** |
| * Used to describe the type and get/delete URLs of various CT tasks. |
| */ |
| export interface TaskDescriptor { |
| type: string; |
| get_url: string; |
| delete_url: string; |
| } |
| |
| /** |
| * List of task types and the associated urls to fetch and delete them. |
| */ |
| export const taskDescriptors: Array<TaskDescriptor> = [ |
| { |
| type: 'ChromiumPerf', |
| get_url: '/_/get_chromium_perf_tasks', |
| delete_url: '/_/delete_chromium_perf_task', |
| }, |
| { |
| type: 'ChromiumAnalysis', |
| get_url: '/_/get_chromium_analysis_tasks', |
| delete_url: '/_/delete_chromium_analysis_task', |
| }, |
| { |
| type: 'MetricsAnalysis', |
| get_url: '/_/get_metrics_analysis_tasks', |
| delete_url: '/_/delete_metrics_analysis_task', |
| }, |
| { |
| type: 'RecreatePageSets', |
| get_url: '/_/get_recreate_page_sets_tasks', |
| delete_url: '/_/delete_recreate_page_sets_task', |
| }, |
| { |
| type: 'RecreateWebpageArchives', |
| get_url: '/_/get_recreate_webpage_archives_tasks', |
| delete_url: '/_/delete_recreate_webpage_archives_task', |
| }, |
| ]; |