Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhanced DistributedObjectAdmin to compare for inconsistencies between instances #426

Open
wants to merge 31 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
16e5127
Renamed HzObjectAdminController to DistributedObjectAdminController
jskupsik Nov 25, 2024
d189178
Standardized naming in getAdminStatsForObject()
jskupsik Nov 26, 2024
1849506
Improved ClusterService and ClusterConfig logging
jskupsik Nov 26, 2024
9d827a2
Moved distributed object code to DistributedObjectAdminService
jskupsik Nov 26, 2024
43f6886
ClusterHealthCheckService WIP
jskupsik Nov 27, 2024
787aa19
Merge remote-tracking branch 'refs/remotes/origin/develop' into multi…
jskupsik Nov 27, 2024
c1d848b
Renamed new feature to ClusterConsistencyCheck
jskupsik Nov 27, 2024
c5f4c67
WIP on admin tab
jskupsik Nov 28, 2024
0867cd9
WIP on admin tab
jskupsik Dec 5, 2024
f8dde4a
WIP on admin tab
jskupsik Dec 6, 2024
87d9656
WIP on admin tab
jskupsik Dec 9, 2024
3e0bad0
Merged old distributed objects tab with new changes
jskupsik Dec 9, 2024
423d2e7
WIP work
jskupsik Dec 10, 2024
58dabe2
CachedValue's initial entry (not entered/synced) no longer reports a …
jskupsik Dec 11, 2024
740261d
Bug fixes and name standardization
jskupsik Dec 11, 2024
4eb6e0e
WIP work
jskupsik Dec 12, 2024
14a390c
UI/filtering enhancements
jskupsik Dec 12, 2024
010ceec
Merge remote-tracking branch 'origin/develop' into multiInstanceCompare
jskupsik Dec 12, 2024
ae438e1
Updated CHANGELOG.md
jskupsik Dec 12, 2024
7be4e54
Added error handling, comparing objects
jskupsik Dec 17, 2024
961233f
Moved DistributedObjects to a 2nd level tab
jskupsik Dec 18, 2024
eaaed2f
Added non-comparison fields to detail grid
jskupsik Dec 18, 2024
3d54cb1
Removed the hashCode() check from Cache and CachedValue
jskupsik Dec 19, 2024
f930d0d
Merge branch 'develop' into multiInstanceCompare
amcclain Jan 2, 2025
46f864a
Update copyright date, fix package
amcclain Jan 2, 2025
78eca10
Code review changes
jskupsik Jan 2, 2025
4b8f2e3
Cleaned up getHzInfo/getHoistInfo symmetry
jskupsik Jan 2, 2025
8f1fe7d
Added comment to BaseService getComparisonFields() method
jskupsik Jan 2, 2025
d52a6fc
Merge branch 'develop' into multiInstanceCompare
lbwexler Jan 3, 2025
425c695
Fixed bug where server was not setting itself as primary on init
jskupsik Jan 3, 2025
139dcac
Checkpoint (#432)
lbwexler Jan 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@

## 27.0-SNAPSHOT - unreleased

### 💥 Breaking Changes (upgrade difficulty: 🟢 LOW - Hoist React update)

* Requires `hoist-react >= 71` to support enhanced Distributed Objects page.

### 🎁 New Features

* Added server-side APIs for the new Hoist React `ViewManager` component. Note this Hoist Core
release will be required by `hoist-react >= 71`.
* `DistributedObjectAdminService` now compares certain `adminState` fields of distributed objects
between instances. Implement `BaseService.getComparisonFields()` to enumerate custom fields to
compare.

## 26.0.0 - 2024-12-02

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import io.xh.hoist.util.Utils
import static io.xh.hoist.util.DateTimeUtils.SECONDS

import static grails.async.Promises.task

import static java.lang.Thread.sleep

@Access(['HOIST_ADMIN_READER'])
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* This file belongs to Hoist, an application development toolkit
* developed by Extremely Heavy Industries (www.xh.io | [email protected])
*
* Copyright © 2025 Extremely Heavy Industries Inc.
*/
package io.xh.hoist.admin.cluster

import io.xh.hoist.BaseController
import io.xh.hoist.security.Access

@Access(['HOIST_ADMIN_READER'])
class ClusterObjectsAdminController extends BaseController {
def clusterObjectsService

def getClusterObjectsReport() {
renderJSON(clusterObjectsService.getClusterObjectsReport())
}

@Access(['HOIST_ADMIN'])
def clearHibernateCaches() {
def req = parseRequestJSON()
clusterObjectsService.clearHibernateCaches(req.names)
renderJSON([success: true])
}

@Access(['HOIST_ADMIN'])
def clearAllHibernateCaches() {
clusterObjectsService.clearHibernateCaches()
renderJSON([success: true])
}
}

This file was deleted.

81 changes: 81 additions & 0 deletions grails-app/services/io/xh/hoist/admin/ClusterObjectsService.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* This file belongs to Hoist, an application development toolkit
* developed by Extremely Heavy Industries (www.xh.io | [email protected])
*
* Copyright © 2025 Extremely Heavy Industries Inc.
*/
package io.xh.hoist.admin

import com.hazelcast.cache.impl.CacheProxy
import com.hazelcast.executor.impl.ExecutorServiceProxy
import io.xh.hoist.AdminStats
import io.xh.hoist.BaseService
import io.xh.hoist.cluster.ClusterRequest

import static io.xh.hoist.util.Utils.appContext
import static java.lang.System.currentTimeMillis

class ClusterObjectsService extends BaseService {
def grailsApplication

ClusterObjectsReport getClusterObjectsReport() {
def startTimestamp = currentTimeMillis(),
info = clusterService
.submitToAllInstances(new ListClusterObjects())
.collectMany { it.value.value }

return new ClusterObjectsReport(
info: info,
startTimestamp: startTimestamp,
endTimestamp: currentTimeMillis()
)
}

/**
* Clear all Hibernate caches, or a specific list of caches by name.
*/
void clearHibernateCaches(List<String> names = null) {
def caches = clusterService.distributedObjects.findAll {it instanceof CacheProxy}
names ?= caches*.name
names.each { name ->
def obj = caches.find { it.name == name }
if (obj) {
obj.clear()
logInfo('Cleared ' + name)
} else {
logWarn('Cannot find cache', name)
}
}
}

//--------------------
// Implementation
//--------------------
private List<ClusterObjectInfo> listClusterObjects() {
// Services and their AdminStat implementing resources
Map<String, BaseService> svcs = grailsApplication.mainContext.getBeansOfType(BaseService.class, false, false)
def hoistObjs = svcs.collectMany { _, svc ->
[
new ClusterObjectInfo(name: svc.class.name, type: 'Service', target: svc),
*svc.resources
.findAll { k, v -> v instanceof AdminStats }
.collect { k, v -> new ClusterObjectInfo(name: svc.hzName(k), target: v) }
]
}

// Hazelcast built-ins
def hzObjs = clusterService
.hzInstance
.distributedObjects
.findAll { !(it instanceof ExecutorServiceProxy) }
.collect { new ClusterObjectInfo(target: new HzAdminStats(it)) }

return (hzObjs + hoistObjs) as List<ClusterObjectInfo>
}

static class ListClusterObjects extends ClusterRequest<List<ClusterObjectInfo>> {
List<ClusterObjectInfo> doCall() {
appContext.clusterObjectsService.listClusterObjects()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ package io.xh.hoist.admin

import io.xh.hoist.BaseService
import io.xh.hoist.exception.DataNotAvailableException
import io.xh.hoist.util.DateTimeUtils
import org.apache.tomcat.jdbc.pool.DataSource as PooledDataSource
import org.apache.tomcat.jdbc.pool.PoolConfiguration
import org.springframework.boot.jdbc.DataSourceUnwrapper
Expand Down Expand Up @@ -37,7 +36,7 @@ class ConnectionPoolMonitoringService extends BaseService {
createTimer(
name: 'takeSnapshot',
runFn: this.&takeSnapshot,
interval: {enabled ? config.snapshotInterval * DateTimeUtils.SECONDS: -1}
interval: {enabled ? config.snapshotInterval * SECONDS: -1}
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
package io.xh.hoist.admin

import com.hazelcast.core.DistributedObject
import io.xh.hoist.AdminStats
import io.xh.hoist.BaseService

class ServiceManagerService extends BaseService {

def grailsApplication,
clusterAdminService
def grailsApplication

Collection<Map> listServices() {
getServicesInternal().collect { name, svc ->
Expand Down Expand Up @@ -47,19 +47,19 @@ class ServiceManagerService extends BaseService {
// Implementation
//----------------------
private List getResourceStats(BaseService svc) {
def ret = []
svc.resources
.findAll { !it.key.startsWith('xh_') } // skip hoist implementation objects
.collect { k, v ->
Map stats = v instanceof DistributedObject ?
clusterAdminService.getAdminStatsForObject(v) :
v.adminStats

.each { k, v ->
AdminStats stats = null
if (v instanceof AdminStats) stats = v
if (v instanceof DistributedObject) stats = new HzAdminStats(v)
// rely on the name (key) service knows, i.e avoid HZ prefix
return [*: stats, name: k]
if (stats) ret << [*: stats.adminStats, name: k]
}
return ret
}


private Map<String, BaseService> getServicesInternal() {
return grailsApplication.mainContext.getBeansOfType(BaseService.class, false, false)
}
Expand Down
Loading
Loading