diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/telemetry_task.js b/x-pack/legacy/plugins/maps/server/maps_telemetry/telemetry_task.js index 6e134a483018f..e5e82635a4912 100644 --- a/x-pack/legacy/plugins/maps/server/maps_telemetry/telemetry_task.js +++ b/x-pack/legacy/plugins/maps/server/maps_telemetry/telemetry_task.js @@ -27,7 +27,7 @@ export function scheduleTask(server, taskManager) { taskType: TELEMETRY_TASK_TYPE, state: { stats: {}, runs: 0 }, }); - }catch(e) { + } catch(e) { server.log(['warning', 'maps'], `Error scheduling telemetry task, received ${e.message}`); } })(); @@ -52,32 +52,65 @@ export function telemetryTaskRunner(server) { return ({ taskInstance }) => { const { state } = taskInstance; const prevState = state; - let mapsTelemetry = {}; const callCluster = server.plugins.elasticsearch.getCluster('admin') .callWithInternalUser; + let mapsTelemetryTask; + return { - async run() { + async run({ taskCanceled = false } = {}) { try { - mapsTelemetry = await getMapsTelemetry(server, callCluster); + mapsTelemetryTask = makeCancelable( + getMapsTelemetry(server, callCluster), + taskCanceled + ); } catch (err) { server.log(['warning'], `Error loading maps telemetry: ${err}`); } finally { - return { - state: { - runs: state.runs || 0 + 1, - stats: mapsTelemetry.attributes || prevState.stats || {}, - }, - runAt: getNextMidnight(), - }; + return mapsTelemetryTask + .promise + .then((mapsTelemetry = {}) => { + return { + state: { + runs: state.runs || 0 + 1, + stats: mapsTelemetry.attributes || prevState.stats || {}, + }, + runAt: getNextMidnight(), + }; + }) + .catch(errMsg => server.log(['warning'], + `Error executing maps telemetry task: ${errMsg}`)); } }, + async cancel() { + if (mapsTelemetryTask) { + mapsTelemetryTask.cancel(); + } else { + server.log(['warning'], `Can not cancel "mapsTelemetryTask", it has not been defined`); + } + } }; }; } -export function getNextMidnight() { +function makeCancelable(promise, isCanceled) { + const logMsg = 'Maps telemetry task has been cancelled'; + const wrappedPromise = new Promise((resolve, reject) => { + promise + .then(val => isCanceled ? reject(logMsg) : resolve(val)) + .catch(err => isCanceled ? reject(logMsg) : reject(err.message)); + }); + + return { + promise: wrappedPromise, + cancel() { + isCanceled = true; + }, + }; +} + +function getNextMidnight() { const nextMidnight = new Date(); nextMidnight.setHours(0, 0, 0, 0); nextMidnight.setDate(nextMidnight.getDate() + 1); diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/telemetry_task.test.js b/x-pack/legacy/plugins/maps/server/maps_telemetry/telemetry_task.test.js index 71e92b9af5d7c..d5d90e8a11335 100644 --- a/x-pack/legacy/plugins/maps/server/maps_telemetry/telemetry_task.test.js +++ b/x-pack/legacy/plugins/maps/server/maps_telemetry/telemetry_task.test.js @@ -4,39 +4,68 @@ * you may not use this file except in compliance with the Elastic License. */ -import moment from 'moment'; import { getMockKbnServer, getMockTaskInstance, } from '../test_utils'; import { telemetryTaskRunner } from './telemetry_task'; +import * as mapsTelemetry from './maps_telemetry'; +jest.mock('./maps_telemetry'); + +const expectedAttributes = { + expect: 'values', + toBe: 'populated' +}; + +const generateTelemetry = ({ includeAttributes = true } = {}) => { + mapsTelemetry.getMapsTelemetry = async () => ({ // eslint-disable-line + attributes: includeAttributes ? expectedAttributes : {} + }); +}; describe('telemetryTaskRunner', () => { let mockTaskInstance; let mockKbnServer; + let taskRunner; + beforeEach(() => { mockTaskInstance = getMockTaskInstance(); mockKbnServer = getMockKbnServer(); + taskRunner = telemetryTaskRunner(mockKbnServer)({ taskInstance: mockTaskInstance }); }); - test('Returns empty stats on error', async () => { - const getNextMidnight = () => - moment() - .add(1, 'days') - .startOf('day') - .toDate(); + test('returns empty stats as default', async () => { + generateTelemetry({ includeAttributes: false }); - const getRunner = telemetryTaskRunner(mockKbnServer); - const runResult = await getRunner( - { taskInstance: mockTaskInstance } - ).run(); + const runResult = await taskRunner.run(); expect(runResult).toMatchObject({ - runAt: getNextMidnight(), state: { runs: 1, stats: {}, }, }); }); + + // Return stats when run normally + test('returns stats normally', async () => { + generateTelemetry(); + + const runResult = await taskRunner.run(); + + expect(runResult).toMatchObject({ + state: { + runs: 1, + stats: expectedAttributes, + }, + }); + }); + + test('cancels when cancel flag set to "true", returns undefined', async () => { + generateTelemetry(); + + const runResult = await taskRunner.run({ taskCanceled: true }); + + expect(runResult).toBe(undefined); + }); });