streams-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "ASF GitHub Bot (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (STREAMS-556) Twitter: SevenDaySearchProvider
Date Sat, 23 Dec 2017 22:31:03 GMT

    [ https://issues.apache.org/jira/browse/STREAMS-556?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16302602#comment-16302602
] 

ASF GitHub Bot commented on STREAMS-556:
----------------------------------------

steveblackmon closed pull request #411: STREAMS-556: Twitter: SevenDaySearchProvider
URL: https://github.com/apache/streams/pull/411
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/streams-contrib/streams-provider-twitter/src/main/java/org/apache/streams/twitter/api/SevenDaySearch.java
b/streams-contrib/streams-provider-twitter/src/main/java/org/apache/streams/twitter/api/SevenDaySearch.java
index 92bdf4def..696cd5317 100644
--- a/streams-contrib/streams-provider-twitter/src/main/java/org/apache/streams/twitter/api/SevenDaySearch.java
+++ b/streams-contrib/streams-provider-twitter/src/main/java/org/apache/streams/twitter/api/SevenDaySearch.java
@@ -34,12 +34,12 @@
   /**
    * Returns a collection of relevant Tweets matching a specified query.
    *
-   * @return {@link AccountSettings}
-   * @see <a href=https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-account-settings">https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-account-settings</a>
+   * @return {@link SevenDaySearchResponse}
+   * @see <a href=https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets">https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets</a>
    *
    */
   @RemoteMethod(httpMethod = "GET", path = "/tweets.json")
-  public SevenDaySearchResponse sevenDaySearch(@QueryIfNE SevenDaySearchRequest parameters);
+  public SevenDaySearchResponse sevenDaySearch(@QueryIfNE("*") SevenDaySearchRequest parameters);
 
 }
 
diff --git a/streams-contrib/streams-provider-twitter/src/main/java/org/apache/streams/twitter/provider/SevenDaySearchProvider.java
b/streams-contrib/streams-provider-twitter/src/main/java/org/apache/streams/twitter/provider/SevenDaySearchProvider.java
new file mode 100644
index 000000000..fe4fdcc57
--- /dev/null
+++ b/streams-contrib/streams-provider-twitter/src/main/java/org/apache/streams/twitter/provider/SevenDaySearchProvider.java
@@ -0,0 +1,332 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *
+ *   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.apache.streams.twitter.provider;
+
+import org.apache.streams.config.ComponentConfigurator;
+import org.apache.streams.config.StreamsConfiguration;
+import org.apache.streams.config.StreamsConfigurator;
+import org.apache.streams.core.DatumStatusCounter;
+import org.apache.streams.core.StreamsDatum;
+import org.apache.streams.core.StreamsProvider;
+import org.apache.streams.core.StreamsResultSet;
+import org.apache.streams.jackson.StreamsJacksonMapper;
+import org.apache.streams.twitter.SevenDaySearchProviderConfiguration;
+import org.apache.streams.twitter.TwitterTimelineProviderConfiguration;
+import org.apache.streams.twitter.api.SevenDaySearchRequest;
+import org.apache.streams.twitter.api.StatusesUserTimelineRequest;
+import org.apache.streams.twitter.api.Twitter;
+import org.apache.streams.twitter.converter.TwitterDateTimeFormat;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.Uninterruptibles;
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigFactory;
+import com.typesafe.config.ConfigParseOptions;
+import org.apache.commons.lang.NotImplementedException;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.io.Serializable;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Queue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Retrieve recent posts from a list of user ids or names.
+ */
+public class SevenDaySearchProvider implements StreamsProvider, Serializable {
+
+  private static final String STREAMS_ID = "SevenDaySearchProvider";
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(SevenDaySearchProvider.class);
+
+  public static final int MAX_NUMBER_WAITING = 10000;
+
+  private SevenDaySearchProviderConfiguration config;
+
+  protected final ReadWriteLock lock = new ReentrantReadWriteLock();
+
+  public SevenDaySearchProviderConfiguration getConfig() {
+    return config;
+  }
+
+  protected volatile Queue<StreamsDatum> providerQueue;
+
+  protected SevenDaySearchRequest request;
+
+  protected Twitter client;
+
+  protected ListeningExecutorService executor;
+
+  protected final AtomicBoolean running = new AtomicBoolean();
+
+  private List<ListenableFuture<Object>> futures = new ArrayList<>();
+
+  /**
+   * To use from command line:
+   *
+   * <p/>
+   * Supply (at least) the following required configuration in application.conf:
+   *
+   * <p/>
+   * twitter.oauth.consumerKey
+   * twitter.oauth.consumerSecret
+   * twitter.oauth.accessToken
+   * twitter.oauth.accessTokenSecret
+   * twitter.info
+   *
+   * <p/>
+   * Launch using:
+   *
+   * <p/>
+   * mvn exec:java -Dexec.mainClass=org.apache.streams.twitter.provider.TwitterTimelineProvider
-Dexec.args="application.conf tweets.json"
+   *
+   * @param args args
+   * @throws Exception Exception
+   */
+  public static void main(String[] args) throws Exception {
+
+    Preconditions.checkArgument(args.length >= 2);
+
+    String configfile = args[0];
+    String outfile = args[1];
+
+    Config reference = ConfigFactory.load();
+    File file = new File(configfile);
+    assert (file.exists());
+    Config testResourceConfig = ConfigFactory.parseFileAnySyntax(file, ConfigParseOptions.defaults().setAllowMissing(false));
+
+    Config typesafe  = testResourceConfig.withFallback(reference).resolve();
+
+    StreamsConfiguration streamsConfiguration = StreamsConfigurator.detectConfiguration(typesafe);
+    SevenDaySearchProviderConfiguration config = new ComponentConfigurator<>(SevenDaySearchProviderConfiguration.class).detectConfiguration(typesafe,
"twitter");
+    SevenDaySearchProvider provider = new SevenDaySearchProvider(config);
+
+    ObjectMapper mapper = new StreamsJacksonMapper(Stream.of(TwitterDateTimeFormat.TWITTER_FORMAT).collect(Collectors.toList()));
+
+    PrintStream outStream = new PrintStream(new BufferedOutputStream(new FileOutputStream(outfile)));
+    provider.prepare(config);
+    provider.startStream();
+    do {
+      Uninterruptibles.sleepUninterruptibly(streamsConfiguration.getBatchFrequencyMs(), TimeUnit.MILLISECONDS);
+      for (StreamsDatum datum : provider.readCurrent()) {
+        String json;
+        try {
+          json = mapper.writeValueAsString(datum.getDocument());
+          outStream.println(json);
+        } catch (JsonProcessingException ex) {
+          System.err.println(ex.getMessage());
+        }
+      }
+    }
+    while ( provider.isRunning() );
+    provider.cleanUp();
+    outStream.flush();
+  }
+
+  public SevenDaySearchProvider(SevenDaySearchProviderConfiguration config) {
+    this.config = config;
+  }
+
+  public Queue<StreamsDatum> getProviderQueue() {
+    return this.providerQueue;
+  }
+
+  @Override
+  public String getId() {
+    return STREAMS_ID;
+  }
+
+  @Override
+  public void prepare(Object configurationObject) {
+
+    if( !(configurationObject instanceof SevenDaySearchProviderConfiguration ) ) {
+      this.config = (SevenDaySearchProviderConfiguration)configurationObject;
+    }
+
+    try {
+      lock.writeLock().lock();
+      providerQueue = constructQueue();
+    } finally {
+      lock.writeLock().unlock();
+    }
+
+    Objects.requireNonNull(providerQueue);
+    Objects.requireNonNull(config.getOauth().getConsumerKey());
+    Objects.requireNonNull(config.getOauth().getConsumerSecret());
+    Objects.requireNonNull(config.getOauth().getAccessToken());
+    Objects.requireNonNull(config.getOauth().getAccessTokenSecret());
+    Objects.requireNonNull(config.getQ());
+    Objects.requireNonNull(config.getThreadsPerProvider());
+
+    request = new SevenDaySearchRequest();
+    request.setQ(config.getQ());
+
+    StreamsConfiguration streamsConfiguration = StreamsConfigurator.detectConfiguration();
+
+    try {
+      client = getTwitterClient();
+    } catch (InstantiationException e) {
+      LOGGER.error("InstantiationException", e);
+    }
+
+    Objects.requireNonNull(client);
+
+    executor = MoreExecutors.listeningDecorator(
+        TwitterUserInformationProvider.newFixedThreadPoolWithQueueSize(
+            config.getThreadsPerProvider().intValue(),
+            streamsConfiguration.getQueueSize().intValue()
+        )
+    );
+
+    submitSearchThread();
+
+  }
+
+  @Override
+  public void startStream() {
+
+    LOGGER.debug("{} startStream", STREAMS_ID);
+
+    running.set(true);
+
+    executor.shutdown();
+
+  }
+
+  protected void submitSearchThread() {
+
+      SevenDaySearchProviderTask providerTask = new SevenDaySearchProviderTask(
+          this,
+          client,
+        request
+      );
+      ListenableFuture future = executor.submit(providerTask);
+      futures.add(future);
+      LOGGER.info("Thread Submitted: {}", providerTask.request);
+
+  }
+
+  @Override
+  public StreamsResultSet readCurrent() {
+
+    StreamsResultSet result;
+
+    LOGGER.debug("Providing {} docs", providerQueue.size());
+
+    try {
+      lock.writeLock().lock();
+      result = new StreamsResultSet(providerQueue);
+      result.setCounter(new DatumStatusCounter());
+      providerQueue = constructQueue();
+    } finally {
+      lock.writeLock().unlock();
+    }
+
+    if ( result.size() == 0 && providerQueue.isEmpty() && executor.isTerminated()
) {
+      LOGGER.info("Finished.  Cleaning up...");
+
+      running.set(false);
+
+      LOGGER.info("Exiting");
+    }
+
+    return result;
+
+  }
+
+  protected Queue<StreamsDatum> constructQueue() {
+    return new LinkedBlockingQueue<StreamsDatum>();
+  }
+
+  public StreamsResultSet readNew(BigInteger sequence) {
+    LOGGER.debug("{} readNew", STREAMS_ID);
+    throw new NotImplementedException();
+  }
+
+  public StreamsResultSet readRange(DateTime start, DateTime end) {
+    LOGGER.debug("{} readRange", STREAMS_ID);
+    throw new NotImplementedException();
+  }
+
+  /**
+   * get Twitter Client from TwitterUserInformationConfiguration.
+   * @return result
+   */
+  public Twitter getTwitterClient() throws InstantiationException {
+
+    return Twitter.getInstance(config);
+
+  }
+
+  @Override
+  public void cleanUp() {
+    shutdownAndAwaitTermination(executor);
+  }
+
+  void shutdownAndAwaitTermination(ExecutorService pool) {
+    pool.shutdown(); // Disable new tasks from being submitted
+    try {
+      // Wait a while for existing tasks to terminate
+      if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
+        pool.shutdownNow(); // Cancel currently executing tasks
+        // Wait a while for tasks to respond to being cancelled
+        if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
+          System.err.println("Pool did not terminate");
+        }
+      }
+    } catch (InterruptedException ie) {
+      // (Re-)Cancel if current thread also interrupted
+      pool.shutdownNow();
+      // Preserve interrupt status
+      Thread.currentThread().interrupt();
+    }
+  }
+
+  @Override
+  public boolean isRunning() {
+    if (providerQueue.isEmpty() && executor.isTerminated() && Futures.allAsList(futures).isDone())
{
+      LOGGER.info("Completed");
+      running.set(false);
+      LOGGER.info("Exiting");
+    }
+    return running.get();
+  }
+}
diff --git a/streams-contrib/streams-provider-twitter/src/main/java/org/apache/streams/twitter/provider/SevenDaySearchProviderTask.java
b/streams-contrib/streams-provider-twitter/src/main/java/org/apache/streams/twitter/provider/SevenDaySearchProviderTask.java
new file mode 100644
index 000000000..8bb0b0f4d
--- /dev/null
+++ b/streams-contrib/streams-provider-twitter/src/main/java/org/apache/streams/twitter/provider/SevenDaySearchProviderTask.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *
+ *   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.apache.streams.twitter.provider;
+
+import org.apache.streams.core.StreamsDatum;
+import org.apache.streams.jackson.StreamsJacksonMapper;
+import org.apache.streams.twitter.api.SevenDaySearchRequest;
+import org.apache.streams.twitter.api.SevenDaySearchResponse;
+import org.apache.streams.twitter.api.StatusesUserTimelineRequest;
+import org.apache.streams.twitter.api.Twitter;
+import org.apache.streams.twitter.converter.TwitterDateTimeFormat;
+import org.apache.streams.twitter.pojo.Tweet;
+import org.apache.streams.util.ComponentUtils;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ *  Retrieve recent posts for a single user id.
+ */
+public class SevenDaySearchProviderTask implements Runnable {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(SevenDaySearchProviderTask.class);
+
+  private static ObjectMapper MAPPER = new StreamsJacksonMapper(Stream.of(TwitterDateTimeFormat.TWITTER_FORMAT).collect(Collectors.toList()));
+
+  protected SevenDaySearchProvider provider;
+  protected Twitter client;
+  protected SevenDaySearchRequest request;
+
+  /**
+   * SevenDaySearchProviderTask constructor.
+   * @param provider SevenDaySearchProvider
+   * @param twitter Twitter
+   * @param request SevenDaySearchRequest
+   */
+  public SevenDaySearchProviderTask(SevenDaySearchProvider provider, Twitter twitter, SevenDaySearchRequest
request) {
+    this.provider = provider;
+    this.client = twitter;
+    this.request = request;
+  }
+
+  int item_count = 0;
+  int last_count = 0;
+  int page_count = 0;
+
+  @Override
+  public void run() {
+
+    LOGGER.info("Thread Starting: {}", request.toString());
+
+    do {
+
+      SevenDaySearchResponse response = client.sevenDaySearch(request);
+
+      List<Tweet> statuses = response.getStatuses();
+
+      last_count = statuses.size();
+      if( statuses.size() > 0 ) {
+
+        for (Tweet status : statuses) {
+
+          if (item_count < provider.getConfig().getMaxItems()) {
+            ComponentUtils.offerUntilSuccess(new StreamsDatum(status), provider.providerQueue);
+            item_count++;
+          }
+
+        }
+
+        Stream<Long> statusIds = statuses.stream().map(status -> status.getId());
+        long minId = statusIds.reduce(Math::min).get();
+        page_count++;
+        request.setMaxId(new Long(minId).toString());
+
+      }
+
+    }
+    while (shouldContinuePulling(last_count, page_count, item_count));
+
+    LOGGER.info("item_count: {} last_count: {} page_count: {} ", item_count, last_count,
page_count);
+    
+  }
+
+  public boolean shouldContinuePulling(int count, int page_count, int item_count) {
+    return (
+        count > 0
+            && item_count < provider.getConfig().getMaxItems()
+            && page_count <= provider.getConfig().getMaxPages());
+  }
+
+
+
+}
diff --git a/streams-contrib/streams-provider-twitter/src/main/jsonschema/org/apache/streams/twitter/config/SevenDaySearchProviderConfiguration.json
b/streams-contrib/streams-provider-twitter/src/main/jsonschema/org/apache/streams/twitter/config/SevenDaySearchProviderConfiguration.json
new file mode 100644
index 000000000..b8b2bc196
--- /dev/null
+++ b/streams-contrib/streams-provider-twitter/src/main/jsonschema/org/apache/streams/twitter/config/SevenDaySearchProviderConfiguration.json
@@ -0,0 +1,26 @@
+{
+  "$schema": "http://json-schema.org/draft-03/schema",
+  "$license": [
+    "http://www.apache.org/licenses/LICENSE-2.0"
+  ],
+  "id": "#",
+  "type": "object",
+  "javaType" : "org.apache.streams.twitter.SevenDaySearchProviderConfiguration",
+  "extends": {"$ref":"TwitterConfiguration.json"},
+  "javaInterfaces": ["java.io.Serializable"],
+  "properties": {
+    "q": {
+      "$ref": "../api/SevenDaySearchRequest.json#properties/q"
+    },
+    "max_items": {
+      "type": "integer",
+      "description": "Max items total",
+      "default": 1000
+    },
+    "max_pages": {
+      "type": "integer",
+      "description": "Max items per page to request",
+      "default": 10
+    }
+  }
+}
\ No newline at end of file
diff --git a/streams-contrib/streams-provider-twitter/src/test/java/org/apache/streams/twitter/test/providers/TwitterSevenDaySearchProviderIT.java
b/streams-contrib/streams-provider-twitter/src/test/java/org/apache/streams/twitter/test/providers/TwitterSevenDaySearchProviderIT.java
new file mode 100644
index 000000000..954ba3ae6
--- /dev/null
+++ b/streams-contrib/streams-provider-twitter/src/test/java/org/apache/streams/twitter/test/providers/TwitterSevenDaySearchProviderIT.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *
+ *   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.apache.streams.twitter.test.providers;
+
+import org.apache.streams.twitter.provider.SevenDaySearchProvider;
+import org.apache.streams.twitter.provider.TwitterTimelineProvider;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.LineNumberReader;
+
+@Test(dependsOnGroups = {"Account"}, groups = {"Providers"})
+public class TwitterSevenDaySearchProviderIT {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(TwitterSevenDaySearchProviderIT.class);
+
+  @Test(groups = "TwitterSevenDaySearchProviderIT")
+  public void testTwitterSevenDaySearchProvider() throws Exception {
+
+    String configfile = "./target/test-classes/TwitterSevenDaySearchProviderIT.conf";
+    String outfile = "./target/test-classes/TwitterSevenDaySearchProviderIT.stdout.txt";
+
+    String[] args = new String[2];
+    args[0] = configfile;
+    args[1] = outfile;
+
+    Thread testThread = new Thread(() -> {
+      try {
+        SevenDaySearchProvider.main(args);
+      } catch ( Exception ex ) {
+        LOGGER.error("Test Exception!", ex);
+      }
+    });
+    testThread.start();
+    testThread.join(600000);
+
+    File out = new File(outfile);
+    Assert.assertTrue (out.exists());
+    Assert.assertTrue (out.canRead());
+    Assert.assertTrue (out.isFile());
+
+    FileReader outReader = new FileReader(out);
+    LineNumberReader outCounter = new LineNumberReader(outReader);
+
+    while (outCounter.readLine() != null) {}
+
+    Assert.assertEquals (outCounter.getLineNumber(), 100);
+
+  }
+}
diff --git a/streams-contrib/streams-provider-twitter/src/test/resources/TwitterSevenDaySearchProviderIT.conf
b/streams-contrib/streams-provider-twitter/src/test/resources/TwitterSevenDaySearchProviderIT.conf
new file mode 100644
index 000000000..b0117b96a
--- /dev/null
+++ b/streams-contrib/streams-provider-twitter/src/test/resources/TwitterSevenDaySearchProviderIT.conf
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+include "../../../../twitter.conf"
+twitter.max_items = 100
+twitter.max_pages = 10
+twitter.q = "data"


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


> Twitter: SevenDaySearchProvider
> -------------------------------
>
>                 Key: STREAMS-556
>                 URL: https://issues.apache.org/jira/browse/STREAMS-556
>             Project: Streams
>          Issue Type: New Feature
>            Reporter: Steve Blackmon
>            Assignee: Steve Blackmon
>   Original Estimate: 4h
>  Remaining Estimate: 4h
>
> Provider that pages through SevenDaySearch results collecting Tweets until a limit is
hit or there are no more posts.



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Mime
View raw message