blob: 2a9ee4a5007b431c127a82a8fa908f61e1d808ce [file] [log] [blame]
Rob Mohr8d13e252022-09-27 20:01:44 +00001# Copyright 2022 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7# https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14"""Ensure the given call completes before swarming kills the build."""
15
16import contextlib
17import dataclasses
Rob Mohr0b9859a2024-03-06 23:25:38 +000018from typing import Generator
Rob Mohr8d13e252022-09-27 20:01:44 +000019
20from recipe_engine import recipe_api
Rob Mohr8d13e252022-09-27 20:01:44 +000021from RECIPE_MODULES.fuchsia.utils import nice_duration
22
23
24class TimeoutApi(recipe_api.RecipeApi):
25 """Ensure the given call completes before swarming kills the build."""
26
27 @contextlib.contextmanager
Rob Mohr0b9859a2024-03-06 23:25:38 +000028 def __call__(self, buffer_sec: float = 120) -> Generator[None, None, None]:
Rob Mohr7ff94c02023-11-20 17:01:28 +000029 current_time_sec: float = self.m.time.time()
Rob Mohr8d13e252022-09-27 20:01:44 +000030
31 # Amount of time elapsed in the run.
Rob Mohr7ff94c02023-11-20 17:01:28 +000032 elapsed_time_sec: float = (
Rob Mohrd6071192023-06-15 22:17:01 +000033 current_time_sec - self.m.buildbucket.build.start_time.seconds
Rob Mohr8d13e252022-09-27 20:01:44 +000034 )
35
36 # Amount of time before build times out.
Rob Mohr7ff94c02023-11-20 17:01:28 +000037 time_remaining_sec: float = (
Rob Mohrd6071192023-06-15 22:17:01 +000038 self.m.buildbucket.build.execution_timeout.seconds
39 - elapsed_time_sec
Rob Mohr8d13e252022-09-27 20:01:44 +000040 )
41
42 # Give a buffer before build times out and kill this step then. This
43 # should give enough time to read any logfiles and maybe upload to
Rob Mohrd6071192023-06-15 22:17:01 +000044 # GCS before the build times out.
Rob Mohr7ff94c02023-11-20 17:01:28 +000045 timeout_sec: float = time_remaining_sec - buffer_sec
Rob Mohr8d13e252022-09-27 20:01:44 +000046
Rob Mohrd6071192023-06-15 22:17:01 +000047 # Most tests don't appropriately set up timing, and this could be
48 # invoked at the very end of a build where it's about to timeout, so
49 # make sure the timeout is always at least 10 seconds in the future.
Rob Mohr7ff94c02023-11-20 17:01:28 +000050 if timeout_sec < 10.0:
51 timeout_sec = 10.0
Rob Mohr8d13e252022-09-27 20:01:44 +000052
Rob Mohrd6071192023-06-15 22:17:01 +000053 with self.m.step.nest(f'timeout {nice_duration(timeout_sec)}'):
Rob Mohradee1d42023-03-28 21:30:26 +000054 pass
Rob Mohr8d13e252022-09-27 20:01:44 +000055
Rob Mohr8d13e252022-09-27 20:01:44 +000056 try:
Rob Mohr686cf712023-06-15 22:19:09 +000057 with self.m.time.timeout(timeout_sec):
Rob Mohr8d13e252022-09-27 20:01:44 +000058 yield
59
60 finally:
61 pass