2011-07-03 09:47:31 -07:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
2012-03-13 16:21:04 -07:00
|
|
|
* Copyright 2012 Facebook, Inc.
|
2011-07-03 09:47:31 -07:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Collects old logs and caches to reduce the amount of data stored in the
|
|
|
|
* database.
|
|
|
|
*
|
|
|
|
* @group daemon
|
|
|
|
*/
|
2012-03-13 16:21:04 -07:00
|
|
|
final class PhabricatorGarbageCollectorDaemon extends PhabricatorDaemon {
|
2011-07-03 09:47:31 -07:00
|
|
|
|
|
|
|
public function run() {
|
|
|
|
|
|
|
|
// Keep track of when we start and stop the GC so we can emit useful log
|
|
|
|
// messages.
|
|
|
|
$just_ran = false;
|
|
|
|
|
|
|
|
do {
|
|
|
|
$run_at = PhabricatorEnv::getEnvConfig('gcdaemon.run-at');
|
|
|
|
$run_for = PhabricatorEnv::getEnvConfig('gcdaemon.run-for');
|
|
|
|
|
|
|
|
// Just use the default timezone, we don't need to get fancy and try
|
|
|
|
// to localize this.
|
|
|
|
$start = strtotime($run_at);
|
|
|
|
if ($start === false) {
|
|
|
|
throw new Exception(
|
|
|
|
"Configuration 'gcdaemon.run-at' could not be parsed: '{$run_at}'.");
|
|
|
|
}
|
|
|
|
|
|
|
|
$now = time();
|
|
|
|
|
|
|
|
if ($now < $start || $now > ($start + $run_for)) {
|
|
|
|
if ($just_ran) {
|
2012-07-11 11:40:18 -07:00
|
|
|
$this->log("Stopped garbage collector.");
|
2011-07-03 09:47:31 -07:00
|
|
|
$just_ran = false;
|
|
|
|
}
|
|
|
|
// The configuration says we can't collect garbage right now, so
|
|
|
|
// just sleep until we can.
|
|
|
|
$this->sleep(300);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$just_ran) {
|
2012-07-11 11:40:18 -07:00
|
|
|
$this->log("Started garbage collector.");
|
2011-07-03 09:47:31 -07:00
|
|
|
$just_ran = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
$n_herald = $this->collectHeraldTranscripts();
|
|
|
|
$n_daemon = $this->collectDaemonLogs();
|
2011-07-08 15:26:33 -07:00
|
|
|
$n_parse = $this->collectParseCaches();
|
2012-07-11 11:40:18 -07:00
|
|
|
$n_markup = $this->collectMarkupCaches();
|
2011-07-03 09:47:31 -07:00
|
|
|
|
|
|
|
$collected = array(
|
2011-07-08 15:26:33 -07:00
|
|
|
'Herald Transcript' => $n_herald,
|
|
|
|
'Daemon Log' => $n_daemon,
|
|
|
|
'Differential Parse Cache' => $n_parse,
|
2012-07-11 11:40:18 -07:00
|
|
|
'Markup Cache' => $n_markup,
|
2011-07-03 09:47:31 -07:00
|
|
|
);
|
|
|
|
$collected = array_filter($collected);
|
|
|
|
|
|
|
|
foreach ($collected as $thing => $count) {
|
|
|
|
$count = number_format($count);
|
2012-07-11 11:40:18 -07:00
|
|
|
$this->log("Garbage collected {$count} '{$thing}' objects.");
|
2011-07-03 09:47:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
$total = array_sum($collected);
|
|
|
|
if ($total < 100) {
|
|
|
|
// We didn't max out any of the GCs so we're basically caught up. Ease
|
|
|
|
// off the GC loop so we don't keep doing table scans just to delete
|
|
|
|
// a handful of rows.
|
|
|
|
$this->sleep(300);
|
|
|
|
} else {
|
|
|
|
$this->stillWorking();
|
|
|
|
}
|
|
|
|
} while (true);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private function collectHeraldTranscripts() {
|
|
|
|
$ttl = PhabricatorEnv::getEnvConfig('gcdaemon.ttl.herald-transcripts');
|
|
|
|
if ($ttl <= 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
$table = new HeraldTranscript();
|
|
|
|
$conn_w = $table->establishConnection('w');
|
|
|
|
|
|
|
|
queryfx(
|
|
|
|
$conn_w,
|
|
|
|
'UPDATE %T SET
|
|
|
|
objectTranscript = "",
|
|
|
|
ruleTranscripts = "",
|
|
|
|
conditionTranscripts = "",
|
2011-07-26 18:11:54 -07:00
|
|
|
applyTranscripts = "",
|
|
|
|
garbageCollected = 1
|
|
|
|
WHERE garbageCollected = 0 AND `time` < %d
|
2011-07-03 09:47:31 -07:00
|
|
|
LIMIT 100',
|
|
|
|
$table->getTableName(),
|
|
|
|
time() - $ttl);
|
|
|
|
|
|
|
|
return $conn_w->getAffectedRows();
|
|
|
|
}
|
|
|
|
|
|
|
|
private function collectDaemonLogs() {
|
|
|
|
$ttl = PhabricatorEnv::getEnvConfig('gcdaemon.ttl.daemon-logs');
|
|
|
|
if ($ttl <= 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
$table = new PhabricatorDaemonLogEvent();
|
|
|
|
$conn_w = $table->establishConnection('w');
|
|
|
|
|
|
|
|
queryfx(
|
|
|
|
$conn_w,
|
|
|
|
'DELETE FROM %T WHERE epoch < %d LIMIT 100',
|
|
|
|
$table->getTableName(),
|
|
|
|
time() - $ttl);
|
|
|
|
|
|
|
|
return $conn_w->getAffectedRows();
|
|
|
|
}
|
|
|
|
|
2011-07-08 15:26:33 -07:00
|
|
|
private function collectParseCaches() {
|
|
|
|
$key = 'gcdaemon.ttl.differential-parse-cache';
|
|
|
|
$ttl = PhabricatorEnv::getEnvConfig($key);
|
|
|
|
if ($ttl <= 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
$table = new DifferentialChangeset();
|
|
|
|
$conn_w = $table->establishConnection('w');
|
|
|
|
|
|
|
|
queryfx(
|
|
|
|
$conn_w,
|
|
|
|
'DELETE FROM %T WHERE dateCreated < %d LIMIT 100',
|
|
|
|
DifferentialChangeset::TABLE_CACHE,
|
|
|
|
time() - $ttl);
|
|
|
|
|
|
|
|
return $conn_w->getAffectedRows();
|
2011-07-03 09:47:31 -07:00
|
|
|
}
|
|
|
|
|
2012-07-11 11:40:18 -07:00
|
|
|
private function collectMarkupCaches() {
|
|
|
|
$key = 'gcdaemon.ttl.markup-cache';
|
|
|
|
$ttl = PhabricatorEnv::getEnvConfig($key);
|
|
|
|
if ($ttl <= 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
$table = new PhabricatorMarkupCache();
|
|
|
|
$conn_w = $table->establishConnection('w');
|
|
|
|
|
|
|
|
queryfx(
|
|
|
|
$conn_w,
|
|
|
|
'DELETE FROM %T WHERE dateCreated < %d LIMIT 100',
|
|
|
|
$table->getTableName(),
|
|
|
|
time() - $ttl);
|
|
|
|
|
|
|
|
return $conn_w->getAffectedRows();
|
|
|
|
}
|
|
|
|
|
2011-07-03 09:47:31 -07:00
|
|
|
}
|