public static async Task <TweetProcessingData> ProcessTweet( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { TweetProcessingData tpd = context.GetInput <TweetProcessingData>(); if (!context.IsReplaying) { log.LogInformation("P_ProcessTweet call A_GetBusinessLogicScore"); } // The following function is not async, so it could be called directly rather than through the activity model. PublishLabel tmpLabelBL = PublishLabel.NotAssigned; (tpd.Score, tmpLabelBL, tpd.TextWithoutTagsHighlighted) = await context.CallActivityAsync <Tuple <double, PublishLabel, string> >("A_GetBusinessLogicScore", tpd.TextWithoutTags); tpd.LabelBL = (int)tmpLabelBL; if (tpd.LabelBL != (int)PublishLabel.Negative) { log.LogInformation("Minimum BL score exceeded, query ML filter."); var mlResult = await context.CallActivityAsync <MlResult>("A_GetMlScore", tpd.TextWithoutTags); tpd.ScoreML = mlResult.Score; tpd.LabelML = (int)mlResult.Label; tpd.VersionML = mlResult.MlVersion; if (!(tpd.VersionML is null)) { log.LogInformation( $"ML-inference OK, label: {tpd.LabelML}, " + $"score: {tpd.ScoreML.ToString("F", CultureInfo.InvariantCulture)}, " + $"version: {tpd.VersionML}"); } else { // Did not get a reply from the ML function, therefore // we fall back and continue according to the traditional // logic's result; indicated by tpd.VersionML is null. log.LogInformation("ML inference failed or did not reply, rely on conventional logic."); } }
public static async Task <List <TweetProcessingData> > GetTweets([ActivityTrigger] string lastTweetId, ILogger log) { log.LogInformation($"A_GetTweets: Getting new tweets after {lastTweetId}."); KeyVaultAccessor kva = KeyVaultAccessor.GetInstance(); string apiKey = await kva.GetSecretAsync("TwitterApiKey"); // aka consumer key string apiSecretKey = await kva.GetSecretAsync("TwitterApiSecretKey"); // aka consumer secret string accessToken = await kva.GetSecretAsync("TwitterAccessToken"); string accessTokenSecret = await kva.GetSecretAsync("TwitterAccessTokenSecret"); string monitoredTwitterAccount = Environment.GetEnvironmentVariable("MonitoredTwitterAccount"); List <TweetProcessingData> tpds = new List <TweetProcessingData>(); // return value, empty list if Twitter connection failure var userCredentials = Auth.SetUserCredentials(apiKey, apiSecretKey, accessToken, accessTokenSecret); try { // This variable is not used later, but seems to leave an id for the library. var authenticatedUser = User.GetAuthenticatedUser(userCredentials); } catch (AggregateException ae) { // Inserted try-catch after a seemingly intermittent exception that lead to // the service stopping completely, 20210102, ca. 11 am. log.LogWarning($"A_GetTweets: User authentication failure: {ae.Message}. Return no tweets and retry in next cycle."); return(tpds); } // Note: The following does NOT get MaximumNumberOfResults tweets // from after lastTweetId!!! Rather it gets the most recent // tweets with the early limit defined by lastTweetId OR the // defined maximum, whichever is more limiting! // (Therefore, in order to test on past tweets, one may need // to increase MaximumNumberOfResults considerably to get ALL // tweets from the one targeted to the current one. SearchTweetsParameters searchParameter = new SearchTweetsParameters($"from:{monitoredTwitterAccount}") { MaximumNumberOfResults = 15, SinceId = long.Parse(lastTweetId) }; IEnumerable <ITweet> tweets = null; try { tweets = await SearchAsync.SearchTweets(searchParameter); } catch (Exception e) { // Inserted try-catch after a seemingly intermittent exception that lead to // the service stopping completely, 20201213, ca. 7 am. log.LogWarning($"A_GetTweets: SearchTweets failed with exception: {e.Message}"); } if (tweets is null) { log.LogWarning($"A_GetTweets: Twitter connection failure. Return no tweets and retry in next cycle."); return(tpds); } // Since the further processing can scramble the order again, we don't need to sort here. foreach (var tweet in tweets) { // Copy the data that we need over to a serializable struct. TweetProcessingData tpd = new TweetProcessingData(); tpd.IdStr = tweet.IdStr; tpd.CreatedAt = tweet.CreatedAt; tpd.FullText = tweet.FullText; tpd.Hashtags = String.Join("|", tweet.Hashtags.Select(t => t.Text)); tpd.InReplyToStatusIdStr = tweet.InReplyToStatusIdStr; tpd.Url = tweet.Url; tpd.TextWithoutTags = TweetAnalysis.removeHashtagsFromText(tweet.FullText, tweet.Hashtags); tpds.Add(tpd); } log.LogInformation($"A_GetTweets: Done, got {tweets.Count()} new tweets."); return(tpds); }