mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-30 01:10:58 +01:00
Truncate object fields in Herald transcripts
Summary: A few users have hit cases where Herald transcripts of large commits exceed the MySQL packet limit, because one of the fields in the transcript is an enomrous textual diff. There's no value in saving these huge amounts of data. Transcripts are useful for understanding the action of Herald rules, but can be reconstructed later. Instead of saving all of the data, limit each field to 4KB of data. For strings, we just truncate at 4KB. For arrays, we truncate after 4KB of values. Test Plan: Ran unit tests. Artificially decreased limit and ran transcripts, saw them truncate properly. Reviewers: btrahan Reviewed By: btrahan CC: frgtn, aran Differential Revision: https://secure.phabricator.com/D7783
This commit is contained in:
parent
b0f7e7a6af
commit
181bfffaa1
3 changed files with 79 additions and 0 deletions
|
@ -779,6 +779,7 @@ phutil_register_library_map(array(
|
||||||
'HeraldTranscriptController' => 'applications/herald/controller/HeraldTranscriptController.php',
|
'HeraldTranscriptController' => 'applications/herald/controller/HeraldTranscriptController.php',
|
||||||
'HeraldTranscriptListController' => 'applications/herald/controller/HeraldTranscriptListController.php',
|
'HeraldTranscriptListController' => 'applications/herald/controller/HeraldTranscriptListController.php',
|
||||||
'HeraldTranscriptQuery' => 'applications/herald/query/HeraldTranscriptQuery.php',
|
'HeraldTranscriptQuery' => 'applications/herald/query/HeraldTranscriptQuery.php',
|
||||||
|
'HeraldTranscriptTestCase' => 'applications/herald/storage/__tests__/HeraldTranscriptTestCase.php',
|
||||||
'Javelin' => 'infrastructure/javelin/Javelin.php',
|
'Javelin' => 'infrastructure/javelin/Javelin.php',
|
||||||
'JavelinReactorExample' => 'applications/uiexample/examples/JavelinReactorExample.php',
|
'JavelinReactorExample' => 'applications/uiexample/examples/JavelinReactorExample.php',
|
||||||
'JavelinUIExample' => 'applications/uiexample/examples/JavelinUIExample.php',
|
'JavelinUIExample' => 'applications/uiexample/examples/JavelinUIExample.php',
|
||||||
|
@ -3211,6 +3212,7 @@ phutil_register_library_map(array(
|
||||||
'HeraldTranscriptController' => 'HeraldController',
|
'HeraldTranscriptController' => 'HeraldController',
|
||||||
'HeraldTranscriptListController' => 'HeraldController',
|
'HeraldTranscriptListController' => 'HeraldController',
|
||||||
'HeraldTranscriptQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'HeraldTranscriptQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
|
'HeraldTranscriptTestCase' => 'PhabricatorTestCase',
|
||||||
'JavelinReactorExample' => 'PhabricatorUIExample',
|
'JavelinReactorExample' => 'PhabricatorUIExample',
|
||||||
'JavelinUIExample' => 'PhabricatorUIExample',
|
'JavelinUIExample' => 'PhabricatorUIExample',
|
||||||
'JavelinViewExample' => 'PhabricatorUIExample',
|
'JavelinViewExample' => 'PhabricatorUIExample',
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class HeraldTranscriptTestCase extends PhabricatorTestCase {
|
||||||
|
|
||||||
|
public function testTranscriptTruncation() {
|
||||||
|
$long_string = str_repeat('x', 1024 * 1024);
|
||||||
|
$short_string = str_repeat('x', 4096)."\n<...>";
|
||||||
|
|
||||||
|
$long_array = array(
|
||||||
|
'a' => $long_string,
|
||||||
|
'b' => $long_string,
|
||||||
|
);
|
||||||
|
|
||||||
|
$mixed_array = array(
|
||||||
|
'a' => 'abc',
|
||||||
|
'b' => 'def',
|
||||||
|
'c' => $long_string,
|
||||||
|
);
|
||||||
|
|
||||||
|
$fields = array(
|
||||||
|
'ls' => $long_string,
|
||||||
|
'la' => $long_array,
|
||||||
|
'ma' => $mixed_array,
|
||||||
|
);
|
||||||
|
|
||||||
|
$truncated_fields = id(new HeraldObjectTranscript())
|
||||||
|
->setFields($fields)
|
||||||
|
->getFields();
|
||||||
|
|
||||||
|
$this->assertEqual($short_string, $truncated_fields['ls']);
|
||||||
|
|
||||||
|
$this->assertEqual(
|
||||||
|
array('a', '<...>'),
|
||||||
|
array_keys($truncated_fields['la']));
|
||||||
|
$this->assertEqual(
|
||||||
|
$short_string.'!<...>',
|
||||||
|
implode('!', $truncated_fields['la']));
|
||||||
|
|
||||||
|
$this->assertEqual(
|
||||||
|
array('a', 'b', 'c'),
|
||||||
|
array_keys($truncated_fields['ma']));
|
||||||
|
$this->assertEqual(
|
||||||
|
'abc!def!'.substr($short_string, 6),
|
||||||
|
implode('!', $truncated_fields['ma']));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,6 +35,10 @@ final class HeraldObjectTranscript {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setFields(array $fields) {
|
public function setFields(array $fields) {
|
||||||
|
foreach ($fields as $key => $value) {
|
||||||
|
$fields[$key] = self::truncateValue($value, 4096);
|
||||||
|
}
|
||||||
|
|
||||||
$this->fields = $fields;
|
$this->fields = $fields;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -42,4 +46,30 @@ final class HeraldObjectTranscript {
|
||||||
public function getFields() {
|
public function getFields() {
|
||||||
return $this->fields;
|
return $this->fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function truncateValue($value, $length) {
|
||||||
|
if (is_string($value)) {
|
||||||
|
if (strlen($value) <= $length) {
|
||||||
|
return $value;
|
||||||
|
} else {
|
||||||
|
// NOTE: phutil_utf8_shorten() has huge runtime for giant strings.
|
||||||
|
return phutil_utf8ize(substr($value, 0, $length)."\n<...>");
|
||||||
|
}
|
||||||
|
} else if (is_array($value)) {
|
||||||
|
foreach ($value as $key => $v) {
|
||||||
|
if ($length <= 0) {
|
||||||
|
$value['<...>'] = '<...>';
|
||||||
|
unset($value[$key]);
|
||||||
|
} else {
|
||||||
|
$v = self::truncateValue($v, $length);
|
||||||
|
$length -= strlen($v);
|
||||||
|
$value[$key] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $value;
|
||||||
|
} else {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue