Skip to content

Commit

Permalink
feat: Change Kudos Clustering Mechanism with Cache - MEED-7742 - Meed…
Browse files Browse the repository at this point in the history
…s-io/meeds#2537 (#554)

This change will change the Clustering mechanism to use a Cache instead
of deprecated and dropped `RPCService`.
  • Loading branch information
boubaker authored Nov 15, 2024
1 parent bfcf1db commit 8ab8938
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
@NoArgsConstructor
@AllArgsConstructor
public class GlobalSettings implements Cloneable {

private static final String END_PERIOD_DATE_IN_SECONDS_PARAM = "endPeriodDateInSeconds";

private static final String START_PERIOD_DATE_IN_SECONDS_PARAM = "startPeriodDateInSeconds";
Expand All @@ -39,20 +40,13 @@ public class GlobalSettings implements Cloneable {

private static final String KUDOS_PER_PERIOD_PARAM = "kudosPerPeriod";

private static final String ACCESS_PERMISSION_PARAM = "accessPermission";

String accessPermission;

long kudosPerPeriod;

KudosPeriodType kudosPeriodType = KudosPeriodType.DEFAULT;

public JSONObject toJSONObject(boolean includeTransient) {
JSONObject jsonObject = new JSONObject();
try {
if (accessPermission != null) {
jsonObject.put(ACCESS_PERMISSION_PARAM, accessPermission);
}
jsonObject.put(KUDOS_PER_PERIOD_PARAM, kudosPerPeriod);
jsonObject.put(KUDOS_PERIOD_TYPE_PARAM, kudosPeriodType.name());
if (includeTransient) {
Expand Down Expand Up @@ -96,10 +90,7 @@ public static final GlobalSettings parseStringToObject(String jsonString) {

@Override
public GlobalSettings clone() { // NOSONAR
try {
return (GlobalSettings) super.clone();
} catch (CloneNotSupportedException e) {
return new GlobalSettings(accessPermission, kudosPerPeriod, kudosPeriodType);
}
return new GlobalSettings(kudosPerPeriod, kudosPeriodType);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,22 @@
import static io.meeds.kudos.service.utils.Utils.timeFromSeconds;
import static io.meeds.kudos.service.utils.Utils.timeToSeconds;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import org.exoplatform.commons.api.settings.SettingService;
import org.exoplatform.commons.api.settings.SettingValue;
import org.exoplatform.commons.exception.ObjectNotFoundException;
import org.exoplatform.services.listener.ListenerService;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.rpc.RPCService;
import org.exoplatform.services.rpc.RemoteCommand;
import org.exoplatform.social.core.activity.model.ExoSocialActivity;
import org.exoplatform.social.core.identity.model.Identity;
import org.exoplatform.social.core.identity.provider.OrganizationIdentityProvider;
Expand All @@ -72,7 +68,6 @@
import io.meeds.kudos.model.exception.KudosAlreadyLinkedException;
import io.meeds.kudos.storage.KudosStorage;

import jakarta.annotation.PostConstruct;
import lombok.SneakyThrows;

/**
Expand All @@ -81,12 +76,6 @@
@Service
public class KudosService {

private static final Log LOG = ExoLogger.getLogger(KudosService.class);

private static final String CLUSTER_GLOBAL_SETTINGS_UPDATED = "KudosService-GlobalSettings-Updated";

private static final String CLUSTER_NODE_ID = UUID.randomUUID().toString();

@Autowired
private ActivityManager activityManager;

Expand All @@ -105,53 +94,33 @@ public class KudosService {
@Autowired
private SettingService settingService;

@Autowired(required = false)
private RPCService rpcService;

private GlobalSettings globalSettings;

@Value("${kudos.defaultAccessPermission:}") // NOSONAR
private String defaultAccessPermission;

@Value("${kudos.defaultKudosPerPeriod:3}")
private long defaultKudosPerPeriod;

/**
* The generic command used to replicate changes over the cluster
*/
private RemoteCommand reloadSettingsCommand;

@PostConstruct
public void init() {
GlobalSettings loadedGlobalSettings = loadGlobalSettings();
if (loadedGlobalSettings == null) {
this.globalSettings = new GlobalSettings();
this.globalSettings.setKudosPerPeriod(defaultKudosPerPeriod);
} else {
this.globalSettings = loadedGlobalSettings;
}
installClusterListener();
}

/**
* @return {@link GlobalSettings} of Kudos module
*/
@Cacheable("Kudos.globalSettings")
public GlobalSettings getGlobalSettings() {
if (this.globalSettings == null) {
this.globalSettings = loadGlobalSettings();
SettingValue<?> globalSettingsValue = settingService.get(KUDOS_CONTEXT, KUDOS_SCOPE, SETTINGS_KEY_NAME);
if (globalSettingsValue == null || StringUtils.isBlank(globalSettingsValue.getValue().toString())) {
return new GlobalSettings(defaultKudosPerPeriod, KudosPeriodType.DEFAULT);
} else {
return GlobalSettings.parseStringToObject(globalSettingsValue.getValue().toString());
}
return this.globalSettings;
}

/**
* Stores new parameters of Kudos module
*
* @param settings {@link GlobalSettings}
*/
@CacheEvict(cacheNames = "Kudos.globalSettings", allEntries = true)
public void saveGlobalSettings(GlobalSettings settings) {
settingService.set(KUDOS_CONTEXT, KUDOS_SCOPE, SETTINGS_KEY_NAME, SettingValue.create(settings.toStringToPersist()));
this.globalSettings = null;
clearCacheClusterWide();
}

/**
Expand Down Expand Up @@ -615,44 +584,4 @@ private long getAllowedKudosPerPeriod() {
return storedGlobalSettings == null ? 0 : storedGlobalSettings.getKudosPerPeriod();
}

private GlobalSettings loadGlobalSettings() {
SettingValue<?> globalSettingsValue = settingService.get(KUDOS_CONTEXT, KUDOS_SCOPE, SETTINGS_KEY_NAME);
if (globalSettingsValue == null || StringUtils.isBlank(globalSettingsValue.getValue().toString())) {
return null;
} else {
return GlobalSettings.parseStringToObject(globalSettingsValue.getValue().toString());
}
}

private void installClusterListener() {
if (rpcService != null) {
// Clear global settings in current node
// to force reload it from store
// if another cluster node had changed
// the settings
this.reloadSettingsCommand = rpcService.registerCommand(new RemoteCommand() {
public String getId() {
return CLUSTER_GLOBAL_SETTINGS_UPDATED;
}

public Serializable execute(Serializable[] args) throws Throwable {
if (!CLUSTER_NODE_ID.equals(args[0])) {
KudosService.this.globalSettings = null;
}
return true;
}
});
}
}

private void clearCacheClusterWide() {
if (this.reloadSettingsCommand != null) {
try {
rpcService.executeCommandOnAllNodes(this.reloadSettingsCommand, false, CLUSTER_NODE_ID);
} catch (Exception e) {
LOG.warn("An error occurred while clearing global settings cache on other nodes", e);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,7 @@ public static KudosPeriod getPeriodOfTime(GlobalSettings globalSettings, LocalDa
public static KudosPeriodType getPeriodType(GlobalSettings globalSettings) {
KudosPeriodType kudosPeriodType = null;
if (globalSettings == null || globalSettings.getKudosPeriodType() == null) {
LOG.warn("Provided globalSettings doesn't have a parametred kudos period type, using MONTH period type: " + globalSettings,
new RuntimeException());
LOG.warn("Provided globalSettings doesn't have a parametred kudos period type, using MONTH period type: {}", globalSettings);
kudosPeriodType = KudosPeriodType.DEFAULT;
} else {
kudosPeriodType = globalSettings.getKudosPeriodType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
Expand Down Expand Up @@ -514,7 +513,6 @@ public void testGlobalSettings() {
GlobalSettings globalSettings = kudosService.getGlobalSettings();
assertNotNull(globalSettings);
assertNotNull(globalSettings.getKudosPeriodType());
assertTrue(StringUtils.isBlank(globalSettings.getAccessPermission()));
assertTrue(globalSettings.getKudosPerPeriod() > 0);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/
package io.meeds.test.kudos.mock;

import java.util.Collections;
import java.util.List;

import org.apache.commons.lang3.ArrayUtils;
Expand Down Expand Up @@ -70,7 +71,6 @@ public boolean canRedactOnSpace(Space space, String username) {
return space != null && redactor != null && StringUtils.equals(username, redactor);
}

@Override
public boolean canViewSpace(Space space, String username) {
return space != null && member != null && StringUtils.equals(username, member);
}
Expand All @@ -79,4 +79,13 @@ public boolean isSuperManager(String userId) {
return false;
}

public List<String> findExternalInvitationsSpacesByEmail(String email) {
return Collections.emptyList();
}

@Override
public void deleteExternalUserInvitations(String email) {
//
}

}

0 comments on commit 8ab8938

Please sign in to comment.