Coverage for /builds/BuildGrid/buildgrid/buildgrid/server/actioncache/instance.py: 100.00%

32 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2025-03-13 15:36 +0000

1# Copyright (C) 2018 Bloomberg LP 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# <http://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, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14 

15from datetime import datetime, timedelta 

16 

17from buildgrid._protos.build.bazel.remote.execution.v2.remote_execution_pb2 import DESCRIPTOR as RE_DESCRIPTOR 

18from buildgrid._protos.build.bazel.remote.execution.v2.remote_execution_pb2 import ActionResult, Digest 

19from buildgrid.server.actioncache.caches.action_cache_abc import ActionCacheABC 

20from buildgrid.server.logging import buildgrid_logger 

21from buildgrid.server.metrics_names import METRIC 

22from buildgrid.server.metrics_utils import publish_distribution_metric 

23from buildgrid.server.servicer import Instance 

24 

25LOGGER = buildgrid_logger(__name__) 

26EPOCH = datetime(1970, 1, 1) 

27 

28 

29class ActionCache(Instance): 

30 SERVICE_NAME = RE_DESCRIPTOR.services_by_name["ActionCache"].full_name 

31 

32 def __init__(self, cache: ActionCacheABC) -> None: 

33 """Initialises a new ActionCache instance. 

34 

35 Args: 

36 cache (ActionCacheABC): The cache to use to store results. 

37 

38 """ 

39 self._cache = cache 

40 

41 # --- Public API --- 

42 

43 def start(self) -> None: 

44 self._cache.start() 

45 

46 def stop(self) -> None: 

47 self._cache.stop() 

48 LOGGER.info("Stopped ActionCache.") 

49 

50 @property 

51 def allow_updates(self) -> bool: 

52 return self._cache.allow_updates 

53 

54 def get_action_result(self, action_digest: Digest) -> ActionResult: 

55 """Retrieves the cached result for an Action. 

56 

57 If there is no cached result found, returns None. 

58 

59 Args: 

60 action_digest (Digest): The digest of the Action to retrieve the 

61 cached result of. 

62 

63 """ 

64 res = self._cache.get_action_result(action_digest) 

65 

66 time_completed = res.execution_metadata.worker_completed_timestamp.ToDatetime() 

67 if time_completed != EPOCH: 

68 age = datetime.now() - time_completed 

69 age_in_ms = age / timedelta(milliseconds=1) 

70 publish_distribution_metric(METRIC.ACTION_CACHE.RESULT_AGE, age_in_ms) 

71 

72 return res 

73 

74 def update_action_result(self, action_digest: Digest, action_result: ActionResult) -> None: 

75 """Stores a result for an Action in the cache. 

76 

77 If the result has a non-zero exit code and `cache_failed_actions` is False 

78 for this cache, the result is not cached. 

79 

80 Args: 

81 action_digest (Digest): The digest of the Action whose result is 

82 being cached. 

83 action_result (ActionResult): The result to cache for the given 

84 Action digest. 

85 

86 """ 

87 self._cache.update_action_result(action_digest, action_result)