Path: blob/master/src/infrastructure/daemon/garbagecollector/PhabricatorGarbageCollector.php
12242 views
<?php12/**3* @task info Getting Collector Information4* @task collect Collecting Garbage5*/6abstract class PhabricatorGarbageCollector extends Phobject {789/* -( Getting Collector Information )-------------------------------------- */101112/**13* Get a human readable name for what this collector cleans up, like14* "User Activity Logs".15*16* @return string Human-readable collector name.17* @task info18*/19abstract public function getCollectorName();202122/**23* Specify that the collector has an automatic retention policy and24* is not configurable.25*26* @return bool True if the collector has an automatic retention policy.27* @task info28*/29public function hasAutomaticPolicy() {30return false;31}323334/**35* Get the default retention policy for this collector.36*37* Return the age (in seconds) when resources start getting collected, or38* `null` to retain resources indefinitely.39*40* @return int|null Lifetime, or `null` for indefinite retention.41* @task info42*/43public function getDefaultRetentionPolicy() {44throw new PhutilMethodNotImplementedException();45}464748/**49* Get the effective retention policy.50*51* @return int|null Lifetime, or `null` for indefinite retention.52* @task info53*/54public function getRetentionPolicy() {55if ($this->hasAutomaticPolicy()) {56throw new Exception(57pht(58'Can not get retention policy of collector with automatic '.59'policy.'));60}6162$config = PhabricatorEnv::getEnvConfig('phd.garbage-collection');63$const = $this->getCollectorConstant();6465return idx($config, $const, $this->getDefaultRetentionPolicy());66}67686970/**71* Get a unique string constant identifying this collector.72*73* @return string Collector constant.74* @task info75*/76final public function getCollectorConstant() {77return $this->getPhobjectClassConstant('COLLECTORCONST', 64);78}798081/* -( Collecting Garbage )------------------------------------------------- */828384/**85* Run the collector.86*87* @return bool True if there is more garbage to collect.88* @task collect89*/90final public function runCollector() {91// Don't do anything if this collector is configured with an indefinite92// retention policy.93if (!$this->hasAutomaticPolicy()) {94$policy = $this->getRetentionPolicy();95if (!$policy) {96return false;97}98}99100// Hold a lock while performing collection to avoid racing other daemons101// running the same collectors.102$params = array(103'collector' => $this->getCollectorConstant(),104);105$lock = PhabricatorGlobalLock::newLock('gc', $params);106107try {108$lock->lock(5);109} catch (PhutilLockException $ex) {110return false;111}112113try {114$result = $this->collectGarbage();115} catch (Exception $ex) {116$lock->unlock();117throw $ex;118}119120$lock->unlock();121122return $result;123}124125126/**127* Collect garbage from whatever source this GC handles.128*129* @return bool True if there is more garbage to collect.130* @task collect131*/132abstract protected function collectGarbage();133134135/**136* Get the most recent epoch timestamp that is considered garbage.137*138* Records older than this should be collected.139*140* @return int Most recent garbage timestamp.141* @task collect142*/143final protected function getGarbageEpoch() {144if ($this->hasAutomaticPolicy()) {145throw new Exception(146pht(147'Can not get garbage epoch for a collector with an automatic '.148'collection policy.'));149}150151$ttl = $this->getRetentionPolicy();152if (!$ttl) {153throw new Exception(154pht(155'Can not get garbage epoch for a collector with an indefinite '.156'retention policy.'));157}158159return (PhabricatorTime::getNow() - $ttl);160}161162163/**164* Load all of the available garbage collectors.165*166* @return list<PhabricatorGarbageCollector> Garbage collectors.167* @task collect168*/169final public static function getAllCollectors() {170return id(new PhutilClassMapQuery())171->setAncestorClass(__CLASS__)172->setUniqueMethod('getCollectorConstant')173->execute();174}175176}177178179