Long-Polling is now more robust and requires less CPU resources.
This commit is contained in:
@@ -90,15 +90,6 @@ public class ChatRequestHandler extends LotroServerRequestHandler implements Uri
|
||||
_responseWriter = responseWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChanged() {
|
||||
try {
|
||||
return _chatRoom.getChatRoomListener(_playerId).hasMessages();
|
||||
} catch (SubscriptionExpiredException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean wasProcessed() {
|
||||
return _processed;
|
||||
|
||||
@@ -112,19 +112,6 @@ public class GameRequestHandler extends LotroServerRequestHandler implements Uri
|
||||
_responseWriter = responseWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChanged() {
|
||||
try {
|
||||
return _gameMediator.getCommunicationChannel(_resourceOwner, _channelNumber).hasGameEvents();
|
||||
} catch (PrivateInformationException e) {
|
||||
return true;
|
||||
} catch (SubscriptionExpiredException e) {
|
||||
return true;
|
||||
} catch (SubscriptionConflictException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean wasProcessed() {
|
||||
return _processed;
|
||||
|
||||
@@ -465,17 +465,6 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri
|
||||
_responseWriter = responseWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChanged() {
|
||||
try {
|
||||
return _hallServer.getCommunicationChannel(_resourceOwner, _channelNumber).hasChangesInCommunicationChannel();
|
||||
} catch (SubscriptionExpiredException e) {
|
||||
return true;
|
||||
} catch (SubscriptionConflictException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean wasProcessed() {
|
||||
return _processed;
|
||||
|
||||
@@ -11,6 +11,7 @@ var GempLotrHallUI = Class.extend({
|
||||
buttonsDiv:null,
|
||||
|
||||
pocketDiv:null,
|
||||
pocketValue:null,
|
||||
hallChannelId: null,
|
||||
|
||||
init:function (div, url, chat) {
|
||||
@@ -422,8 +423,11 @@ var GempLotrHallUI = Class.extend({
|
||||
if (root.tagName == "hall") {
|
||||
this.hallChannelId = root.getAttribute("channelNumber");
|
||||
|
||||
var currency = root.getAttribute("currency");
|
||||
this.pocketDiv.html(formatPrice(currency));
|
||||
var currency = parseInt(root.getAttribute("currency"));
|
||||
if (currency != this.pocketValue) {
|
||||
this.pocketValue = currency;
|
||||
this.pocketDiv.html(formatPrice(currency));
|
||||
}
|
||||
|
||||
var motd = root.getAttribute("motd");
|
||||
if (motd != null)
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
package com.gempukku.polling;
|
||||
|
||||
public interface LongPollableResource {
|
||||
public void registerForChanges(LongPollingResource longPollingResource);
|
||||
/**
|
||||
* Registers the request for changes, however if there are any changes that can be consumed immediatelly, then
|
||||
* true is returned.
|
||||
* @param waitingRequest
|
||||
* @return
|
||||
*/
|
||||
public boolean registerRequest(WaitingRequest waitingRequest);
|
||||
|
||||
public void deregisterResource(LongPollingResource longPollingResource);
|
||||
public void deregisterRequest(WaitingRequest waitingRequest);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.gempukku.polling;
|
||||
|
||||
public interface LongPollingResource {
|
||||
public boolean isChanged();
|
||||
|
||||
public boolean wasProcessed();
|
||||
|
||||
public void processIfNotProcessed();
|
||||
|
||||
@@ -2,33 +2,40 @@ package com.gempukku.polling;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class LongPollingSystem {
|
||||
private static Logger _log = Logger.getLogger(LongPollingSystem.class);
|
||||
|
||||
private ConcurrentLinkedQueue<TimeoutResource> _waitingActions = new ConcurrentLinkedQueue<TimeoutResource>();
|
||||
private final Set<ResourceWaitingRequest> _waitingActions = Collections.synchronizedSet(new HashSet<ResourceWaitingRequest>());
|
||||
|
||||
private long _pollingInterval = 1000;
|
||||
private long _pollingLength = 10000;
|
||||
private ProcessingRunnable _processingRunnable;
|
||||
|
||||
private ProcessingRunnable _timeoutRunnable;
|
||||
private ExecutorService _executorService = Executors.newCachedThreadPool();
|
||||
|
||||
public LongPollingSystem() {
|
||||
}
|
||||
|
||||
public void start() {
|
||||
_processingRunnable = new ProcessingRunnable();
|
||||
Thread thr = new Thread(_processingRunnable);
|
||||
_timeoutRunnable = new ProcessingRunnable();
|
||||
Thread thr = new Thread(_timeoutRunnable);
|
||||
thr.start();
|
||||
}
|
||||
|
||||
public void processLongPollingResource(LongPollingResource resource, LongPollableResource pollableResource) {
|
||||
if (resource.isChanged())
|
||||
resource.processIfNotProcessed();
|
||||
else
|
||||
pollableResource.registerForChanges(resource);
|
||||
|
||||
_waitingActions.add(new TimeoutResource(resource, pollableResource, System.currentTimeMillis()));
|
||||
ResourceWaitingRequest request = new ResourceWaitingRequest(pollableResource, resource, System.currentTimeMillis());
|
||||
if (pollableResource.registerRequest(request)) {
|
||||
execute(resource);
|
||||
} else {
|
||||
_waitingActions.add(request);
|
||||
}
|
||||
}
|
||||
|
||||
private void pause() {
|
||||
@@ -39,21 +46,38 @@ public class LongPollingSystem {
|
||||
}
|
||||
}
|
||||
|
||||
private void processWaitingRequest(final ResourceWaitingRequest request) {
|
||||
_waitingActions.remove(request);
|
||||
execute(request.getLongPollingResource());
|
||||
}
|
||||
|
||||
private void execute(final LongPollingResource resource) {
|
||||
_executorService.submit(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
resource.processIfNotProcessed();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class ProcessingRunnable implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
long now = System.currentTimeMillis();
|
||||
Iterator<TimeoutResource> iterator = _waitingActions.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
TimeoutResource resource = iterator.next();
|
||||
if (resource.getLongPollingResource().wasProcessed())
|
||||
iterator.remove();
|
||||
else {
|
||||
if (resource.getStart() + _pollingLength < now) {
|
||||
resource.getLongPollableResource().deregisterResource(resource.getLongPollingResource());
|
||||
resource.getLongPollingResource().processIfNotProcessed();
|
||||
synchronized (_waitingActions) {
|
||||
long now = System.currentTimeMillis();
|
||||
Iterator<ResourceWaitingRequest> iterator = _waitingActions.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
ResourceWaitingRequest waitingRequest = iterator.next();
|
||||
if (waitingRequest.getLongPollingResource().wasProcessed())
|
||||
iterator.remove();
|
||||
else {
|
||||
if (waitingRequest.getStart() + _pollingLength < now) {
|
||||
waitingRequest.getLongPollableResource().deregisterRequest(waitingRequest);
|
||||
iterator.remove();
|
||||
execute(waitingRequest.getLongPollingResource());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,17 +86,22 @@ public class LongPollingSystem {
|
||||
}
|
||||
}
|
||||
|
||||
private class TimeoutResource {
|
||||
private long _start;
|
||||
private LongPollableResource _longPollableResource;
|
||||
private class ResourceWaitingRequest implements WaitingRequest {
|
||||
private LongPollingResource _longPollingResource;
|
||||
private LongPollableResource _longPollableResource;
|
||||
private long _start;
|
||||
|
||||
private TimeoutResource(LongPollingResource longPollingResource, LongPollableResource longPollableResource, long start) {
|
||||
_longPollingResource = longPollingResource;
|
||||
private ResourceWaitingRequest(LongPollableResource longPollableResource, LongPollingResource longPollingResource, long start) {
|
||||
_longPollableResource = longPollableResource;
|
||||
_longPollingResource = longPollingResource;
|
||||
_start = start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processRequest() {
|
||||
processWaitingRequest(this);
|
||||
}
|
||||
|
||||
public LongPollableResource getLongPollableResource() {
|
||||
return _longPollableResource;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.gempukku.polling;
|
||||
|
||||
public interface WaitingRequest {
|
||||
public void processRequest();
|
||||
}
|
||||
@@ -3,21 +3,20 @@ package com.gempukku.lotro.game.state;
|
||||
import com.gempukku.lotro.common.Token;
|
||||
import com.gempukku.lotro.communication.GameStateListener;
|
||||
import com.gempukku.lotro.game.PhysicalCard;
|
||||
import static com.gempukku.lotro.game.state.GameEvent.Type.*;
|
||||
import com.gempukku.lotro.logic.decisions.AwaitingDecision;
|
||||
import com.gempukku.lotro.logic.timing.GameStats;
|
||||
import com.gempukku.polling.LongPollableResource;
|
||||
import com.gempukku.polling.LongPollingResource;
|
||||
import com.gempukku.polling.WaitingRequest;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.gempukku.lotro.game.state.GameEvent.Type.*;
|
||||
|
||||
public class GameCommunicationChannel implements GameStateListener, LongPollableResource {
|
||||
private List<GameEvent> _events = new LinkedList<GameEvent>();
|
||||
private String _self;
|
||||
private long _lastConsumed = System.currentTimeMillis();
|
||||
private int _channelNumber;
|
||||
private LongPollingResource _longPollingResource;
|
||||
private WaitingRequest _waitingRequest;
|
||||
|
||||
public GameCommunicationChannel(String self, int channelNumber) {
|
||||
_self = self;
|
||||
@@ -37,19 +36,23 @@ public class GameCommunicationChannel implements GameStateListener, LongPollable
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void deregisterResource(LongPollingResource longPollingResource) {
|
||||
_longPollingResource = null;
|
||||
public synchronized void deregisterRequest(WaitingRequest waitingRequest) {
|
||||
_waitingRequest = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void registerForChanges(LongPollingResource longPollingResource) {
|
||||
_longPollingResource = longPollingResource;
|
||||
public synchronized boolean registerRequest(WaitingRequest waitingRequest) {
|
||||
if (_events.size()>0)
|
||||
return true;
|
||||
|
||||
_waitingRequest = waitingRequest;
|
||||
return false;
|
||||
}
|
||||
|
||||
private synchronized void appendEvent(GameEvent event) {
|
||||
_events.add(event);
|
||||
if (_longPollingResource != null)
|
||||
_longPollingResource.processIfNotProcessed();
|
||||
if (_waitingRequest != null)
|
||||
_waitingRequest.processRequest();
|
||||
}
|
||||
|
||||
private int[] getCardIds(Collection<PhysicalCard> cards) {
|
||||
|
||||
@@ -2,14 +2,15 @@ package com.gempukku.lotro.draft;
|
||||
|
||||
import com.gempukku.lotro.game.CardCollection;
|
||||
import com.gempukku.polling.LongPollableResource;
|
||||
import com.gempukku.polling.LongPollingResource;
|
||||
import com.gempukku.polling.WaitingRequest;
|
||||
|
||||
public class DraftCommunicationChannel implements LongPollableResource {
|
||||
private int _channelNumber;
|
||||
private long _lastAccessed;
|
||||
|
||||
private boolean _changed;
|
||||
private String _cardChoiceOnClient;
|
||||
private LongPollingResource _longPollingResource;
|
||||
private WaitingRequest _waitingRequest;
|
||||
|
||||
public DraftCommunicationChannel(int channelNumber) {
|
||||
_channelNumber = channelNumber;
|
||||
@@ -28,18 +29,23 @@ public class DraftCommunicationChannel implements LongPollableResource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deregisterResource(LongPollingResource longPollingResource) {
|
||||
_longPollingResource = null;
|
||||
public synchronized void deregisterRequest(WaitingRequest waitingRequest) {
|
||||
_waitingRequest = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerForChanges(LongPollingResource longPollingResource) {
|
||||
_longPollingResource = longPollingResource;
|
||||
public boolean registerRequest(WaitingRequest waitingRequest) {
|
||||
if (_changed)
|
||||
return true;
|
||||
|
||||
_waitingRequest = waitingRequest;
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized void draftChanged() {
|
||||
if (_longPollingResource != null)
|
||||
_longPollingResource.processIfNotProcessed();
|
||||
_changed = true;
|
||||
if (_waitingRequest != null)
|
||||
_waitingRequest.processRequest();
|
||||
}
|
||||
|
||||
public boolean hasChangesInCommunicationChannel(DraftCardChoice draftCardChoice) {
|
||||
@@ -59,7 +65,7 @@ public class DraftCommunicationChannel implements LongPollableResource {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void processCommunicationChannel(DraftCardChoice draftCardChoice, CardCollection chosenCards, DraftChannelVisitor draftChannelVisitor) {
|
||||
public synchronized void processCommunicationChannel(DraftCardChoice draftCardChoice, CardCollection chosenCards, DraftChannelVisitor draftChannelVisitor) {
|
||||
updateLastAccess();
|
||||
|
||||
CardCollection cardCollection = draftCardChoice.getCardCollection();
|
||||
@@ -72,5 +78,7 @@ public class DraftCommunicationChannel implements LongPollableResource {
|
||||
_cardChoiceOnClient = null;
|
||||
}
|
||||
draftChannelVisitor.chosenCards(chosenCards);
|
||||
|
||||
_changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.gempukku.lotro.game;
|
||||
import com.gempukku.lotro.chat.ChatMessage;
|
||||
import com.gempukku.lotro.chat.ChatRoomListener;
|
||||
import com.gempukku.polling.LongPollableResource;
|
||||
import com.gempukku.polling.LongPollingResource;
|
||||
import com.gempukku.polling.WaitingRequest;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -11,23 +11,27 @@ import java.util.List;
|
||||
public class ChatCommunicationChannel implements ChatRoomListener, LongPollableResource {
|
||||
private List<ChatMessage> _messages = new LinkedList<ChatMessage>();
|
||||
private long _lastConsumed = System.currentTimeMillis();
|
||||
private LongPollingResource _longPollingResource;
|
||||
private WaitingRequest _waitingRequest;
|
||||
|
||||
@Override
|
||||
public synchronized void deregisterResource(LongPollingResource longPollingResource) {
|
||||
_longPollingResource = null;
|
||||
public synchronized void deregisterRequest(WaitingRequest waitingRequest) {
|
||||
_waitingRequest = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void registerForChanges(LongPollingResource longPollingResource) {
|
||||
_longPollingResource = longPollingResource;
|
||||
public synchronized boolean registerRequest(WaitingRequest waitingRequest) {
|
||||
if (_messages.size()>0)
|
||||
return true;
|
||||
|
||||
_waitingRequest = waitingRequest;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void messageReceived(ChatMessage message) {
|
||||
_messages.add(message);
|
||||
if (_longPollingResource != null)
|
||||
_longPollingResource.processIfNotProcessed();
|
||||
if (_waitingRequest != null)
|
||||
_waitingRequest.processRequest();
|
||||
}
|
||||
|
||||
public synchronized List<ChatMessage> consumeMessages() {
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.gempukku.lotro.hall;
|
||||
|
||||
import com.gempukku.lotro.game.Player;
|
||||
import com.gempukku.polling.LongPollableResource;
|
||||
import com.gempukku.polling.LongPollingResource;
|
||||
import com.gempukku.polling.WaitingRequest;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.mutable.MutableObject;
|
||||
|
||||
@@ -17,26 +17,30 @@ public class HallCommunicationChannel implements LongPollableResource {
|
||||
private Map<String, Map<String, String>> _tablePropsOnClient = new LinkedHashMap<String, Map<String, String>>();
|
||||
private Set<String> _playedGames = new HashSet<String>();
|
||||
private boolean _changed;
|
||||
private LongPollingResource _longPollingResource;
|
||||
private WaitingRequest _waitingRequest;
|
||||
|
||||
public HallCommunicationChannel(int channelNumber) {
|
||||
_channelNumber = channelNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void deregisterResource(LongPollingResource longPollingResource) {
|
||||
_longPollingResource = null;
|
||||
public synchronized void deregisterRequest(WaitingRequest waitingRequest) {
|
||||
_waitingRequest = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void registerForChanges(LongPollingResource longPollingResource) {
|
||||
_longPollingResource = longPollingResource;
|
||||
public boolean registerRequest(WaitingRequest waitingRequest) {
|
||||
if (_changed)
|
||||
return true;
|
||||
|
||||
_waitingRequest = waitingRequest;
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized void hallChanged() {
|
||||
_changed = true;
|
||||
if (_longPollingResource != null)
|
||||
_longPollingResource.processIfNotProcessed();
|
||||
if (_waitingRequest != null)
|
||||
_waitingRequest.processRequest();
|
||||
}
|
||||
|
||||
public int getChannelNumber() {
|
||||
|
||||
Reference in New Issue
Block a user