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

feat: Change Kudos Clustering Mechanism with Cache - MEED-7742 - Meeds-io/meeds#2537 #554

Merged
merged 1 commit into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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) {
//
}

}