@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Allow unit tests to have arbitrarily long names (>255 characters)

Summary:
Depends on D20179. Ref T13088. See PHI351. See PHI1018. In various cases, unit tests names are 19 paths mashed together.

This is probably not an ideal name, and the test harness should probably pick a better name, but if users are fine with it and don't want to do the work to summarize on their own, accept them. We may summarize with "..." in some cases depending on how this fares in the UI.

The actual implementation is a separate "strings" table which is just `<hash-of-string, full-string>`. The unit message table can end up being mostly strings, so this should reduce storage requirements a bit.

For now, I'm not forcing a migration: new writes use the new table, existing rows retain the data. I plan to provide a migration tool, recommend migration, then force migration eventually.

Prior to that, I'm likely to move at least some other columns to use this table (e.g., lint names), since we have a lot of similar data (arbitrarily long user string constants that we are unlikely to need to search or filter).

Test Plan: {F6213819}

Reviewers: amckinley

Reviewed By: amckinley

Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam

Maniphest Tasks: T13088

Differential Revision: https://secure.phabricator.com/D20180

+124
+6
resources/sql/autopatches/20190215.harbor.01.stringindex.sql
··· 1 + CREATE TABLE {$NAMESPACE}_harbormaster.harbormaster_string ( 2 + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + stringIndex BINARY(12) NOT NULL, 4 + stringValue LONGTEXT NOT NULL, 5 + UNIQUE KEY `key_string` (stringIndex) 6 + ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+2
resources/sql/autopatches/20190215.harbor.02.stringcol.sql
··· 1 + ALTER TABLE {$NAMESPACE}_harbormaster.harbormaster_buildunitmessage 2 + ADD nameIndex BINARY(12) NOT NULL;
+2
src/__phutil_library_map__.php
··· 1441 1441 'HarbormasterStepDeleteController' => 'applications/harbormaster/controller/HarbormasterStepDeleteController.php', 1442 1442 'HarbormasterStepEditController' => 'applications/harbormaster/controller/HarbormasterStepEditController.php', 1443 1443 'HarbormasterStepViewController' => 'applications/harbormaster/controller/HarbormasterStepViewController.php', 1444 + 'HarbormasterString' => 'applications/harbormaster/storage/HarbormasterString.php', 1444 1445 'HarbormasterTargetEngine' => 'applications/harbormaster/engine/HarbormasterTargetEngine.php', 1445 1446 'HarbormasterTargetSearchAPIMethod' => 'applications/harbormaster/conduit/HarbormasterTargetSearchAPIMethod.php', 1446 1447 'HarbormasterTargetWorker' => 'applications/harbormaster/worker/HarbormasterTargetWorker.php', ··· 7070 7071 'HarbormasterStepDeleteController' => 'HarbormasterPlanController', 7071 7072 'HarbormasterStepEditController' => 'HarbormasterPlanController', 7072 7073 'HarbormasterStepViewController' => 'HarbormasterPlanController', 7074 + 'HarbormasterString' => 'HarbormasterDAO', 7073 7075 'HarbormasterTargetEngine' => 'Phobject', 7074 7076 'HarbormasterTargetSearchAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 7075 7077 'HarbormasterTargetWorker' => 'HarbormasterWorker',
+31
src/applications/harbormaster/query/HarbormasterBuildUnitMessageQuery.php
··· 57 57 return $where; 58 58 } 59 59 60 + protected function didFilterPage(array $messages) { 61 + $indexes = array(); 62 + foreach ($messages as $message) { 63 + $index = $message->getNameIndex(); 64 + if (strlen($index)) { 65 + $indexes[$index] = $index; 66 + } 67 + } 68 + 69 + if ($indexes) { 70 + $map = HarbormasterString::newIndexMap($indexes); 71 + 72 + foreach ($messages as $message) { 73 + $index = $message->getNameIndex(); 74 + 75 + if (!strlen($index)) { 76 + continue; 77 + } 78 + 79 + $name = idx($map, $index); 80 + if ($name === null) { 81 + $name = pht('Unknown Unit Message ("%s")', $index); 82 + } 83 + 84 + $message->setName($name); 85 + } 86 + } 87 + 88 + return $messages; 89 + } 90 + 60 91 public function getQueryApplicationClass() { 61 92 return 'PhabricatorHarbormasterApplication'; 62 93 }
+54
src/applications/harbormaster/storage/HarbormasterString.php
··· 1 + <?php 2 + 3 + final class HarbormasterString 4 + extends HarbormasterDAO { 5 + 6 + protected $stringIndex; 7 + protected $stringValue; 8 + 9 + protected function getConfiguration() { 10 + return array( 11 + self::CONFIG_TIMESTAMPS => false, 12 + self::CONFIG_COLUMN_SCHEMA => array( 13 + 'stringIndex' => 'bytes12', 14 + 'stringValue' => 'text', 15 + ), 16 + self::CONFIG_KEY_SCHEMA => array( 17 + 'key_string' => array( 18 + 'columns' => array('stringIndex'), 19 + 'unique' => true, 20 + ), 21 + ), 22 + ) + parent::getConfiguration(); 23 + } 24 + 25 + public static function newIndex($string) { 26 + $index = PhabricatorHash::digestForIndex($string); 27 + 28 + $table = new self(); 29 + $conn = $table->establishConnection('w'); 30 + 31 + queryfx( 32 + $conn, 33 + 'INSERT IGNORE INTO %R (stringIndex, stringValue) VALUES (%s, %s)', 34 + $table, 35 + $index, 36 + $string); 37 + 38 + return $index; 39 + } 40 + 41 + public static function newIndexMap(array $indexes) { 42 + $table = new self(); 43 + $conn = $table->establishConnection('r'); 44 + 45 + $rows = queryfx_all( 46 + $conn, 47 + 'SELECT stringIndex, stringValue FROM %R WHERE stringIndex IN (%Ls)', 48 + $table, 49 + $indexes); 50 + 51 + return ipull($rows, 'stringValue', 'stringIndex'); 52 + } 53 + 54 + }
+29
src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php
··· 8 8 protected $engine; 9 9 protected $namespace; 10 10 protected $name; 11 + protected $nameIndex; 11 12 protected $result; 12 13 protected $duration; 13 14 protected $properties = array(); ··· 132 133 'engine' => 'text255', 133 134 'namespace' => 'text255', 134 135 'name' => 'text255', 136 + 'nameIndex' => 'bytes12', 135 137 'result' => 'text32', 136 138 'duration' => 'double?', 137 139 ), ··· 258 260 ); 259 261 260 262 return implode("\0", $parts); 263 + } 264 + 265 + public function save() { 266 + if ($this->nameIndex === null) { 267 + $this->nameIndex = HarbormasterString::newIndex($this->getName()); 268 + } 269 + 270 + // See T13088. While we're letting installs do online migrations to avoid 271 + // downtime, don't populate the "name" column for new writes. New writes 272 + // use the "HarbormasterString" table instead. 273 + $old_name = $this->name; 274 + $this->name = ''; 275 + 276 + $caught = null; 277 + try { 278 + $result = parent::save(); 279 + } catch (Exception $ex) { 280 + $caught = $ex; 281 + } 282 + 283 + $this->name = $old_name; 284 + 285 + if ($caught) { 286 + throw $caught; 287 + } 288 + 289 + return $result; 261 290 } 262 291 263 292