Skip to content

Commit f27336c

Browse files
committed
Reset github connections on every sync iteration
The HTTP connections to GitHub are managed by pygithub library. It uses a connection pool, initialized when Github object is created (in KPD we have one per BranchWorker), and the connections are actively reused. KPD creates the BranchWorkers, and by extension the Github objects, only once at start up. However KPD runs the main sync_patches() routine once every two minutes, which means that actual underlying connections are very likely to become stale. Of course, there is an encapsulated logic in pygithub to re-establish the connections. However it appears that attempting to use a connection that was never explicitly closed, causes issues when interacting with ttlsproxy. In particular we often get AsyncSocketException, which appears to be correlated with KPD's misbehavior with respect to email notifications. Attempt to mitigate these problems by re-creating GithubSync object (which spawns BranchWorker-s) on every iteration of the main daemon loop (that is: every 2 mins). Differential Revision: D80043971 Reviewed-by: Song Liu <[email protected]> Signed-off-by: Ihor Solodrai <[email protected]>
1 parent 732fc7a commit f27336c

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

kernel_patches_daemon/daemon.py

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,49 @@ def __init__(
3030
loop_delay: int = DEFAULT_LOOP_DELAY,
3131
) -> None:
3232
self.project: str = kpd_config.patchwork.project
33-
self.github_sync_worker = GithubSync(
34-
kpd_config=kpd_config, labels_cfg=labels_cfg
35-
)
33+
self.kpd_config = kpd_config
34+
self.labels_cfg = labels_cfg
3635
self.loop_delay: Final[int] = loop_delay
3736
self.metrics_logger = metrics_logger
37+
self.github_sync_worker: GithubSync = GithubSync(
38+
kpd_config=self.kpd_config, labels_cfg=self.labels_cfg
39+
)
40+
41+
def reset_github_sync(self) -> bool:
42+
try:
43+
self.github_sync_worker = GithubSync(
44+
kpd_config=self.kpd_config, labels_cfg=self.labels_cfg
45+
)
46+
return True
47+
except Exception:
48+
logger.exception(
49+
"Unhandled exception while creating GithubSync object",
50+
exc_info=True,
51+
)
52+
return False
3853

3954
async def submit_metrics(self) -> None:
40-
if self.metrics_logger:
41-
logger.info("Submitting run metrics into metrics logger")
42-
try:
43-
self.metrics_logger(self.project, self.github_sync_worker.stats)
44-
except Exception:
45-
logger.exception(
46-
"Failed to submit run metrics into metrics logger", exc_info=True
47-
)
48-
else:
55+
if self.metrics_logger is None:
4956
logger.warn(
5057
"Not submitting run metrics because metrics logger is not configured"
5158
)
59+
return
60+
try:
61+
self.metrics_logger(self.project, self.github_sync_worker.stats)
62+
logger.info("Submitted run metrics into metrics logger")
63+
except Exception:
64+
logger.exception(
65+
"Failed to submit run metrics into metrics logger", exc_info=True
66+
)
5267

5368
async def run(self) -> None:
5469
while True:
70+
ok = self.reset_github_sync()
71+
if not ok:
72+
logger.error(
73+
"Most likely something went wrong connecting to GitHub or Patchwork. Skipping this iteration without submitting metrics."
74+
)
75+
continue
5576
try:
5677
await self.github_sync_worker.sync_patches()
5778
self.github_sync_worker.increment_counter("runs_successful")

tests/test_daemon.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import unittest
88
from typing import Any, Dict, List
9-
from unittest.mock import AsyncMock, patch
9+
from unittest.mock import AsyncMock, MagicMock, patch
1010

1111
from kernel_patches_daemon.config import KPDConfig
1212
from kernel_patches_daemon.daemon import KernelPatchesWorker
@@ -68,6 +68,7 @@ def setUp(self) -> None:
6868
)
6969

7070
self.worker.github_sync_worker.sync_patches = AsyncMock()
71+
self.worker.reset_github_sync = MagicMock(return_value=True)
7172

7273
async def test_run_ok(self) -> None:
7374
with (
@@ -81,6 +82,7 @@ async def test_run_ok(self) -> None:
8182

8283
gh_sync = self.worker.github_sync_worker
8384
gh_sync.sync_patches.assert_called_once()
85+
self.worker.reset_github_sync.assert_called_once()
8486
self.assertEqual(len(LOGGED_METRICS), 1)
8587
stats = LOGGED_METRICS[0][self.worker.project]
8688
self.assertEqual(stats["runs_successful"], 1)

0 commit comments

Comments
 (0)