AbstractTwitterMessageSource no longer implements Lifecycle (no longer extends AbstractEndpoint). @Ignore-d irrelevant tests, and removed the RateLimitStatusTrigger.

This commit is contained in:
Mark Fisher
2010-11-18 19:44:48 -05:00
parent 5265dad85d
commit 382e074f59
9 changed files with 62 additions and 233 deletions

View File

@@ -48,7 +48,6 @@ public class TwitterInboundChannelAdapterParser extends AbstractPollingInboundCh
BASE_PACKAGE + ".core.Twitter4jTemplate");
builder.addConstructorArgValue(templateBuilder.getBeanDefinition());
}
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "query");
return builder.getBeanDefinition();
}

View File

@@ -21,14 +21,13 @@ import java.util.Comparator;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledFuture;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.integration.Message;
import org.springframework.integration.MessagingException;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.context.IntegrationObjectSupport;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.endpoint.AbstractEndpoint;
import org.springframework.integration.store.MetadataStore;
import org.springframework.integration.store.SimpleMetadataStore;
import org.springframework.integration.support.MessageBuilder;
@@ -51,11 +50,11 @@ import org.springframework.util.StringUtils;
* @since 2.0
*/
@SuppressWarnings("rawtypes")
abstract class AbstractTwitterMessageSource<T> extends AbstractEndpoint implements MessageSource {
abstract class AbstractTwitterMessageSource<T> extends IntegrationObjectSupport implements MessageSource {
private volatile long lastPollForTweet;
private final TwitterPollingTask twitterPoller = new TwitterPollingTask();
private final TwitterPollingTask twitterPollingTask = new TwitterPollingTask();
private volatile MetadataStore metadataStore;
@@ -73,8 +72,6 @@ abstract class AbstractTwitterMessageSource<T> extends AbstractEndpoint implemen
private final TweetComparator tweetComparator = new TweetComparator();
private volatile ScheduledFuture<?> twitterPollingTask;
private final Object markerGuard = new Object();
@@ -91,8 +88,6 @@ abstract class AbstractTwitterMessageSource<T> extends AbstractEndpoint implemen
@Override
protected void onInit() throws Exception{
super.onInit();
Assert.notNull(this.getTaskScheduler(),
"Unable to locate TaskScheduler. You must inject one explicitly or define a bean by the name 'taskScheduler'.");
if (this.metadataStore == null) {
// first try to look for a 'metadataStore' in the context
BeanFactory beanFactory = this.getBeanFactory();
@@ -128,18 +123,17 @@ abstract class AbstractTwitterMessageSource<T> extends AbstractEndpoint implemen
public Message<?> receive() {
Tweet tweet = this.tweets.poll();
if (tweet == null){
if (tweet == null) {
long currentTime = System.currentTimeMillis();
long diff = currentTime - lastPollForTweet;
if (diff < 15000){
long elapsedTime = currentTime - this.lastPollForTweet;
if (elapsedTime < 15000) {
// need to wait longer
return null;
}
twitterPoller.run();
this.twitterPollingTask.run();
tweet = this.tweets.poll();
lastPollForTweet = currentTime;
this.lastPollForTweet = currentTime;
}
if (tweet != null) {
this.lastProcessedId = tweet.getId();
this.metadataStore.put(this.metadataKey, String.valueOf(this.lastProcessedId));
@@ -173,24 +167,6 @@ abstract class AbstractTwitterMessageSource<T> extends AbstractEndpoint implemen
protected abstract List<Tweet> pollForTweets(long sinceId);
// Lifecycle methods
@Override
protected void doStart() {
// temporarily injecting Twitter into a trigger so it can deal with Rate Limits.
// This will likely change once we switch to Spring Social.
RateLimitStatusTrigger trigger = new RateLimitStatusTrigger(this.twitterOperations.getUnderlyingTwitter());
this.twitterPollingTask = this.getTaskScheduler().schedule(new TwitterPollingTask(), trigger);
}
@Override
protected void doStop() {
if (this.twitterPollingTask != null) {
this.twitterPollingTask.cancel(true);
}
}
private class TwitterPollingTask implements Runnable {
public void run() {

View File

@@ -1,85 +0,0 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* 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.springframework.integration.twitter.inbound;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.scheduling.SchedulingException;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.util.Assert;
import twitter4j.RateLimitStatus;
import twitter4j.Twitter;
import twitter4j.TwitterException;
/**
* Trigger implementation that takes the Twitter rate limit into consideration.
*
* @author Oleg Zhurakousky
* @since 2.0
*/
class RateLimitStatusTrigger implements Trigger {
private final Log logger = LogFactory.getLog(getClass());
private final Twitter twitter;
public RateLimitStatusTrigger(Twitter twitter) {
Assert.notNull(twitter, "'twitter' must not be null");
this.twitter = twitter;
}
/**
* Returns the next time the task may execute. Considers the Twitter rate limit.
*/
public Date nextExecutionTime(TriggerContext triggerContext) {
if (triggerContext.lastCompletionTime() == null) {
return new Date();
}
try {
RateLimitStatus rateLimitStatus = this.twitter.getRateLimitStatus();
int secondsUntilReset = rateLimitStatus.getSecondsUntilReset();
int remainingHits = rateLimitStatus.getRemainingHits();
if (remainingHits == 0) {
if (logger.isDebugEnabled()) {
logger.debug("rate status limit service returned 0 for the remaining hits value");
}
return null;
}
if (secondsUntilReset == 0) {
if (logger.isDebugEnabled()) {
logger.debug("rate status limit service returned 0 for the seconds until reset period value");
}
return null;
}
int secondsUntilWeCanPullAgain = secondsUntilReset / remainingHits;
long msUntilWeCanPullAgain = secondsUntilWeCanPullAgain * 1000;
logger.debug("Waiting for " + secondsUntilWeCanPullAgain
+ " seconds until the next timeline pull. Have " + remainingHits
+ " remaining pull this rate period. The period ends in " + secondsUntilReset);
return new Date(System.currentTimeMillis() + msUntilWeCanPullAgain);
}
catch (TwitterException e) {
throw new SchedulingException("Failed to schedule the next Twitter update", e);
}
}
}