зеркало из https://github.com/nextcloud/spreed.git
show bridge process state and log
Signed-off-by: Julien Veyssier <eneiluj@posteo.net>
This commit is contained in:
Родитель
f0561d0357
Коммит
b46f39e70d
|
@ -395,6 +395,15 @@ return [
|
|||
'token' => '^[a-z0-9]{4,30}$',
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'Matterbridge#getBridgeProcessState',
|
||||
'url' => '/api/{apiVersion}/bridge/{token}/process',
|
||||
'verb' => 'GET',
|
||||
'requirements' => [
|
||||
'apiVersion' => 'v1',
|
||||
'token' => '^[a-z0-9]{4,30}$',
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'Matterbridge#editBridgeOfRoom',
|
||||
'url' => '/api/{apiVersion}/bridge/{token}',
|
||||
|
|
|
@ -60,11 +60,27 @@ class MatterbridgeController extends AEnvironmentAwareController {
|
|||
* @return DataResponse
|
||||
*/
|
||||
public function getBridgeOfRoom(): DataResponse {
|
||||
$this->bridgeManager->checkBridge($this->room);
|
||||
$pid = $this->bridgeManager->checkBridge($this->room);
|
||||
$logContent = $this->bridgeManager->getBridgeLog($this->room);
|
||||
$bridge = $this->bridgeManager->getBridgeOfRoom($this->room);
|
||||
$bridge['running'] = ($pid !== 0);
|
||||
$bridge['log'] = $logContent;
|
||||
return new DataResponse($bridge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bridge process information
|
||||
*
|
||||
* @NoAdminRequired
|
||||
* @RequireLoggedInModeratorParticipant
|
||||
*
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function getBridgeProcessState(): DataResponse {
|
||||
$result = $this->bridgeManager->getBridgeProcessState($this->room);
|
||||
return new DataResponse($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit bridge information of one room
|
||||
*
|
||||
|
|
|
@ -92,6 +92,36 @@ class MatterbridgeManager {
|
|||
return $this->getBridgeFromDb($room);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bridge process information for a specific room
|
||||
*
|
||||
* @param Room $room the room
|
||||
* @return array process state and log
|
||||
*/
|
||||
public function getBridgeProcessState(Room $room): array {
|
||||
$bridge = $this->getBridgeFromDb($room);
|
||||
|
||||
$logContent = $this->getBridgeLog($room);
|
||||
|
||||
$pid = $this->checkBridgeProcess($room, $bridge, false);
|
||||
return [
|
||||
'running' => ($pid !== 0),
|
||||
'log' => $logContent
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bridge log file content
|
||||
*
|
||||
* @param Room $room the room
|
||||
* @return string log file content
|
||||
*/
|
||||
public function getBridgeLog(Room $room): string {
|
||||
$outputPath = sprintf('/tmp/bridge-%s.log', $room->getToken());
|
||||
$logContent = file_get_contents($outputPath);
|
||||
return $logContent ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit bridge information for a room
|
||||
*
|
||||
|
@ -153,8 +183,9 @@ class MatterbridgeManager {
|
|||
/**
|
||||
* For one room, check mattermost process respects desired state
|
||||
* @param Room $room the room
|
||||
* @return int the bridge process ID
|
||||
*/
|
||||
public function checkBridge(Room $room): void {
|
||||
public function checkBridge(Room $room): int {
|
||||
$bridge = $this->getBridgeOfRoom($room);
|
||||
$pid = $this->checkBridgeProcess($room, $bridge);
|
||||
if ($pid !== $bridge['pid']) {
|
||||
|
@ -162,6 +193,7 @@ class MatterbridgeManager {
|
|||
$bridge['pid'] = $pid;
|
||||
$this->saveBridgeToDb($room, $bridge);
|
||||
}
|
||||
return $pid;
|
||||
}
|
||||
|
||||
private function getDataFolder(): ISimpleFolder {
|
||||
|
@ -437,43 +469,48 @@ class MatterbridgeManager {
|
|||
*
|
||||
* @param Room $room the room
|
||||
* @param array $bridge bridge information
|
||||
* @param $relaunch whether to launch the process if it's down but bridge is enabled
|
||||
* @return int the corresponding matterbridge process ID, 0 if none
|
||||
*/
|
||||
private function checkBridgeProcess(Room $room, array $bridge): int {
|
||||
private function checkBridgeProcess(Room $room, array $bridge, bool $relaunch = true): int {
|
||||
$pid = 0;
|
||||
|
||||
if (isset($bridge['pid']) && intval($bridge['pid']) !== 0) {
|
||||
// config : there is a PID stored
|
||||
$pid = intval($bridge['pid']);
|
||||
$isRunning = $this->isRunning($pid);
|
||||
$isRunning = $this->isRunning($bridge['pid']);
|
||||
// if bridge running and enabled is false : kill it
|
||||
if ($isRunning) {
|
||||
if ($bridge['enabled']) {
|
||||
$this->logger->info('Process running AND bridge enabled in config : doing nothing');
|
||||
$pid = $bridge['pid'];
|
||||
} else {
|
||||
$this->logger->info('Process running AND bridge disabled in config : KILL ' . $pid);
|
||||
$killed = $this->killPid($pid);
|
||||
$this->logger->info('Process running AND bridge disabled in config : KILL ' . $bridge['pid']);
|
||||
$killed = $this->killPid($bridge['pid']);
|
||||
if ($killed) {
|
||||
$pid = 0;
|
||||
} else {
|
||||
$this->logger->info('Impossible to kill ' . $pid);
|
||||
throw new ImpossibleToKillException('Impossible to kill bridge process [' . $pid . ']');
|
||||
$this->logger->info('Impossible to kill ' . $bridge['pid']);
|
||||
throw new ImpossibleToKillException('Impossible to kill bridge process [' . $bridge['pid'] . ']');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no process found
|
||||
if ($bridge['enabled']) {
|
||||
$this->logger->info('Process not found AND bridge enabled in config : relaunching');
|
||||
$pid = $this->launchMatterbridge($room);
|
||||
if ($relaunch) {
|
||||
$this->logger->info('Process not found AND bridge enabled in config : relaunching');
|
||||
$pid = $this->launchMatterbridge($room);
|
||||
}
|
||||
} else {
|
||||
$this->logger->info('Process not found AND bridge disabled in config : doing nothing');
|
||||
}
|
||||
}
|
||||
} elseif ($bridge['enabled']) {
|
||||
// config : no PID stored
|
||||
// config : enabled => launch it
|
||||
$pid = $this->launchMatterbridge($room);
|
||||
$this->logger->info('Launch process, PID is '.$pid);
|
||||
if ($relaunch) {
|
||||
// config : no PID stored
|
||||
// config : enabled => launch it
|
||||
$pid = $this->launchMatterbridge($room);
|
||||
$this->logger->info('Launch process, PID is '.$pid);
|
||||
}
|
||||
} else {
|
||||
$this->logger->info('No PID defined in config AND bridge disabled in config : doing nothing');
|
||||
}
|
||||
|
|
|
@ -40,7 +40,17 @@
|
|||
:checked="enabled"
|
||||
@update:checked="onEnabled">
|
||||
{{ t('spreed', 'Enabled') }}
|
||||
({{ processStateText }})
|
||||
</ActionCheckbox>
|
||||
<button class="" @click="showLogContent">
|
||||
{{ t('spreed', 'Show matterbridge log') }}
|
||||
</button>
|
||||
<Modal v-if="logModal"
|
||||
@close="closeLogModal">
|
||||
<div class="modal__content">
|
||||
<textarea v-model="processLog" class="log-content" />
|
||||
</div>
|
||||
</Modal>
|
||||
<Multiselect
|
||||
ref="partMultiselect"
|
||||
v-model="selectedType"
|
||||
|
@ -73,11 +83,13 @@
|
|||
import {
|
||||
editBridge,
|
||||
getBridge,
|
||||
getBridgeProcessState,
|
||||
} from '../../../services/matterbridgeService'
|
||||
import { showSuccess } from '@nextcloud/dialogs'
|
||||
import ActionCheckbox from '@nextcloud/vue/dist/Components/ActionCheckbox'
|
||||
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
|
||||
import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
|
||||
import Modal from '@nextcloud/vue/dist/Components/Modal'
|
||||
import BridgePart from './BridgePart'
|
||||
|
||||
export default {
|
||||
|
@ -87,6 +99,7 @@ export default {
|
|||
ActionButton,
|
||||
Multiselect,
|
||||
BridgePart,
|
||||
Modal,
|
||||
},
|
||||
|
||||
mixins: [
|
||||
|
@ -100,6 +113,9 @@ export default {
|
|||
enabled: false,
|
||||
parts: [],
|
||||
loading: false,
|
||||
processRunning: null,
|
||||
processLog: '',
|
||||
logModal: false,
|
||||
types: {
|
||||
nctalk: {
|
||||
name: t('spreed', 'Nextcloud Talk'),
|
||||
|
@ -430,6 +446,13 @@ export default {
|
|||
return p.type !== 'nctalk' || p.channel !== this.token
|
||||
})
|
||||
},
|
||||
processStateText() {
|
||||
return this.processRunning === null
|
||||
? t('spreed', 'unknown state')
|
||||
: this.processRunning
|
||||
? t('spreed', 'running')
|
||||
: t('spreed', 'not running')
|
||||
},
|
||||
},
|
||||
|
||||
beforeMount() {
|
||||
|
@ -460,17 +483,17 @@ export default {
|
|||
this.onSave()
|
||||
},
|
||||
onSave() {
|
||||
console.debug(this.parts)
|
||||
this.editBridge(this.token, this.enabled, this.parts)
|
||||
},
|
||||
async getBridge(token) {
|
||||
this.loading = true
|
||||
try {
|
||||
const result = await getBridge(token)
|
||||
console.debug(result)
|
||||
const bridge = result.data.ocs.data
|
||||
this.enabled = bridge.enabled
|
||||
this.parts = bridge.parts
|
||||
this.processLog = bridge.log
|
||||
this.processRunning = bridge.running
|
||||
} catch (exception) {
|
||||
console.debug(exception)
|
||||
}
|
||||
|
@ -485,6 +508,24 @@ export default {
|
|||
console.debug(exception)
|
||||
}
|
||||
this.loading = false
|
||||
setTimeout(() => this.getBridgeProcessState(this.token), 4000)
|
||||
},
|
||||
async getBridgeProcessState(token) {
|
||||
try {
|
||||
const result = await getBridgeProcessState(token)
|
||||
this.processLog = result.data.ocs.data.log
|
||||
this.processRunning = result.data.ocs.data.running
|
||||
console.debug(result.data.ocs.data.log)
|
||||
} catch (exception) {
|
||||
console.debug(exception)
|
||||
}
|
||||
},
|
||||
showLogContent() {
|
||||
this.getBridgeProcessState(this.token)
|
||||
this.logModal = true
|
||||
},
|
||||
closeLogModal() {
|
||||
this.logModal = false
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -514,6 +555,7 @@ export default {
|
|||
}
|
||||
|
||||
.basic-settings {
|
||||
button,
|
||||
.multiselect {
|
||||
width: calc(100% - 40px);
|
||||
margin-left: 40px;
|
||||
|
@ -523,4 +565,9 @@ export default {
|
|||
ul {
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
|
||||
.log-content {
|
||||
width: 600px;
|
||||
height: 400px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -50,6 +50,15 @@ const getBridge = async function(token) {
|
|||
return response
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bridge binary state for a room
|
||||
* @param {token} token the conversation token.
|
||||
*/
|
||||
const getBridgeProcessState = async function(token) {
|
||||
const response = await axios.get(generateOcsUrl('apps/spreed/api/v1', 2) + `bridge/${token}/process`)
|
||||
return response
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask to stop all bridges (and kill all related processes)
|
||||
*/
|
||||
|
@ -71,6 +80,7 @@ const getMatterbridgeVersion = async function() {
|
|||
export {
|
||||
editBridge,
|
||||
getBridge,
|
||||
getBridgeProcessState,
|
||||
stopAllBridges,
|
||||
getMatterbridgeVersion,
|
||||
enableMatterbridgeApp,
|
||||
|
|
Загрузка…
Ссылка в новой задаче