Page MenuHomePhabricator

D19793.diff
No OneTemporary

D19793.diff

diff --git a/src/applications/repository/management/PhabricatorRepositoryManagementThawWorkflow.php b/src/applications/repository/management/PhabricatorRepositoryManagementThawWorkflow.php
--- a/src/applications/repository/management/PhabricatorRepositoryManagementThawWorkflow.php
+++ b/src/applications/repository/management/PhabricatorRepositoryManagementThawWorkflow.php
@@ -120,33 +120,71 @@
$repository->getDisplayName()));
}
- $bindings = $service->getActiveBindings();
- $bindings = mpull($bindings, null, 'getDevicePHID');
- if (empty($bindings[$device->getPHID()])) {
- throw new PhutilArgumentUsageException(
- pht(
- 'Repository "%s" has no active binding to device "%s". Only '.
- 'actively bound devices can be promoted or demoted.',
- $repository->getDisplayName(),
- $device->getName()));
- }
-
- $versions = PhabricatorRepositoryWorkingCopyVersion::loadVersions(
- $repository->getPHID());
-
- $versions = mpull($versions, null, 'getDevicePHID');
- $versions = array_select_keys($versions, array_keys($bindings));
-
- if ($versions && $promote) {
- throw new PhutilArgumentUsageException(
- pht(
- 'Unable to promote "%s" for repository "%s": the leaders for '.
- 'this cluster are not ambiguous.',
- $device->getName(),
- $repository->getDisplayName()));
- }
-
if ($promote) {
+ // You can only promote active devices. (You may demote active or
+ // inactive devices.)
+ $bindings = $service->getActiveBindings();
+ $bindings = mpull($bindings, null, 'getDevicePHID');
+ if (empty($bindings[$device->getPHID()])) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Repository "%s" has no active binding to device "%s". Only '.
+ 'actively bound devices can be promoted.',
+ $repository->getDisplayName(),
+ $device->getName()));
+ }
+
+ $versions = PhabricatorRepositoryWorkingCopyVersion::loadVersions(
+ $repository->getPHID());
+ $versions = mpull($versions, null, 'getDevicePHID');
+
+ // Before we promote, make sure there are no outstanding versions on
+ // devices with inactive bindings. If there are, you need to demote
+ // these first.
+ $inactive = array();
+ foreach ($versions as $device_phid => $version) {
+ if (isset($bindings[$device_phid])) {
+ continue;
+ }
+ $inactive[$device_phid] = $version;
+ }
+
+ if ($inactive) {
+ $handles = $viewer->loadHandles(array_keys($inactive));
+
+ $handle_list = iterator_to_array($handles);
+ $handle_list = mpull($handle_list, 'getName');
+ $handle_list = implode(', ', $handle_list);
+
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Repository "%s" has versions on inactive devices. Demote '.
+ '(or reactivate) these devices before promoting a new '.
+ 'leader: %s.',
+ $repository->getDisplayName(),
+ $handle_list));
+ }
+
+ // Now, make sure there are no outstanding versions on devices with
+ // active bindings. These also need to be demoted (or promoting is a
+ // mistake or already happened).
+ $active = array_select_keys($versions, array_keys($bindings));
+ if ($active) {
+ $handles = $viewer->loadHandles(array_keys($active));
+
+ $handle_list = iterator_to_array($handles);
+ $handle_list = mpull($handle_list, 'getName');
+ $handle_list = implode(', ', $handle_list);
+
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Unable to promote "%s" for repository "%s" because this '.
+ 'cluster already has one or more unambiguous leaders: %s.',
+ $device->getName(),
+ $repository->getDisplayName(),
+ $handle_list));
+ }
+
PhabricatorRepositoryWorkingCopyVersion::updateVersion(
$repository->getPHID(),
$device->getPHID(),
diff --git a/src/docs/user/cluster/cluster_repositories.diviner b/src/docs/user/cluster/cluster_repositories.diviner
--- a/src/docs/user/cluster/cluster_repositories.diviner
+++ b/src/docs/user/cluster/cluster_repositories.diviner
@@ -414,28 +414,24 @@
push logs.
If you are comfortable discarding these changes, you can instruct Phabricator
-that it can forget about the leaders in two ways: disable the service bindings
-to all of the leader devices so they are no longer part of the cluster, or use
-`bin/repository thaw` to `--demote` the leaders explicitly.
+that it can forget about the leaders by doing this:
-If you do this, **you will lose data**. Either action will discard any changes
-on the affected leaders which have not replicated to other devices in the
-cluster.
+ - Disable the service bindings to all of the leader devices so they are no
+ longer part of the cluster.
+ - Then, use `bin/repository thaw` to `--demote` the leaders explicitly.
-To remove a device from the cluster, disable all of the bindings to it
-in Almanac, using the web UI.
-
-{icon exclamation-triangle, color="red"} Any data which is only present on
-the disabled device will be lost.
-
-To demote a device without removing it from the cluster, run this command:
+To demote a device, run this command:
```
phabricator/ $ ./bin/repository thaw rXYZ --demote repo002.corp.net
```
{icon exclamation-triangle, color="red"} Any data which is only present on
-**this** device will be lost.
+the demoted device will be lost.
+
+If you do this, **you will lose unreplicated data**. You will discard any
+changes on the affected leaders which have not replicated to other devices
+in the cluster.
Ambiguous Leaders

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 19, 4:09 PM (1 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7396067
Default Alt Text
D19793.diff (6 KB)

Event Timeline