@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<?php
2
3final class PhabricatorConfigClusterSearchController
4 extends PhabricatorConfigServicesController {
5
6 public function handleRequest(AphrontRequest $request) {
7 $title = pht('Search Servers');
8 $doc_href = PhabricatorEnv::getDoclink('Cluster: Search');
9
10 $button = id(new PHUIButtonView())
11 ->setIcon('fa-book')
12 ->setHref($doc_href)
13 ->setTag('a')
14 ->setText(pht('Documentation'));
15
16 $header = $this->buildHeaderView($title, $button);
17
18 $search_status = $this->buildClusterSearchStatus();
19
20 $crumbs = $this->newCrumbs()
21 ->addTextCrumb($title);
22
23 $content = id(new PHUITwoColumnView())
24 ->setHeader($header)
25 ->setFooter($search_status);
26
27 $nav = $this->newNavigation('search-servers');
28
29 return $this->newPage()
30 ->setTitle($title)
31 ->setCrumbs($crumbs)
32 ->setNavigation($nav)
33 ->appendChild($content);
34 }
35
36 private function buildClusterSearchStatus() {
37 $viewer = $this->getViewer();
38
39 $services = PhabricatorSearchService::getAllServices();
40 Javelin::initBehavior('phabricator-tooltips');
41
42 $view = array();
43 foreach ($services as $service) {
44 $view[] = $this->renderStatusView($service);
45 }
46 return $view;
47 }
48
49 private function renderStatusView($service) {
50 $head = array_merge(
51 array(pht('Type')),
52 array_keys($service->getStatusViewColumns()),
53 array(pht('Status')));
54
55 $rows = array();
56
57 $status_map = PhabricatorSearchService::getConnectionStatusMap();
58 $stats = false;
59 $stats_view = false;
60
61 foreach ($service->getHosts() as $host) {
62 try {
63 // Default status icon
64 //
65 // At the moment the default status is shown also when
66 // you just use MySQL as search server. So, on MySQL it
67 // shows "Unknown" even if probably it should says "Active".
68 // If you have time, please improve the MySQL getConnectionStatus()
69 // to return something more useful than this default.
70 $default_status = array(
71 'icon' => 'fa-question-circle',
72 'color' => 'blue',
73 'label' => pht('Unknown'),
74 );
75 $status = $host->getConnectionStatus();
76 $status = idx($status_map, $status, $default_status);
77 } catch (Exception $ex) {
78 $status['icon'] = 'fa-times';
79 $status['label'] = pht('Connection Error');
80 $status['color'] = 'red';
81 $host->didHealthCheck(false);
82 }
83
84 if (!$stats_view) {
85 try {
86 $stats = $host->getEngine()->getIndexStats($host);
87 $stats_view = $this->renderIndexStats($stats);
88 } catch (Exception $e) {
89 $stats_view = false;
90 }
91 }
92
93 $type_icon = 'fa-search sky';
94 $type_tip = $host->getDisplayName();
95
96 $type_icon = id(new PHUIIconView())
97 ->setIcon($type_icon);
98 $status_view = array(
99 id(new PHUIIconView())->setIcon($status['icon'].' '.$status['color']),
100 ' ',
101 $status['label'],
102 );
103 $row = array(array($type_icon, ' ', $type_tip));
104 $row = array_merge($row, array_values(
105 $host->getStatusViewColumns()));
106 $row[] = $status_view;
107 $rows[] = $row;
108 }
109
110 $table = id(new AphrontTableView($rows))
111 ->setNoDataString(pht('No search servers are configured.'))
112 ->setHeaders($head);
113
114 $view = $this->buildConfigBoxView(pht('Search Servers'), $table);
115
116 $stats = null;
117 if ($stats_view->hasAnyProperties()) {
118 $stats = $this->buildConfigBoxView(
119 pht('%s Stats', $service->getDisplayName()),
120 $stats_view);
121 }
122
123 return array($stats, $view);
124 }
125
126 private function renderIndexStats($stats) {
127 $view = new PHUIPropertyListView();
128 if ($stats !== false) {
129 foreach ($stats as $label => $val) {
130 $view->addProperty($label, $val);
131 }
132 }
133 return $view;
134 }
135
136}