This is an automated email from the ASF dual-hosted git repository.
andytaylor pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/artemis-console.git
The following commit(s) were added to refs/heads/main by this push:
new 4a9d0b5 ARTEMIS-6030 - added status of lock coordinators to console
4a9d0b5 is described below
commit 4a9d0b5b374a23dcc6aa4fb04609f69d8e52a5ec
Author: Andy Taylor <[email protected]>
AuthorDate: Mon Apr 27 10:07:48 2026 +0100
ARTEMIS-6030 - added status of lock coordinators to console
---
.../artemis-console-plugin/src/artemis-service.ts | 54 +++++++++++++++++++++-
.../src/status/Status.test.tsx | 1 +
.../artemis-console-plugin/src/status/Status.tsx | 47 ++++++++++++++++++-
3 files changed, 100 insertions(+), 2 deletions(-)
diff --git
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-service.ts
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-service.ts
index 75c5e40..5d1b3dc 100644
---
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-service.ts
+++
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/artemis-service.ts
@@ -97,6 +97,20 @@ export type Acceptors = {
acceptors: Acceptor[]
}
+export type LockCoordinator = {
+ name: string
+ lockId: string
+ className: string
+ simpleName: string
+ locked: boolean
+ started: boolean
+ status: string
+}
+
+export type LockCoordinators = {
+ lockCoordinators: LockCoordinator[]
+}
+
export type ClusterConnection = {
Started: boolean
Address: string
@@ -164,7 +178,8 @@ const DESTROY_QUEUE_SIG = "destroyQueue(java.lang.String)";
const REMOVE_ALL_MESSAGES_SIG = "removeAllMessages()";
const CLOSE_CONNECTION_SIG = "closeConnectionWithID(java.lang.String)";
const CLOSE_SESSION_SIG =
"closeSessionWithID(java.lang.String,java.lang.String)";
-const CLOSE_CONSUMER_SIG =
"closeConsumerWithID(java.lang.String,java.lang.String)"
+const CLOSE_CONSUMER_SIG =
"closeConsumerWithID(java.lang.String,java.lang.String)";
+const LIST_LOCK_MANAGER_SIG = "listLockCoordinatorsAsJSON()";
const MS_PER_SEC = 1000;
const MS_PER_MIN = 60 * MS_PER_SEC;
@@ -356,6 +371,36 @@ class ArtemisService {
});
}
+ async createLockCoordinators(): Promise<LockCoordinators> {
+ return new Promise<LockCoordinators>(async (resolve, reject) => {
+ const lockCoordinators: LockCoordinators = {
+ lockCoordinators: []
+ };
+ const brokerObjectName = await this.getBrokerObjectName();
+ const brokerMBean = await findMBeanInfo(brokerObjectName);
+ const doesListLockCoordinatorMethodExist =
this.doesListLockCoordinatorMethodExist(brokerMBean as MBeanNode)
+ if (!doesListLockCoordinatorMethodExist) {
+ console.log("Lock Coordinators not available in this broker
version");
+ resolve(lockCoordinators);
+ } else if(this.canListLockCoordinators(brokerMBean as MBeanNode)) {
+ const lockCoordinatorString = await
jolokiaService.execute(brokerObjectName, LIST_LOCK_MANAGER_SIG).catch(error => {
+ eventService.notify({ type: "warning", message:
jolokiaService.errorMessage(error) })
+ return "[]"
+ }) as string;
+ if (lockCoordinatorString) {
+ lockCoordinators.lockCoordinators =
JSON.parse(lockCoordinatorString);
+ console.info("resolved " + lockCoordinators);
+ console.info("from " + lockCoordinatorString);
+ resolve(lockCoordinators);
+ }
+
+ } else {
+ console.info("oops")
+ resolve(lockCoordinators);
+ }
+ reject("invalid response:")
+ });
+ }
async createAcceptors(): Promise<Acceptors> {
return new Promise<Acceptors>(async (resolve, reject) => {
const brokerObjectName = await this.brokerObjectName;
@@ -755,6 +800,9 @@ class ArtemisService {
return (this.DEBUG_PRIVS &&
queueMBean?.hasInvokeRights(SEND_MESSAGE_SIG)) ?? false;
}
+ canListLockCoordinators = (brokerMBean: MBeanNode | undefined): boolean =>
{
+ return (this.DEBUG_PRIVS &&
brokerMBean?.hasInvokeRights(LIST_LOCK_MANAGER_SIG)) ?? false;
+ }
canBrowseQueue = (broker: MBeanNode | undefined, queue: string): boolean
=> {
if(broker) {
const queueMBean = broker.parent?.find(node => {
@@ -810,6 +858,10 @@ class ArtemisService {
return false;
}
+ doesListLockCoordinatorMethodExist = (broker: MBeanNode | undefined):
boolean => {
+ return broker?broker.hasOperations("listLockCoordinatorsAsJSON"):
false;
+ }
+
canListConnections = (broker: MBeanNode | undefined): boolean => {
return (this.DEBUG_PRIVS &&
broker?.hasInvokeRights(LIST_CONNECTIONS_SIG)) ?? false
}
diff --git
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/status/Status.test.tsx
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/status/Status.test.tsx
index 135b99b..3c15901 100644
---
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/status/Status.test.tsx
+++
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/status/Status.test.tsx
@@ -80,6 +80,7 @@ describe('Status', () => {
...mockBrokerState
})
;(artemisService.createAcceptors as jest.Mock).mockResolvedValue({
acceptors: [] })
+ ;(artemisService.createLockCoordinators as jest.Mock).mockResolvedValue({
lockCoordinators: [] })
;(artemisService.createClusterConnections as
jest.Mock).mockResolvedValue({ clusterConnections: [] })
;(artemisService.getBrokerObjectName as
jest.Mock).mockResolvedValue('org.apache.activemq.artemis:broker=127.0.0.1')
})
diff --git
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/status/Status.tsx
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/status/Status.tsx
index eea1a01..b8e2ec7 100644
---
a/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/status/Status.tsx
+++
b/artemis-console-extension/artemis-extension/packages/artemis-console-plugin/src/status/Status.tsx
@@ -46,7 +46,7 @@ import { ExclamationCircleIcon } from
'@patternfly/react-icons/dist/esm/icons/ex
import { OkIcon } from '@patternfly/react-icons/dist/esm/icons/ok-icon'
import { Attributes, eventService, jolokiaService, Operations } from
'@hawtio/react';
import React, { ReactNode, useContext, useEffect, useState } from "react";
-import { Acceptors, artemisService, BrokerInfo, BrokerState,
ClusterConnections } from "../artemis-service";
+import { Acceptors, artemisService, BrokerInfo, BrokerState,
ClusterConnections, LockCoordinators } from "../artemis-service";
import { ArtemisContext } from "../context";
import { Table, Tbody, Td, Th, Thead, Tr } from "@patternfly/react-table";
import { LockedIcon } from '@patternfly/react-icons'
@@ -56,6 +56,7 @@ export const Status: React.FunctionComponent = () => {
const [brokerState, setBrokerState] = useState<BrokerState>({ loaded:
false, accessible: false, message: "Loading..." })
const [brokerInfo, setBrokerInfo] = useState<BrokerInfo>()
const [acceptors, setAcceptors] = useState<Acceptors>();
+ const [lockCoordinators, setLockCoordinators] =
useState<LockCoordinators>();
const [clusterConnections, setClusterConnections] =
useState<ClusterConnections>()
const { findAndSelectNode } = useContext(ArtemisContext)
@@ -86,6 +87,16 @@ export const Status: React.FunctionComponent = () => {
});
}
+ const getLockCoordinators = async () => {
+ artemisService.createLockCoordinators()
+ .then((lockCoordinators) => {
+ setLockCoordinators(lockCoordinators)
+ })
+ .catch((error) => {
+ eventService.notify({type: 'warning', message:
jolokiaService.errorMessage(error) })
+ });
+ }
+
const getClusterConnections = async () => {
artemisService.createClusterConnections()
.then((clusterConnections) => {
@@ -102,6 +113,8 @@ export const Status: React.FunctionComponent = () => {
getAcceptors();
+ getLockCoordinators();
+
getClusterConnections();
// Pause auto-refresh when Operations dialog is open to prevent
collapsing expanded operations
@@ -271,6 +284,38 @@ export const Status: React.FunctionComponent = () => {
</Card>
</GridItem>
</Grid>
+ {lockCoordinators && lockCoordinators.lockCoordinators.length > 0
&&
+ <ExpandableSection toggleTextExpanded="Lock Coordinators"
toggleTextCollapsed="Lock Coordinators">
+ <Grid hasGutter span={4}>
+ <GridItem span={6} rowSpan={3}>
+ <Card isFullHeight={true} >
+ <CardBody>
+ <Divider />
+ <Table>
+ <Thead>
+ <Tr>
+ <Th>Name</Th>
+ <Th>ID</Th>
+ <Th>Status</Th>
+ </Tr>
+ </Thead>
+ <Tbody>
+ {
+
lockCoordinators?.lockCoordinators.map((coordinator, index) => {
+ return <Tr>
+ <Td>{coordinator.name}</Td>
+
<Td>{coordinator.lockId}</Td>
+
<Td>{coordinator.status}</Td>
+ </Tr>
+ })
+ }
+ </Tbody>
+ </Table>
+ </CardBody>
+ </Card>
+ </GridItem>
+ </Grid>
+ </ExpandableSection>}
<ExpandableSection toggleTextExpanded="Acceptors"
toggleTextCollapsed="Acceptors">
<Grid hasGutter span={4}>
{
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]