Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1669,7 +1669,7 @@
"@types/selenium-webdriver": "^4.1.28",
"@types/semver": "^7.7.0",
"@types/set-value": "^4.0.3",
"@types/sinon": "^7.0.13",
"@types/sinon": "^17.0.3",
"@types/source-map-support": "^0.5.10",
"@types/stats-lite": "^2.2.0",
"@types/styled-components": "^5.1.0",
Expand Down Expand Up @@ -1843,7 +1843,7 @@
"selenium-webdriver": "^4.33.0",
"sharp": "0.32.6",
"simple-git": "^3.27.0",
"sinon": "^7.4.2",
"sinon": "^19.0.2",
"sort-package-json": "^3.2.1",
"source-map": "^0.7.4",
"storybook": "^8.6.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* 2.0.
*/

import sinon from 'sinon';
import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock';
import {
RuleExecutorOptions,
Expand Down Expand Up @@ -125,7 +124,6 @@ jest.mock('../lib/alerting_event_logger/alerting_event_logger');
jest.mock('../rules_client/lib/get_alert_from_raw');
const mockGetAlertFromRaw = getAlertFromRaw as jest.MockedFunction<typeof getAlertFromRaw>;

let fakeTimer: sinon.SinonFakeTimers;
const logger: ReturnType<typeof loggingSystemMock.createLogger> = loggingSystemMock.createLogger();
const taskRunnerLogger = createTaskRunnerLogger({ logger, tags: ['1', 'test'] });

Expand Down Expand Up @@ -162,11 +160,12 @@ describe('Task Runner', () => {
let mockedTaskInstance: ConcreteTaskInstance;

beforeAll(() => {
fakeTimer = sinon.useFakeTimers();
jest.useFakeTimers();
jest.setSystemTime(new Date(DATE_1970));
mockedTaskInstance = mockTaskInstance();
});

afterAll(() => fakeTimer.restore());
afterAll(() => jest.useRealTimers());

const encryptedSavedObjectsClient = encryptedSavedObjectsMock.createClient();
const internalSavedObjectsRepository = savedObjectsRepositoryMock.create();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* 2.0.
*/

import sinon from 'sinon';
import { Subject } from 'rxjs';
import { SavedObjectsErrorHelpers } from '@kbn/core/server';
import {
Expand All @@ -19,15 +18,17 @@ import { MsearchError } from './msearch_error';
import { BulkUpdateError } from './bulk_update_error';

describe('createManagedConfiguration()', () => {
let clock: sinon.SinonFakeTimers;
const logger = mockLogger();

beforeAll(() => {
jest.useFakeTimers();
});

beforeEach(() => {
jest.resetAllMocks();
clock = sinon.useFakeTimers();
});

afterEach(() => clock.restore());
afterAll(() => jest.useRealTimers());

test('returns observables with initialized values', async () => {
const capacitySubscription = jest.fn();
Expand Down Expand Up @@ -143,7 +144,7 @@ describe('createManagedConfiguration()', () => {
capacityConfiguration$.subscribe(capacitySubscription);
pollIntervalConfiguration$.subscribe(pollIntervalSubscription);
errors$.next(new Error('foo'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL);
expect(capacitySubscription).toHaveBeenCalledTimes(1);
expect(pollIntervalSubscription).toHaveBeenCalledTimes(1);
});
Expand All @@ -168,51 +169,44 @@ describe('createManagedConfiguration()', () => {
return { subscription, errors$ };
}

beforeEach(() => {
jest.resetAllMocks();
clock = sinon.useFakeTimers();
});

afterEach(() => clock.restore());

describe('default claim strategy', () => {
test('should decrease configuration at the next interval when an error is emitted', async () => {
const { subscription, errors$ } = setupScenario(10);
errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1);
expect(subscription).toHaveBeenCalledTimes(1);
expect(subscription).toHaveBeenNthCalledWith(1, 10);
clock.tick(1);
jest.advanceTimersByTime(1);
expect(subscription).toHaveBeenCalledTimes(2);
expect(subscription).toHaveBeenNthCalledWith(2, 8);
});

test('should decrease configuration at the next interval when a 500 error is emitted', async () => {
const { subscription, errors$ } = setupScenario(10);
errors$.next(SavedObjectsErrorHelpers.decorateGeneralError(new Error('a'), 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1);
expect(subscription).toHaveBeenCalledTimes(1);
expect(subscription).toHaveBeenNthCalledWith(1, 10);
clock.tick(1);
jest.advanceTimersByTime(1);
expect(subscription).toHaveBeenCalledTimes(2);
expect(subscription).toHaveBeenNthCalledWith(2, 8);
});

test('should decrease configuration at the next interval when a 503 error is emitted', async () => {
const { subscription, errors$ } = setupScenario(10);
errors$.next(SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError('a', 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1);
expect(subscription).toHaveBeenCalledTimes(1);
expect(subscription).toHaveBeenNthCalledWith(1, 10);
clock.tick(1);
jest.advanceTimersByTime(1);
expect(subscription).toHaveBeenCalledTimes(2);
expect(subscription).toHaveBeenNthCalledWith(2, 8);
});

test('should log a warning when the configuration changes from the starting value', async () => {
const { errors$ } = setupScenario(10);
errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL);
expect(logger.warn).toHaveBeenCalledWith(
'Capacity configuration is temporarily reduced after Elasticsearch returned 1 "too many request" and/or "execute [inline] script" error(s).'
);
Expand All @@ -221,7 +215,7 @@ describe('createManagedConfiguration()', () => {
test('should increase configuration back to normal incrementally after an error is emitted', async () => {
const { subscription, errors$ } = setupScenario(10);
errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL * 10);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL * 10);
expect(subscription).toHaveBeenNthCalledWith(1, 10);
expect(subscription).toHaveBeenNthCalledWith(2, 8);
expect(subscription).toHaveBeenNthCalledWith(3, 9);
Expand All @@ -234,7 +228,7 @@ describe('createManagedConfiguration()', () => {
const { subscription, errors$ } = setupScenario(10);
for (let i = 0; i < 20; i++) {
errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL);
}
expect(subscription).toHaveBeenNthCalledWith(1, 10);
expect(subscription).toHaveBeenNthCalledWith(2, 8);
Expand All @@ -252,32 +246,32 @@ describe('createManagedConfiguration()', () => {
test('should decrease configuration at the next interval when an msearch 429 error is emitted', async () => {
const { subscription, errors$ } = setupScenario(10);
errors$.next(new MsearchError(429));
clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1);
expect(subscription).toHaveBeenCalledTimes(1);
expect(subscription).toHaveBeenNthCalledWith(1, 10);
clock.tick(1);
jest.advanceTimersByTime(1);
expect(subscription).toHaveBeenCalledTimes(2);
expect(subscription).toHaveBeenNthCalledWith(2, 8);
});

test('should decrease configuration at the next interval when an msearch 500 error is emitted', async () => {
const { subscription, errors$ } = setupScenario(10);
errors$.next(new MsearchError(500));
clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1);
expect(subscription).toHaveBeenCalledTimes(1);
expect(subscription).toHaveBeenNthCalledWith(1, 10);
clock.tick(1);
jest.advanceTimersByTime(1);
expect(subscription).toHaveBeenCalledTimes(2);
expect(subscription).toHaveBeenNthCalledWith(2, 8);
});

test('should decrease configuration at the next interval when an msearch 503 error is emitted', async () => {
const { subscription, errors$ } = setupScenario(10);
errors$.next(new MsearchError(503));
clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1);
expect(subscription).toHaveBeenCalledTimes(1);
expect(subscription).toHaveBeenNthCalledWith(1, 10);
clock.tick(1);
jest.advanceTimersByTime(1);
expect(subscription).toHaveBeenCalledTimes(2);
expect(subscription).toHaveBeenNthCalledWith(2, 8);
});
Expand All @@ -287,10 +281,10 @@ describe('createManagedConfiguration()', () => {
errors$.next(
new BulkUpdateError({ statusCode: 429, message: 'test', type: 'too_many_requests' })
);
clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1);
expect(subscription).toHaveBeenCalledTimes(1);
expect(subscription).toHaveBeenNthCalledWith(1, 10);
clock.tick(1);
jest.advanceTimersByTime(1);
expect(subscription).toHaveBeenCalledTimes(2);
expect(subscription).toHaveBeenNthCalledWith(2, 8);
});
Expand All @@ -300,10 +294,10 @@ describe('createManagedConfiguration()', () => {
errors$.next(
new BulkUpdateError({ statusCode: 500, message: 'test', type: 'server_error' })
);
clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1);
expect(subscription).toHaveBeenCalledTimes(1);
expect(subscription).toHaveBeenNthCalledWith(1, 10);
clock.tick(1);
jest.advanceTimersByTime(1);
expect(subscription).toHaveBeenCalledTimes(2);
expect(subscription).toHaveBeenNthCalledWith(2, 8);
});
Expand All @@ -313,28 +307,28 @@ describe('createManagedConfiguration()', () => {
errors$.next(
new BulkUpdateError({ statusCode: 503, message: 'test', type: 'unavailable' })
);
clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1);
expect(subscription).toHaveBeenCalledTimes(1);
expect(subscription).toHaveBeenNthCalledWith(1, 10);
clock.tick(1);
jest.advanceTimersByTime(1);
expect(subscription).toHaveBeenCalledTimes(2);
expect(subscription).toHaveBeenNthCalledWith(2, 8);
});

test('should not change configuration at the next interval when other msearch error is emitted', async () => {
const { subscription, errors$ } = setupScenario(10);
errors$.next(new MsearchError(404));
clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1);
expect(subscription).toHaveBeenCalledTimes(1);
expect(subscription).toHaveBeenNthCalledWith(1, 10);
clock.tick(1);
jest.advanceTimersByTime(1);
expect(subscription).toHaveBeenCalledTimes(1);
});

test('should log a warning when the configuration changes from the starting value', async () => {
const { errors$ } = setupScenario(10, CLAIM_STRATEGY_MGET);
errors$.next(new MsearchError(429));
clock.tick(ADJUST_THROUGHPUT_INTERVAL);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL);
expect(logger.warn).toHaveBeenCalledWith(
'Capacity configuration is temporarily reduced after Elasticsearch returned 1 "too many request" and/or "execute [inline] script" error(s).'
);
Expand All @@ -343,7 +337,7 @@ describe('createManagedConfiguration()', () => {
test('should increase configuration back to normal incrementally after an error is emitted', async () => {
const { subscription, errors$ } = setupScenario(10, CLAIM_STRATEGY_MGET);
errors$.next(new MsearchError(429));
clock.tick(ADJUST_THROUGHPUT_INTERVAL * 10);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL * 10);
expect(subscription).toHaveBeenNthCalledWith(1, 10);
expect(subscription).toHaveBeenNthCalledWith(2, 8);
expect(subscription).toHaveBeenNthCalledWith(3, 9);
Expand All @@ -356,7 +350,7 @@ describe('createManagedConfiguration()', () => {
const { subscription, errors$ } = setupScenario(10, CLAIM_STRATEGY_MGET);
for (let i = 0; i < 20; i++) {
errors$.next(new MsearchError(429));
clock.tick(ADJUST_THROUGHPUT_INTERVAL);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL);
}
expect(subscription).toHaveBeenNthCalledWith(1, 10);
expect(subscription).toHaveBeenNthCalledWith(2, 8);
Expand Down Expand Up @@ -384,39 +378,32 @@ describe('createManagedConfiguration()', () => {
return { subscription, errors$ };
}

beforeEach(() => {
jest.resetAllMocks();
clock = sinon.useFakeTimers();
});

afterEach(() => clock.restore());

test('should increase configuration at the next interval when an error is emitted', async () => {
const { subscription, errors$ } = setupScenario(100);
errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1);
expect(subscription).toHaveBeenCalledTimes(1);
clock.tick(1);
jest.advanceTimersByTime(1);
expect(subscription).toHaveBeenCalledTimes(2);
expect(subscription).toHaveBeenNthCalledWith(2, 120);
});

test('should increase configuration at the next interval when a 500 error is emitted', async () => {
const { subscription, errors$ } = setupScenario(100);
errors$.next(SavedObjectsErrorHelpers.decorateGeneralError(new Error('a'), 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1);
expect(subscription).toHaveBeenCalledTimes(1);
clock.tick(1);
jest.advanceTimersByTime(1);
expect(subscription).toHaveBeenCalledTimes(2);
expect(subscription).toHaveBeenNthCalledWith(2, 120);
});

test('should increase configuration at the next interval when a 503 error is emitted', async () => {
const { subscription, errors$ } = setupScenario(100);
errors$.next(SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError('a', 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL - 1);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL - 1);
expect(subscription).toHaveBeenCalledTimes(1);
clock.tick(1);
jest.advanceTimersByTime(1);
expect(subscription).toHaveBeenCalledTimes(2);
expect(subscription).toHaveBeenNthCalledWith(2, 120);
});
Expand All @@ -433,41 +420,14 @@ describe('createManagedConfiguration()', () => {
expect(subscription).toHaveBeenNthCalledWith(1, 100);
// It emits the error with cluster_block_exception type immediately
expect(subscription).toHaveBeenNthCalledWith(2, INTERVAL_AFTER_BLOCK_EXCEPTION);
clock.tick(INTERVAL_AFTER_BLOCK_EXCEPTION);
jest.advanceTimersByTime(INTERVAL_AFTER_BLOCK_EXCEPTION);
expect(subscription).toHaveBeenCalledTimes(3);
expect(subscription).toHaveBeenNthCalledWith(3, 100);
});

test('should log a warning when the configuration changes from the starting value', async () => {
const { errors$ } = setupScenario(100);
errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL);
expect(logger.warn).toHaveBeenCalledWith(
'Poll interval configuration is temporarily increased after Elasticsearch returned 1 "too many request" and/or "execute [inline] script" and/or "cluster_block_exception" error(s).'
);
});

test('should log a warning when an issue occurred in the calculating of the increased poll interval', async () => {
const { errors$ } = setupScenario(NaN);
errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL);
expect(logger.error).toHaveBeenCalledWith(
'Poll interval configuration had an issue calculating the new poll interval: Math.min(Math.ceil(NaN * 1.2), Math.max(60000, NaN)) = NaN, will keep the poll interval unchanged (NaN)'
);
});

test('should log a warning when an issue occurred in the calculating of the decreased poll interval', async () => {
setupScenario(NaN);
clock.tick(ADJUST_THROUGHPUT_INTERVAL);
expect(logger.error).toHaveBeenCalledWith(
'Poll interval configuration had an issue calculating the new poll interval: Math.max(NaN, Math.floor(NaN * 0.95)) = NaN, will keep the poll interval unchanged (NaN)'
);
});

test('should decrease configuration back to normal incrementally after an error is emitted', async () => {
const { subscription, errors$ } = setupScenario(100);
errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL * 10);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL * 10);
expect(subscription).toHaveBeenNthCalledWith(2, 120);
expect(subscription).toHaveBeenNthCalledWith(3, 114);
// 108.3 -> 108 from Math.floor
Expand All @@ -483,7 +443,7 @@ describe('createManagedConfiguration()', () => {
const { subscription, errors$ } = setupScenario(100);
for (let i = 0; i < 3; i++) {
errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL);
}
expect(subscription).toHaveBeenNthCalledWith(2, 120);
expect(subscription).toHaveBeenNthCalledWith(3, 144);
Expand All @@ -495,7 +455,7 @@ describe('createManagedConfiguration()', () => {
const { subscription, errors$ } = setupScenario(3000);
for (let i = 0; i < 18; i++) {
errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL);
}
expect(subscription).toHaveBeenNthCalledWith(2, 3600);
expect(subscription).toHaveBeenNthCalledWith(3, 4320);
Expand All @@ -520,7 +480,7 @@ describe('createManagedConfiguration()', () => {
const { subscription, errors$ } = setupScenario(65000);
for (let i = 0; i < 5; i++) {
errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b'));
clock.tick(ADJUST_THROUGHPUT_INTERVAL);
jest.advanceTimersByTime(ADJUST_THROUGHPUT_INTERVAL);
}
expect(subscription).toHaveBeenCalledTimes(1);
expect(subscription).toHaveBeenNthCalledWith(1, 65000);
Expand Down
Loading