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

Development: Improve boundary cases with Hazelcast #9387

Merged
merged 11 commits into from
Oct 20, 2024
Merged
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.");
}
SimonEntholzer marked this conversation as resolved.
Show resolved Hide resolved
}

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");
}
SimonEntholzer marked this conversation as resolved.
Show resolved Hide resolved
}

/**
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.");
}
SimonEntholzer marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
Loading