• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 24637157883

19 Apr 2026 07:23PM UTC coverage: 52.377% (-40.5%) from 92.924%
24637157883

Pull #23274

github

web-flow
Merge b54f275c2 into 0283af69e
Pull Request #23274: rust: upgrade to v1.95.0

31658 of 60443 relevant lines covered (52.38%)

1.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

28.89
/src/python/pants/pantsd/service/store_gc_service.py
1
# Copyright 2018 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from __future__ import annotations
2✔
5

6
import logging
2✔
7
import time
2✔
8

9
from pants.engine.internals.scheduler import Scheduler
2✔
10
from pants.option.bootstrap_options import (
2✔
11
    DEFAULT_LOCAL_STORE_OPTIONS,
12
    LOCAL_STORE_LEASE_TIME_SECS,
13
    LocalStoreOptions,
14
)
15
from pants.pantsd.service.pants_service import PantsService
2✔
16

17

18
class StoreGCService(PantsService):
2✔
19
    """Store Garbage Collection Service.
20

21
    This service both ensures that in-use files continue to be present in the engine's Store, and
22
    performs occasional garbage collection to bound the size of the engine's Store.
23

24
    NB: The lease extension interval should be a small multiple of LOCAL_STORE_LEASE_TIME_SECS
25
    to ensure that valid leases are extended well before they might expire.
26
    """
27

28
    def __init__(
2✔
29
        self,
30
        scheduler: Scheduler,
31
        period_secs: float = 10,
32
        lease_extension_interval_secs: float = (float(LOCAL_STORE_LEASE_TIME_SECS) / 100),
33
        gc_interval_secs: float = (1 * 60 * 60),
34
        local_store_options: LocalStoreOptions = DEFAULT_LOCAL_STORE_OPTIONS,
35
    ):
36
        super().__init__()
×
37
        self._scheduler_session = scheduler.new_session(build_id="store_gc_service_session")
×
38
        self._logger = logging.getLogger(__name__)
×
39

40
        self._period_secs = period_secs
×
41
        self._lease_extension_interval_secs = lease_extension_interval_secs
×
42
        self._gc_interval_secs = gc_interval_secs
×
43
        self._target_size_bytes = local_store_options.target_total_size_bytes()
×
44

45
        self._set_next_gc()
×
46
        self._set_next_lease_extension()
×
47

48
    def _set_next_gc(self):
2✔
49
        self._next_gc = time.time() + self._gc_interval_secs
×
50

51
    def _set_next_lease_extension(self):
2✔
52
        self._next_lease_extension = time.time() + self._lease_extension_interval_secs
×
53

54
    def _maybe_extend_lease(self):
2✔
55
        if time.time() < self._next_lease_extension:
×
56
            return
×
57
        self._logger.info("Extending leases")
×
58
        self._scheduler_session.lease_files_in_graph()
×
59
        self._logger.info("Done extending leases")
×
60
        self._set_next_lease_extension()
×
61

62
    def _maybe_garbage_collect(self):
2✔
63
        if time.time() < self._next_gc:
×
64
            return
×
65
        self._logger.info(f"Garbage collecting store. target_size={self._target_size_bytes:,}")
×
66
        self._scheduler_session.garbage_collect_store(self._target_size_bytes)
×
67
        self._logger.info("Done garbage collecting store")
×
68
        self._set_next_gc()
×
69

70
    def run(self):
2✔
71
        """Main service entrypoint.
72

73
        Called via Thread.start() via PantsDaemon.run().
74
        """
75
        while not self._state.is_terminating:
×
76
            try:
×
77
                self._maybe_garbage_collect()
×
78
                self._maybe_extend_lease()
×
79
                # Waiting with a timeout in maybe_pause has the effect of waiting until:
80
                # 1) we are paused and then resumed
81
                # 2) we are terminated (which will break the loop)
82
                # 3) the timeout is reached, which will cause us to wake up and check gc/leases
83
                self._state.maybe_pause(timeout=self._period_secs)
×
84
            except Exception as e:
×
85
                self._logger.critical(f"GC failed: {e!r}")
×
86
                self.terminate()
×
87
        self._scheduler_session.cancel()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc