Skip to content

Commit 2162232

Browse files
author
Matt Pryor
authored
Prevent overflow by replacing backoff with fixed delay (#102)
1 parent 08b03a6 commit 2162232

File tree

1 file changed

+12
-27
lines changed

1 file changed

+12
-27
lines changed

capi_janitor/openstack/operator.py

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import functools
44
import os
55
import random
6+
import string
67

78
import kopf
89
import yaml
@@ -30,8 +31,8 @@
3031
CREDENTIAL_ANNOTATION = "janitor.capi.stackhpc.com/credential-policy"
3132
CREDENTIAL_ANNOTATION_DELETE = "delete"
3233

33-
RETRY_ANNOTATION = "janitor.capi.stackhpc.com/retries"
34-
RETRY_MAX_BACKOFF = int(os.environ.get("CAPI_JANITOR_RETRY_MAX_BACKOFF", "60"))
34+
RETRY_ANNOTATION = "janitor.capi.stackhpc.com/retry"
35+
RETRY_DEFAULT_DELAY = int(os.environ.get("CAPI_JANITOR_RETRY_DEFAULT_DELAY", "60"))
3536

3637

3738
@kopf.on.cleanup()
@@ -264,10 +265,8 @@ async def wrapper(**kwargs):
264265
body = kwargs["body"]
265266
resource = await ekclient.api(body["apiVersion"]).resource(body["kind"])
266267
try:
267-
result = await handler(**kwargs)
268+
return await handler(**kwargs)
268269
except Exception as exc:
269-
# Check to see how many times a handler has been retried
270-
retries = int(kwargs["annotations"].get(RETRY_ANNOTATION, "0"))
271270
if isinstance(exc, kopf.TemporaryError):
272271
kwargs["logger"].warn(str(exc))
273272
backoff = exc.delay
@@ -277,16 +276,22 @@ async def wrapper(**kwargs):
277276
else:
278277
kwargs["logger"].exception(str(exc))
279278
# Calculate the backoff
280-
backoff = min(2**retries + random.uniform(0, 1), RETRY_MAX_BACKOFF)
279+
backoff = RETRY_DEFAULT_DELAY
281280
# Wait for the backoff before annotating the resource
282281
await asyncio.sleep(backoff)
282+
# Annotate the object with a random value to trigger another event
283283
try:
284284
await resource.patch(
285285
kwargs["name"],
286286
{
287287
"metadata": {
288288
"annotations": {
289-
RETRY_ANNOTATION: str(retries + 1),
289+
RETRY_ANNOTATION: "".join(
290+
random.choices(
291+
string.ascii_lowercase + string.digits,
292+
k = 8
293+
)
294+
),
290295
}
291296
}
292297
},
@@ -295,26 +300,6 @@ async def wrapper(**kwargs):
295300
except easykube.ApiError as exc:
296301
if exc.status_code != 404:
297302
raise
298-
else:
299-
if RETRY_ANNOTATION in kwargs["annotations"]:
300-
# If the handler completes successfully, ensure the annotation is removed
301-
# The forward slash in the annotation is designated by '~1' in JSON patch
302-
annotation = RETRY_ANNOTATION.replace('/', '~1')
303-
try:
304-
await resource.json_patch(
305-
kwargs["name"],
306-
[
307-
{
308-
"op": "remove",
309-
"path": f"/metadata/annotations/{annotation}",
310-
},
311-
],
312-
namespace = kwargs["namespace"]
313-
)
314-
except easykube.ApiError as exc:
315-
if exc.status_code != 404:
316-
raise
317-
return result
318303
return wrapper
319304

320305

0 commit comments

Comments
 (0)