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

22 statements  

« prev     ^ index     » next       coverage.py v6.4.1, created at 2022-06-22 21:04 +0000

1# Copyright (C) 2020 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 

15 

16import logging 

17 

18from buildgrid._protos.build.bazel.remote.execution.v2.remote_execution_pb2 import ( 

19 ActionResult, 

20 Digest 

21) 

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

23from buildgrid.server.cas.storage.storage_abc import StorageABC 

24from buildgrid.server.referencestorage.storage import ReferenceCache 

25 

26 

27# TODO: Move relevant code from ReferenceCache into here, and deprecate 

28# the ReferenceCache class. It's only used by old versions of BuildStream. 

29class LruActionCache(ActionCacheABC, ReferenceCache): 

30 

31 """In-memory Action Cache implementation with LRU eviction. 

32 

33 This cache has a configurable fixed size, evicting the least recently 

34 accessed entry when adding a new entry would exceed the fixed size. The 

35 cache is entirely stored in memory so its contents are lost on restart. 

36 

37 The actual LRU functionality is implemented by ``ReferenceCache``, which 

38 this class inherits from. This class is a thin wrapper around that which 

39 provides a way to turn Action digests into hashable objects, and the 

40 common API defined in ``ActionCacheABC``. 

41 

42 This type of cache is ideal for use cases that need a simple and fast 

43 cache, with no requirements for longevity of the cache content. It is not 

44 recommended to use this type of cache in situations where you may wish to 

45 obtain cached results a reasonable time in the future, due to its fixed 

46 size. 

47 

48 """ 

49 

50 def __init__(self, storage: StorageABC, max_cached_refs: int, 

51 allow_updates: bool=True, cache_failed_actions: bool=True): 

52 """Initialise a new in-memory LRU Action Cache. 

53 

54 Args: 

55 storage (StorageABC): Storage backend instance to be used. 

56 max_cached_refs (int): Maximum number of entries to store in the cache. 

57 allow_updates (bool): Whether to allow writing to the cache. If false, 

58 this is a read-only cache for all clients. 

59 cache_failed_actions (bool): Whether or not to cache Actions with 

60 non-zero exit codes. 

61 

62 """ 

63 ActionCacheABC.__init__(self, storage=storage) 

64 ReferenceCache.__init__(self, storage, max_cached_refs, allow_updates) 

65 

66 self._logger = logging.getLogger(__name__) 

67 self._cache_failed_actions = cache_failed_actions 

68 

69 self.instance_name = None 

70 

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

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

73 

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

75 

76 Args: 

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

78 cached result of. 

79 

80 """ 

81 key = self._get_key(action_digest) 

82 return self.get_action_reference(key) 

83 

84 def update_action_result(self, action_digest: Digest, 

85 action_result: ActionResult) -> None: 

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

87 

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

89 for this cache, the result is not cached. 

90 

91 Args: 

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

93 being cached. 

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

95 Action digest. 

96 

97 """ 

98 if self._cache_failed_actions or action_result.exit_code == 0: 

99 key = self._get_key(action_digest) 

100 self.update_reference(key, action_result) 

101 

102 self._logger.info( 

103 f"Result cached for action [{action_digest.hash}/{action_digest.size_bytes}]") 

104 

105 def _get_key(self, action_digest: Digest): 

106 """Get a hashable cache key from a given Action digest. 

107 

108 Args: 

109 action_digest (Digest): The digest to produce a cache key for. 

110 

111 """ 

112 return (action_digest.hash, action_digest.size_bytes)