Skip to content

Commit

Permalink
feat: set slower backoff for current context
Browse files Browse the repository at this point in the history
Signed-off-by: Philippe Martin <[email protected]>
  • Loading branch information
feloy committed Oct 16, 2024
1 parent 57090e1 commit 0fb3ec2
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 15 deletions.
8 changes: 4 additions & 4 deletions packages/main/src/plugin/kubernetes/backoff.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { expect, test } from 'vitest';
import { Backoff } from './backoff.js';

test('backoff increment and limit without jitter', () => {
const backoff = new Backoff(100, 500, 0);
const backoff = new Backoff(100, 2, 500, 0);
expect(backoff.get()).toEqual(100);
expect(backoff.get()).toEqual(200);
expect(backoff.get()).toEqual(400);
Expand All @@ -32,15 +32,15 @@ test('backoff increment and limit without jitter', () => {
test('backoff with jitter', () => {
let jitterFound = false;
let base = 100;
let backoff: Backoff = new Backoff(base, 500, 10);
let backoff: Backoff = new Backoff(base, 2, 500, 10);
// run several tests, as we cannot rely on a single one due to the random nature
for (let i = 0; i < 10; i++) {
const value = backoff.get();
expect(value).not.toBeLessThan(base);
expect(value).toBeLessThan(base * 1.1);
if (value === base) {
// this can happen, try again
backoff = new Backoff(base, 500, 10);
backoff = new Backoff(base, 2, 500, 10);
continue;
}
jitterFound = true;
Expand All @@ -54,7 +54,7 @@ test('backoff with jitter', () => {
});

test('backoff reset', () => {
const backoff = new Backoff(100, 500, 0);
const backoff = new Backoff(100, 2, 500, 0);
expect(backoff.get()).toBe(100);
expect(backoff.get()).toBe(200);
expect(backoff.get()).toBe(400);
Expand Down
3 changes: 2 additions & 1 deletion packages/main/src/plugin/kubernetes/backoff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class Backoff {
private readonly initial: number;
constructor(
public value: number,
public multiplier: number,
private readonly max: number,
private readonly jitter: number,
) {
Expand All @@ -29,7 +30,7 @@ export class Backoff {
get(): number {
const current = this.value;
if (this.value < this.max) {
this.value *= 2;
this.value *= this.multiplier;
this.value += this.getJitter();
}
return current;
Expand Down
6 changes: 6 additions & 0 deletions packages/main/src/plugin/kubernetes/contexts-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,14 @@
export const connectTimeout = 1000;
// initial delay between two connection attempts
export const backoffInitialValue = 1000;
// the backoff will be multiplied by this number every time
export const backoffMultiplier = 2.0;
// the backoff will be multiplied by this number every time for current context
export const backoffMultiplierCurrentContext = 1.2;
// maximum delay between two connection attempts
export const backoffLimit = 60_000;
// maximum delay between two connection attempts for current context
export const backoffLimitCurrentContext = 10_000;
// jitter to add to the delay between two connection attempts
export const backoffJitter = 300;
// the time to wait for any update on the data to dispatch before to send it
Expand Down
3 changes: 3 additions & 0 deletions packages/main/src/plugin/kubernetes/contexts-manager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ vi.mock('./contexts-constants.js', () => {
return {
connectTimeout: 1,
backoffInitialValue: 10000,
backoffMultiplier: 2.0,
backoffMultiplierCurrentContext: 1.2,
backoffLimit: 1000,
backoffLimitCurrentContext: 1000,
backoffJitter: 0,
dispatchTimeout: 1,
};
Expand Down
41 changes: 31 additions & 10 deletions packages/main/src/plugin/kubernetes/contexts-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,15 @@ import type { V1Route } from '/@api/openshift-types.js';

import type { ApiSenderType } from '../api.js';
import { Backoff } from './backoff.js';
import { backoffInitialValue, backoffJitter, backoffLimit, connectTimeout } from './contexts-constants.js';
import {
backoffInitialValue,
backoffJitter,
backoffLimit,
backoffLimitCurrentContext,
backoffMultiplier,
backoffMultiplierCurrentContext,
connectTimeout,
} from './contexts-constants.js';
import { ContextsInformersRegistry } from './contexts-informers-registry.js';
import type { ContextInternalState } from './contexts-states-registry.js';
import { ContextsStatesRegistry, dispatchAllResources, isSecondaryResourceName } from './contexts-states-registry.js';
Expand Down Expand Up @@ -379,7 +387,7 @@ export class ContextsManager {
checkReachable: true,
resource: 'pods',
timer: timer,
backoff: new Backoff(backoffInitialValue, backoffLimit, backoffJitter),
backoff: this.getBackoffForContext(context.name),
connectionDelay: connectionDelay,
onAdd: obj => {
this.states.setStateAndDispatch(context.name, {
Expand Down Expand Up @@ -447,7 +455,7 @@ export class ContextsManager {
return this.createInformer<V1Deployment>(kc, context, path, listFn, {
resource: 'deployments',
timer: timer,
backoff: new Backoff(backoffInitialValue, backoffLimit, backoffJitter),
backoff: this.getBackoffForContext(context.name),
connectionDelay: connectionDelay,
onAdd: obj => {
this.states.setStateAndDispatch(context.name, {
Expand Down Expand Up @@ -494,7 +502,7 @@ export class ContextsManager {
return this.createInformer<V1ConfigMap>(kc, context, path, listFn, {
resource: 'configmaps',
timer: timer,
backoff: new Backoff(backoffInitialValue, backoffLimit, backoffJitter),
backoff: this.getBackoffForContext(context.name),
connectionDelay: connectionDelay,
onAdd: obj => {
this.states.setStateAndDispatch(context.name, {
Expand Down Expand Up @@ -536,7 +544,7 @@ export class ContextsManager {
return this.createInformer<V1Secret>(kc, context, path, listFn, {
resource: 'secrets',
timer: timer,
backoff: new Backoff(backoffInitialValue, backoffLimit, backoffJitter),
backoff: this.getBackoffForContext(context.name),
connectionDelay: connectionDelay,
onAdd: obj => {
this.states.setStateAndDispatch(context.name, {
Expand Down Expand Up @@ -581,7 +589,7 @@ export class ContextsManager {
return this.createInformer<V1PersistentVolumeClaim>(kc, context, path, listFn, {
resource: 'persistentvolumeclaims',
timer: timer,
backoff: new Backoff(backoffInitialValue, backoffLimit, backoffJitter),
backoff: this.getBackoffForContext(context.name),
connectionDelay: connectionDelay,
onAdd: obj => {
this.states.setStateAndDispatch(context.name, {
Expand Down Expand Up @@ -625,7 +633,7 @@ export class ContextsManager {
return this.createInformer<V1Node>(kc, context, path, listFn, {
resource: 'nodes',
timer: timer,
backoff: new Backoff(backoffInitialValue, backoffLimit, backoffJitter),
backoff: this.getBackoffForContext(context.name),
connectionDelay: connectionDelay,
onAdd: obj => {
this.states.setStateAndDispatch(context.name, {
Expand Down Expand Up @@ -665,7 +673,7 @@ export class ContextsManager {
return this.createInformer<V1Service>(kc, context, path, listFn, {
resource: 'services',
timer: timer,
backoff: new Backoff(backoffInitialValue, backoffLimit, backoffJitter),
backoff: this.getBackoffForContext(context.name),
connectionDelay: connectionDelay,
onAdd: obj => {
this.states.setStateAndDispatch(context.name, {
Expand Down Expand Up @@ -705,7 +713,7 @@ export class ContextsManager {
return this.createInformer<V1Ingress>(kc, context, path, listFn, {
resource: 'ingresses',
timer: timer,
backoff: new Backoff(backoffInitialValue, backoffLimit, backoffJitter),
backoff: this.getBackoffForContext(context.name),
connectionDelay: connectionDelay,
onAdd: obj => {
this.states.setStateAndDispatch(context.name, {
Expand Down Expand Up @@ -751,7 +759,7 @@ export class ContextsManager {
return this.createInformer<V1Route>(kc, context, path, listFn, {
resource: 'routes',
timer: timer,
backoff: new Backoff(backoffInitialValue, backoffLimit, backoffJitter),
backoff: this.getBackoffForContext(context.name),
connectionDelay: connectionDelay,
onAdd: obj => {
this.states.setStateAndDispatch(context.name, {
Expand Down Expand Up @@ -968,4 +976,17 @@ export class ContextsManager {
clearTimeout(timer);
}
}

private getBackoffForContext(contextName: string): Backoff {
if (contextName === this.kubeConfig.currentContext) {
return new Backoff(
backoffInitialValue,
backoffMultiplierCurrentContext,
backoffLimitCurrentContext,
backoffJitter,
);
} else {
return new Backoff(backoffInitialValue, backoffMultiplier, backoffLimit, backoffJitter);
}
}
}

0 comments on commit 0fb3ec2

Please sign in to comment.