Skip to content

Commit

Permalink
Development: Improve boundary cases with Hazelcast (#9387)
Browse files Browse the repository at this point in the history
  • Loading branch information
krusche authored Oct 20, 2024
1 parent 96e53d4 commit f3a48ad
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Profile;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
Expand All @@ -40,6 +41,7 @@
import com.hazelcast.collection.ItemEvent;
import com.hazelcast.collection.ItemListener;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.HazelcastInstanceNotActiveException;
import com.hazelcast.map.IMap;
import com.hazelcast.topic.ITopic;

Expand Down Expand Up @@ -130,7 +132,7 @@ public SharedQueueProcessingService(@Qualifier("hazelcastInstance") HazelcastIns
/**
* Initialize relevant data from hazelcast
*/
@PostConstruct
@EventListener(ApplicationReadyEvent.class)
public void init() {
this.buildAgentInformation = this.hazelcastInstance.getMap("buildAgentInformation");
this.processingJobs = this.hazelcastInstance.getMap("processingJobs");
Expand Down Expand Up @@ -172,7 +174,15 @@ public void removeListenerAndCancelScheduledFuture() {
}

private void removeListener() {
this.queue.removeItemListener(this.listenerId);
// check if Hazelcast is still active, before invoking this
try {
if (hazelcastInstance != null && hazelcastInstance.getLifecycleService().isRunning()) {
this.queue.removeItemListener(this.listenerId);
}
}
catch (HazelcastInstanceNotActiveException e) {
log.error("Failed to remove listener from SharedQueueProcessingService as Hazelcast instance is not active any more.");
}
}

private void cancelCheckAvailabilityAndProcessNextBuildScheduledFuture() {
Expand Down Expand Up @@ -205,7 +215,7 @@ public void updateBuildAgentInformation() {
* If so, process the next build job.
*/
private void checkAvailabilityAndProcessNextBuild() {
if (noDataMemberInClusterAvailable(hazelcastInstance)) {
if (noDataMemberInClusterAvailable(hazelcastInstance) || queue == null) {
log.debug("There are only lite member in the cluster. Not processing build jobs.");
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jakarta.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Profile;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.handler.annotation.DestinationVariable;
Expand All @@ -31,6 +30,7 @@
import org.springframework.web.socket.messaging.SessionUnsubscribeEvent;

import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.HazelcastInstanceNotActiveException;

import de.tum.cit.aet.artemis.communication.service.WebsocketMessagingService;
import de.tum.cit.aet.artemis.core.domain.User;
Expand Down Expand Up @@ -96,7 +96,7 @@ public ParticipationTeamWebsocketService(WebsocketMessagingService websocketMess
/**
* Initialize relevant data from hazelcast
*/
@PostConstruct
@EventListener(ApplicationReadyEvent.class)
public void init() {
// participationId-username -> timestamp
this.lastTypingTracker = hazelcastInstance.getMap("lastTypingTracker");
Expand Down Expand Up @@ -307,11 +307,19 @@ public void handleDisconnect(SessionDisconnectEvent event) {
* @param sessionId id of the sessions which is unsubscribing
*/
public void unsubscribe(String sessionId) {
Optional.ofNullable(destinationTracker.get(sessionId)).ifPresent(destination -> {
Long participationId = getParticipationIdFromDestination(destination);
sendOnlineTeamStudents(participationId, sessionId);
destinationTracker.remove(sessionId);
});
// check if Hazelcast is still active, before invoking this
try {
if (hazelcastInstance != null && hazelcastInstance.getLifecycleService().isRunning()) {
Optional.ofNullable(destinationTracker.get(sessionId)).ifPresent(destination -> {
destinationTracker.remove(sessionId);
Long participationId = getParticipationIdFromDestination(destination);
sendOnlineTeamStudents(participationId, sessionId);
});
}
}
catch (HazelcastInstanceNotActiveException e) {
log.error("Failed to unsubscribe as Hazelcast is no longer active");
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@
import java.util.UUID;
import java.util.concurrent.CancellationException;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Profile;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import com.hazelcast.collection.IQueue;
import com.hazelcast.collection.ItemEvent;
import com.hazelcast.collection.ItemListener;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.HazelcastInstanceNotActiveException;
import com.hazelcast.map.IMap;

import de.tum.cit.aet.artemis.assessment.domain.Result;
Expand Down Expand Up @@ -90,16 +92,28 @@ public LocalCIResultProcessingService(@Qualifier("hazelcastInstance") HazelcastI
/**
* Initializes the result queue, build agent information map and the locks.
*/
@PostConstruct
@EventListener(ApplicationReadyEvent.class)
public void init() {
this.resultQueue = this.hazelcastInstance.getQueue("buildResultQueue");
this.buildAgentInformation = this.hazelcastInstance.getMap("buildAgentInformation");
this.listenerId = resultQueue.addItemListener(new ResultQueueListener(), true);
}

/**
* Removes the item listener from the Hazelcast result queue if the instance is active.
* Logs an error if Hazelcast is not running.
*/
@PreDestroy
public void removeListener() {
this.resultQueue.removeItemListener(this.listenerId);
// check if Hazelcast is still active, before invoking this
try {
if (hazelcastInstance != null && hazelcastInstance.getLifecycleService().isRunning()) {
this.resultQueue.removeItemListener(this.listenerId);
}
}
catch (HazelcastInstanceNotActiveException e) {
log.error("Could not remove listener as hazelcast instance is not active.");
}
}

/**
Expand Down

0 comments on commit f3a48ad

Please sign in to comment.