diff --git a/x-pack/plugins/task_manager/server/kibana_discovery_service/kibana_discovery_service.test.ts b/x-pack/plugins/task_manager/server/kibana_discovery_service/kibana_discovery_service.test.ts index 7a0d9f0b11ce5..5e2f6fcb4bfe3 100644 --- a/x-pack/plugins/task_manager/server/kibana_discovery_service/kibana_discovery_service.test.ts +++ b/x-pack/plugins/task_manager/server/kibana_discovery_service/kibana_discovery_service.test.ts @@ -26,6 +26,7 @@ describe('KibanaDiscoveryService', () => { beforeEach(() => { jest.useFakeTimers(); jest.spyOn(global, 'setTimeout'); + jest.spyOn(global, 'clearTimeout'); jest.setSystemTime(new Date(now)); }); @@ -180,6 +181,47 @@ describe('KibanaDiscoveryService', () => { "Kibana Discovery Service couldn't update this node's last_seen timestamp. id: current-node-id, last_seen: 2024-08-10T10:00:10.000Z, error:foo" ); }); + + it('does not schedule when Kibana is shutting down', async () => { + savedObjectsRepository.update.mockResolvedValueOnce( + {} as SavedObjectsUpdateResponse + ); + + const kibanaDiscoveryService = new KibanaDiscoveryService({ + savedObjectsRepository, + logger, + currentNode, + config: { + active_nodes_lookback: DEFAULT_ACTIVE_NODES_LOOK_BACK_DURATION, + interval: DEFAULT_DISCOVERY_INTERVAL_MS, + }, + }); + await kibanaDiscoveryService.start(); + + expect(savedObjectsRepository.update).toHaveBeenCalledTimes(1); + expect(logger.error).not.toHaveBeenCalled(); + expect(logger.info).toHaveBeenCalledWith('Kibana Discovery Service has been started'); + expect(kibanaDiscoveryService.isStarted()).toBe(true); + expect(setTimeout).toHaveBeenCalledTimes(1); + expect(setTimeout).toHaveBeenNthCalledWith( + 1, + expect.any(Function), + DEFAULT_DISCOVERY_INTERVAL_MS + ); + + kibanaDiscoveryService.stop(); + + await jest.advanceTimersByTimeAsync(15000); + + expect(savedObjectsRepository.update).toHaveBeenCalledTimes(1); + expect(setTimeout).toHaveBeenCalledTimes(1); + expect(setTimeout).toHaveBeenNthCalledWith( + 1, + expect.any(Function), + DEFAULT_DISCOVERY_INTERVAL_MS + ); + expect(clearTimeout).toHaveBeenCalledTimes(1); + }); }); describe('getActiveKibanaNodes', () => { diff --git a/x-pack/plugins/task_manager/server/kibana_discovery_service/kibana_discovery_service.ts b/x-pack/plugins/task_manager/server/kibana_discovery_service/kibana_discovery_service.ts index c532cb755f7d9..5777020acfbb4 100644 --- a/x-pack/plugins/task_manager/server/kibana_discovery_service/kibana_discovery_service.ts +++ b/x-pack/plugins/task_manager/server/kibana_discovery_service/kibana_discovery_service.ts @@ -30,6 +30,8 @@ export class KibanaDiscoveryService { private started = false; private savedObjectsRepository: ISavedObjectsRepository; private logger: Logger; + private stopped = false; + private timer: NodeJS.Timeout | undefined; constructor({ config, currentNode, savedObjectsRepository, logger }: DiscoveryServiceParams) { this.activeNodesLookBack = config.active_nodes_lookback; @@ -52,29 +54,35 @@ export class KibanaDiscoveryService { } private async scheduleUpsertCurrentNode() { - const lastSeenDate = new Date(); - const lastSeen = lastSeenDate.toISOString(); - try { - await this.upsertCurrentNode({ id: this.currentNode, lastSeen }); - if (!this.started) { - this.logger.info('Kibana Discovery Service has been started'); - this.started = true; - } - } catch (e) { - if (!this.started) { - this.logger.error( - `Kibana Discovery Service couldn't be started and will be retried in ${this.discoveryInterval}ms, error:${e.message}` - ); - } else { - this.logger.error( - `Kibana Discovery Service couldn't update this node's last_seen timestamp. id: ${this.currentNode}, last_seen: ${lastSeen}, error:${e.message}` + if (!this.stopped) { + const lastSeenDate = new Date(); + const lastSeen = lastSeenDate.toISOString(); + try { + await this.upsertCurrentNode({ id: this.currentNode, lastSeen }); + if (!this.started) { + this.logger.info('Kibana Discovery Service has been started'); + this.started = true; + } + } catch (e) { + if (!this.started) { + this.logger.error( + `Kibana Discovery Service couldn't be started and will be retried in ${this.discoveryInterval}ms, error:${e.message}` + ); + } else { + this.logger.error( + `Kibana Discovery Service couldn't update this node's last_seen timestamp. id: ${this.currentNode}, last_seen: ${lastSeen}, error:${e.message}` + ); + } + } finally { + this.timer = setTimeout( + async () => await this.scheduleUpsertCurrentNode(), + this.discoveryInterval - (Date.now() - lastSeenDate.getTime()) ); } - } finally { - setTimeout( - async () => await this.scheduleUpsertCurrentNode(), - this.discoveryInterval - (Date.now() - lastSeenDate.getTime()) - ); + } else { + if (this.timer) { + clearTimeout(this.timer); + } } } @@ -106,4 +114,8 @@ export class KibanaDiscoveryService { await this.savedObjectsRepository.delete(BACKGROUND_TASK_NODE_SO_NAME, this.currentNode); this.logger.info('Removed this node from the Kibana Discovery Service'); } + + public stop() { + this.stopped = true; + } } diff --git a/x-pack/plugins/task_manager/server/plugin.ts b/x-pack/plugins/task_manager/server/plugin.ts index 1d2ab4a84580b..d7c3cd7e941fc 100644 --- a/x-pack/plugins/task_manager/server/plugin.ts +++ b/x-pack/plugins/task_manager/server/plugin.ts @@ -404,6 +404,7 @@ export class TaskManagerPlugin public async stop() { if (this.kibanaDiscoveryService?.isStarted()) { + this.kibanaDiscoveryService.stop(); try { await this.kibanaDiscoveryService.deleteCurrentNode(); } catch (e) { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/monitoring.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/monitoring.ts index a86db4a8c27e4..42747c371f9b2 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/monitoring.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/monitoring.ts @@ -14,8 +14,7 @@ import { FtrProviderContext } from '../../../../common/ftr_provider_context'; export default function monitoringAlertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - // Failing: See https://github.com/elastic/kibana/issues/193072 - describe.skip('monitoring', () => { + describe('monitoring', () => { const objectRemover = new ObjectRemover(supertest); after(async () => await objectRemover.removeAll()); @@ -24,7 +23,7 @@ export default function monitoringAlertTests({ getService }: FtrProviderContext) const createResponse = await supertest .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) .set('kbn-xsrf', 'foo') - .send(getTestRuleData({ schedule: { interval: '3s' } })); + .send(getTestRuleData({ schedule: { interval: '1h' } })); expect(createResponse.status).to.eql(200); objectRemover.add(Spaces.space1.id, createResponse.body.id, 'rule', 'alerting'); @@ -57,7 +56,7 @@ export default function monitoringAlertTests({ getService }: FtrProviderContext) ); expect(getResponse.status).to.eql(200); - expect(getResponse.body.monitoring.run.history.length).to.be(3); + expect(getResponse.body.monitoring.run.history.length >= 3).to.be(true); expect(getResponse.body.monitoring.run.history[0].success).to.be(true); expect(getResponse.body.monitoring.run.history[1].success).to.be(true); expect(getResponse.body.monitoring.run.history[2].success).to.be(true); @@ -89,7 +88,7 @@ export default function monitoringAlertTests({ getService }: FtrProviderContext) ); expect(getResponse.status).to.eql(200); - expect(getResponse.body.monitoring.run.history.length).to.be(5); + expect(getResponse.body.monitoring.run.history.length >= 5).to.be(true); expect(getResponse.body.monitoring.run.history[0].success).to.be(true); expect(getResponse.body.monitoring.run.history[1].success).to.be(true); expect(getResponse.body.monitoring.run.history[2].success).to.be(true);