@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.

Give bin/storage some replica-aware options

Summary:
Fixes T10758.

- Adds a "--host" flag. If you specify this, we read your cluster config. This lets you dump from a replica.
- Adds a "--for-replica" flag to `storage dump`. This makes `mysqldump` include a `CHANGE MASTER ...` statement in the output, which is useful when setting up a replica for the first time.

Test Plan:
- Dumped master and replica cluster databases.
- Dumped non-cluster databases.
- Ran various other commands (help, status, etc).

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10758

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

+87 -22
+37 -4
scripts/sql/manage_storage.php
··· 31 31 'Do not prompt before performing dangerous operations.'), 32 32 ), 33 33 array( 34 + 'name' => 'host', 35 + 'param' => 'hostname', 36 + 'help' => pht( 37 + 'Connect to __host__ instead of the default host.'), 38 + ), 39 + array( 34 40 'name' => 'user', 35 41 'short' => 'u', 36 42 'param' => 'username', ··· 75 81 // First, test that the Phabricator configuration is set up correctly. After 76 82 // we know this works we'll test any administrative credentials specifically. 77 83 78 - $ref = PhabricatorDatabaseRef::getMasterDatabaseRef(); 79 - if (!$ref) { 80 - throw new Exception( 81 - pht('No database master is configured.')); 84 + $host = $args->getArg('host'); 85 + if (strlen($host)) { 86 + $ref = null; 87 + 88 + $refs = PhabricatorDatabaseRef::getLiveRefs(); 89 + 90 + // Include the master in case the user is just specifying a redundant 91 + // "--host" flag for no reason and does not actually have a database 92 + // cluster configured. 93 + $refs[] = PhabricatorDatabaseRef::getMasterDatabaseRef(); 94 + 95 + foreach ($refs as $possible_ref) { 96 + if ($possible_ref->getHost() == $host) { 97 + $ref = $possible_ref; 98 + break; 99 + } 100 + } 101 + 102 + if (!$ref) { 103 + throw new PhutilArgumentUsageException( 104 + pht( 105 + 'There is no configured database on host "%s". This command can '. 106 + 'only interact with configured databases.', 107 + $host)); 108 + } 109 + } else { 110 + $ref = PhabricatorDatabaseRef::getMasterDatabaseRef(); 111 + if (!$ref) { 112 + throw new Exception( 113 + pht('No database master is configured.')); 114 + } 82 115 } 83 116 84 117 $default_user = $ref->getUser();
+8 -3
src/docs/user/cluster/cluster_databases.diviner
··· 296 296 be slow, so offloading it to a replica can make the performance of the master 297 297 more consistent. 298 298 299 - To dump from a replica, wait for this TODO to be resolved and then do whatever 300 - it says to do: 299 + To dump from a replica, you can use `bin/storage dump --host <host>` to 300 + control which host the command connects to. (You may still want to execute 301 + this command //from// that host, to avoid sending the whole dump over the 302 + network). 301 303 302 - TODO: Make `bin/storage dump` replica-aware. See T10758. 304 + With the `--for-replica` flag, the `bin/storage dump` command creates dumps 305 + with `--dump-slave`, which includes a `CHANGE MASTER` statement in the output. 306 + This may be helpful when initially setting up new replicas, as it can make it 307 + easier to change the binlog coordinates to the correct position for the dump. 303 308 304 309 With recent versions of MySQL, it is also possible to configure a //delayed// 305 310 replica which intentionally lags behind the master (say, by 12 hours). In the
+42 -15
src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php
··· 7 7 $this 8 8 ->setName('dump') 9 9 ->setExamples('**dump** [__options__]') 10 - ->setSynopsis(pht('Dump all data in storage to stdout.')); 10 + ->setSynopsis(pht('Dump all data in storage to stdout.')) 11 + ->setArguments( 12 + array( 13 + array( 14 + 'name' => 'for-replica', 15 + 'help' => pht( 16 + 'Add __--dump-slave__ to the __mysqldump__ command, '. 17 + 'generating a CHANGE MASTER statement in the output.'), 18 + ), 19 + )); 11 20 } 12 21 13 22 public function didExecute(PhutilArgumentParser $args) { 14 - $api = $this->getAPI(); 23 + $api = $this->getAPI(); 15 24 $patches = $this->getPatches(); 16 25 17 26 $console = PhutilConsole::getConsole(); ··· 33 42 34 43 list($host, $port) = $this->getBareHostAndPort($api->getHost()); 35 44 36 - $flag_password = ''; 37 45 $password = $api->getPassword(); 38 46 if ($password) { 39 47 if (strlen($password->openEnvelope())) { 40 - $flag_password = csprintf('-p%P', $password); 48 + $has_password = true; 41 49 } 42 50 } 43 51 44 - $flag_port = $port 45 - ? csprintf('--port %d', $port) 46 - : ''; 52 + $argv = array(); 53 + $argv[] = '--hex-blob'; 54 + $argv[] = '--single-transaction'; 55 + $argv[] = '--default-character-set=utf8'; 56 + 57 + if ($args->getArg('for-replica')) { 58 + $argv[] = '--dump-slave'; 59 + } 60 + 61 + $argv[] = '-u'; 62 + $argv[] = $api->getUser(); 63 + $argv[] = '-h'; 64 + $argv[] = $host; 47 65 48 - return phutil_passthru( 49 - 'mysqldump --hex-blob --single-transaction --default-character-set=utf8 '. 50 - '-u %s %C -h %s %C --databases %Ls', 51 - $api->getUser(), 52 - $flag_password, 53 - $host, 54 - $flag_port, 55 - $databases); 66 + if ($port) { 67 + $argv[] = '--port'; 68 + $argv[] = $port; 69 + } 70 + 71 + $argv[] = '--databases'; 72 + foreach ($databases as $database) { 73 + $argv[] = $database; 74 + } 75 + 76 + if ($has_password) { 77 + $err = phutil_passthru('mysqldump -p%P %Ls', $password, $argv); 78 + } else { 79 + $err = phutil_passthru('mysqldump %Ls', $argv); 80 + } 81 + 82 + return $err; 56 83 } 57 84 58 85 }