{displayHighlighted(
row.key,
- cache.encoding.key as EncodingType,
+ cache.encoding?.key as EncodingType,
row.keyContentType as ContentType
)}
{displayHighlighted(
row.value,
- cache.encoding.value as EncodingType,
+ cache.encoding?.value as EncodingType,
row.valueContentType as ContentType
)}
@@ -539,7 +543,7 @@ const CacheEntries = () => {
)}
{
/>
{
- const health = ComponentHealth[props.health];
+const Health = (props: { health?: string; displayIcon?: boolean; cacheName?: string }) => {
+ const health = props.health ? ComponentHealth[props.health] : ComponentHealth.UNKNOWN;
const displayIcon = props.displayIcon == undefined ? true : props.displayIcon;
const { theme } = useContext(ThemeContext);
diff --git a/src/app/assets/languages/en.json b/src/app/assets/languages/en.json
index d42dfc9c..9aada459 100644
--- a/src/app/assets/languages/en.json
+++ b/src/app/assets/languages/en.json
@@ -11,6 +11,7 @@
"security-realms-docs-link": "https://infinispan.org/docs/stable/titles/security/security.html#security-realms"
},
"common": {
+ "loading": "Loading...",
"actions": {
"actions": "Actions",
"refresh": "Refresh",
@@ -575,6 +576,9 @@
"back": "Back"
},
"entries": {
+ "read-error": "Connected user lacks BULK_READ permission to browse the cache content.",
+ "read-error-unknown-type": "This cache contains entries that can not be read or edited from the Console.",
+ "read-error-spring-session": "This cache contains Spring Session entries that can not be read or edited from the Console.",
"action-edit": "Edit",
"action-delete": "Delete",
"action-enter": "Enter",
diff --git a/src/app/providers/CacheDetailProvider.tsx b/src/app/providers/CacheDetailProvider.tsx
index cb8feb01..5242b6f3 100644
--- a/src/app/providers/CacheDetailProvider.tsx
+++ b/src/app/providers/CacheDetailProvider.tsx
@@ -70,23 +70,63 @@ const CacheDetailProvider = ({ children }) => {
if (eitherDetail.isRight()) {
setCache(eitherDetail.value);
} else {
- setError(eitherDetail.value.message);
+ // Cache can be unhealthy but existing
+ ConsoleServices.caches()
+ .retrieveHealth(cacheName)
+ .then((eitherHealth) => {
+ if (eitherHealth.isRight()) {
+ // We have the health. Get the config
+ return ConsoleServices.caches()
+ .retrieveConfig(cacheName)
+ .then((eitherConfig) => {
+ if (eitherConfig.isRight()) {
+ const detail: DetailedInfinispanCache = {
+ name: cacheName,
+ configuration: eitherConfig.value,
+ health: eitherHealth.value,
+ started: false
+ };
+ setCache(detail);
+ // we are good;
+ return '';
+ } else {
+ // return the error
+ return eitherConfig.value.message;
+ }
+ })
+ .finally(() => {
+ // loading is over here
+ setLoading(false);
+ });
+ // we are good
+ return '';
+ } else {
+ // return the error
+ return eitherHealth.value.message;
+ }
+ })
+ .then((error) => {
+ if (error.length > 0) {
+ setError(error);
+ setLoading(false);
+ }
+ });
}
})
.finally(() => {
- setLoading(false);
- isEncodingAvailable(cache) && setLoadingEntries(true);
+ setLoadingEntries(isEncodingAvailable(cache));
});
} else {
setError(maybeCm.value.message);
}
- });
+ })
+ .finally(() => setLoading(false));
}
};
const fetchEntry = (keyToSearch: string, kct: ContentType) => {
ConsoleServices.caches()
- .getEntry(cacheName, cache.encoding, keyToSearch, kct)
+ .getEntry(cacheName, cache.encoding!, keyToSearch, kct)
.then((response) => {
let entries: CacheEntry[] = [];
if (response.isRight()) {
@@ -103,7 +143,7 @@ const CacheDetailProvider = ({ children }) => {
if (ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.BULK_READ, cacheName, connectedUser)) {
if (cache) {
ConsoleServices.caches()
- .getEntries(cacheName, cache.encoding, limit)
+ .getEntries(cacheName, cache.encoding!, limit)
.then((eitherEntries) => {
if (eitherEntries.isRight()) {
setCacheEntries(eitherEntries.value);
@@ -124,7 +164,7 @@ const CacheDetailProvider = ({ children }) => {
}
} else {
setLoadingEntries(false);
- setInfoEntries('Connected user lacks BULK_READ permission to browse the cache content.');
+ setInfoEntries('caches.entries.read-error');
}
}
};
diff --git a/src/app/utils/encodingUtils.ts b/src/app/utils/encodingUtils.ts
index 023fa810..f6290c76 100644
--- a/src/app/utils/encodingUtils.ts
+++ b/src/app/utils/encodingUtils.ts
@@ -1,5 +1,8 @@
import { EncodingType } from '@services/infinispanRefData';
export function isEncodingAvailable(cache: DetailedInfinispanCache): boolean {
- return cache?.encoding?.key !== EncodingType.Empty || cache?.encoding?.value !== EncodingType.Empty;
+ return (
+ cache?.encoding !== undefined &&
+ (cache?.encoding?.key !== EncodingType.Empty || cache?.encoding?.value !== EncodingType.Empty)
+ );
}
diff --git a/src/services/cacheService.ts b/src/services/cacheService.ts
index e04c9113..53e243a0 100644
--- a/src/services/cacheService.ts
+++ b/src/services/cacheService.ts
@@ -19,6 +19,36 @@ export class CacheService {
this.fetchCaller = fetchCaller;
}
+ /**
+ * Retrieve cache health
+ *
+ * @param cacheName
+ */
+ public retrieveHealth(cacheName: string): Promise> {
+ return this.fetchCaller.get(
+ this.endpoint + '/caches/' + encodeURIComponent(cacheName) + '?action=health',
+ (data) => data,
+ undefined,
+ true
+ );
+ }
+
+ /**
+ * Retrieve cache config
+ *
+ * @param cacheName
+ */
+ public retrieveConfig(cacheName: string): Promise> {
+ return this.fetchCaller.get(
+ this.endpoint + '/caches/' + encodeURIComponent(cacheName) + '?action=config',
+ (data) =>
+ {
+ name: cacheName,
+ config: JSON.stringify(data, null, 2)
+ }
+ );
+ }
+
/**
* Retrieves all the properties to be displayed in the cache detail in a single rest call
*
diff --git a/src/services/fetchCaller.ts b/src/services/fetchCaller.ts
index 9f993ddd..c4173716 100644
--- a/src/services/fetchCaller.ts
+++ b/src/services/fetchCaller.ts
@@ -194,10 +194,10 @@ export class FetchCaller {
if (text.includes("missing type id property '_type'")) {
message = "You are trying to write a JSON key or value that needs '_type' field in this cache.";
} else if (text.includes('Unknown type id : 5901')) {
- message = 'This cache contains Spring Session entries that can not be read or edited from the Console.';
+ message = 'caches.entries.read-error-spring-session';
success = true;
} else if (text.includes('Unknown type id')) {
- message = 'This cache contains entries that can not be read or edited from the Console.';
+ message = 'caches.entries.read-error-unknown-type';
success = true;
} else if (text != '') {
message = errorMessage + '\n' + text;
diff --git a/src/services/infinispanRefData.ts b/src/services/infinispanRefData.ts
index ad8b1dce..1fb7de87 100644
--- a/src/services/infinispanRefData.ts
+++ b/src/services/infinispanRefData.ts
@@ -13,7 +13,8 @@ export enum ComponentHealth {
HEALTHY = 'HEALTHY',
HEALTHY_REBALANCING = 'HEALTHY_REBALANCING',
DEGRADED = 'DEGRADED',
- FAILED = 'FAILED'
+ FAILED = 'FAILED',
+ UNKNOWN = 'UNKNOWN'
}
/**
* Cache configuration utils class
diff --git a/src/types/InfinispanTypes.ts b/src/types/InfinispanTypes.ts
index e4a31602..adc305a9 100644
--- a/src/types/InfinispanTypes.ts
+++ b/src/types/InfinispanTypes.ts
@@ -121,24 +121,25 @@ interface CacheEncoding {
interface DetailedInfinispanCache {
name: string;
configuration?: CacheConfig;
- encoding: CacheEncoding;
- type: string;
+ encoding?: CacheEncoding;
+ type?: string;
started: boolean;
+ health?: string;
size?: number;
rehash_in_progress?: boolean;
indexing_in_progress?: boolean;
rebalancing_enabled?: boolean;
- editable: boolean;
- updateEntry: boolean;
- deleteEntry: boolean;
- queryable: boolean;
- features: Features;
+ editable?: boolean;
+ updateEntry?: boolean;
+ deleteEntry?: boolean;
+ queryable?: boolean;
+ features?: Features;
backupSites?: [XSite];
stats?: CacheStats;
- mode: string;
+ mode?: string;
memory?: CacheMemory;
- async: boolean;
- tracing: boolean;
+ async?: boolean;
+ tracing?: boolean;
}
interface CacheMemory {