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
« 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.
15from datetime import datetime, timedelta
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
25LOGGER = buildgrid_logger(__name__)
26EPOCH = datetime(1970, 1, 1)
29class ActionCache(Instance):
30 SERVICE_NAME = RE_DESCRIPTOR.services_by_name["ActionCache"].full_name
32 def __init__(self, cache: ActionCacheABC) -> None:
33 """Initialises a new ActionCache instance.
35 Args:
36 cache (ActionCacheABC): The cache to use to store results.
38 """
39 self._cache = cache
41 # --- Public API ---
43 def start(self) -> None:
44 self._cache.start()
46 def stop(self) -> None:
47 self._cache.stop()
48 LOGGER.info("Stopped ActionCache.")
50 @property
51 def allow_updates(self) -> bool:
52 return self._cache.allow_updates
54 def get_action_result(self, action_digest: Digest) -> ActionResult:
55 """Retrieves the cached result for an Action.
57 If there is no cached result found, returns None.
59 Args:
60 action_digest (Digest): The digest of the Action to retrieve the
61 cached result of.
63 """
64 res = self._cache.get_action_result(action_digest)
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)
72 return res
74 def update_action_result(self, action_digest: Digest, action_result: ActionResult) -> None:
75 """Stores a result for an Action in the cache.
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.
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.
86 """
87 self._cache.update_action_result(action_digest, action_result)