/**
* JBoss, Home of Professional Open Source
* Copyright Red Hat, Inc., and individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.aerogear.simplepush.server.netty;
import io.netty.channel.Channel;
import org.jboss.aerogear.io.netty.handler.codec.sockjs.SockJsSessionContext;
import java.util.Iterator;
import org.jboss.aerogear.simplepush.server.SimplePushServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Performs the removal of inactive UserAgents.
*/
public class UserAgentReaper implements Runnable {
private final Logger logger = LoggerFactory.getLogger(UserAgentReaper.class);
private final SimplePushServer simplePushServer;
private final UserAgents userAgents = UserAgents.getInstance();
/**
* Sole constructor.
*
* @param simplePushServer the {@link SimplePushServer} that this reaper will operate on.
*/
public UserAgentReaper(final SimplePushServer simplePushServer) {
this.simplePushServer = simplePushServer;
}
@Override
public void run() {
logger.info("Running reaper at interval of " + simplePushServer.config().userAgentReaperTimeout());
for (Iterator<UserAgent<SockJsSessionContext>> it = userAgents.all().iterator(); it.hasNext();) {
final UserAgent<SockJsSessionContext> userAgent = it.next();
final long now = System.currentTimeMillis();
if (isChannelInactive(userAgent) && userAgent.timestamp() + simplePushServer.config().userAgentReaperTimeout() < now) {
logger.info("Removing inactive UserAgent [" + userAgent.uaid() + "]");
/* TODO: update this when persistence is in place so that the logic to remove is in one place
and not spread out among the UserAgents class and the SimplePushServer.
*/
// remove from user agents map
it.remove();
// remove from database
simplePushServer.removeAllChannels(userAgent.uaid());
// close the user agent connectContext
userAgent.context().close();
}
}
}
private boolean isChannelInactive(final UserAgent<SockJsSessionContext> userAgent) {
final Channel ch = userAgent.context().getContext().channel();
return !ch.isActive() && !ch.isRegistered();
}
}