From f85e2df854e1ba8bf18d7752be8e4d2107bcd8f6 Mon Sep 17 00:00:00 2001 From: kahirokunn Date: Fri, 21 Jun 2024 15:23:58 +0900 Subject: [PATCH] chore: backoff logic now handles retryAfterSeconds. --- packages/kubekit-client/package.json | 2 +- packages/kubekit-client/src/client/index.ts | 11 ++++++++--- packages/kubekit-client/src/lib/error.ts | 12 +++++++++--- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/kubekit-client/package.json b/packages/kubekit-client/package.json index da34ea98..cca03027 100644 --- a/packages/kubekit-client/package.json +++ b/packages/kubekit-client/package.json @@ -1,6 +1,6 @@ { "name": "@kubekit/client", - "version": "0.2.20", + "version": "0.2.21", "main": "dist/index.js", "types": "dist/index.d.ts", "author": "kahirokunn", diff --git a/packages/kubekit-client/src/client/index.ts b/packages/kubekit-client/src/client/index.ts index 6a95633f..703c0f91 100644 --- a/packages/kubekit-client/src/client/index.ts +++ b/packages/kubekit-client/src/client/index.ts @@ -4,6 +4,7 @@ import { ReadableStream, TransformStream } from 'node:stream/web'; import { type ObjectReference } from '../lib/types'; import { KubeConfig } from '../lib/config'; import { KubernetesError, isKubernetesError, isTooLargeResourceVersion } from '../lib/error'; +import { sleep } from '../lib/sleep'; export { sleep } from '../lib/sleep'; export { TaskManager } from '../lib/task_manager'; @@ -44,11 +45,15 @@ function removeNullableProperties * @param attempt - Current attempt * @param maxRetries - Maximum number of retries */ -async function defaultBackoff(attempt: number, maxRetries: number) { +async function defaultBackoff(attempt: number, maxRetries: number, error: unknown | KubernetesError) { + if (isKubernetesError(error) && 'retryAfterSeconds' in error.details) { + await sleep(error.details.retryAfterSeconds * 1000); + return; + } const attempts = Math.min(attempt, maxRetries); const timeout = Math.trunc((Math.random() + 0.4) * (300 << attempts)); - await new Promise((resolve) => setTimeout((response: any) => resolve(response), timeout)); + await sleep(timeout); } const isPlainObject = (value: any) => value?.constructor === Object; @@ -434,7 +439,7 @@ $ k3d cluster create kubekit --k3s-arg '--kube-apiserver-arg=feature-gates=Watch throw error; } - await options.backoff(retry, options.maxRetries); + await options.backoff(retry, options.maxRetries, error); } } } diff --git a/packages/kubekit-client/src/lib/error.ts b/packages/kubekit-client/src/lib/error.ts index 7dbdc006..f20d9ebc 100644 --- a/packages/kubekit-client/src/lib/error.ts +++ b/packages/kubekit-client/src/lib/error.ts @@ -29,14 +29,20 @@ export type KubernetesError = { message: string; reason: string; details: { - group: string; - kind: string; causes: { reason: string; message: string; field: string; }[]; - }; + } & ( + | { + group: string; + kind: string; + } + | { + retryAfterSeconds: number; + } + ); code: number; };