public static HttpResponseMessage Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "analyze/{blogname}")] HttpRequestMessage req, string blogname, TraceWriter log) { Startup.Init(); PostsTableAdapter postsTableAdapter = new PostsTableAdapter(); postsTableAdapter.Init(log); PhotoToAnalyzeQueueAdapter photoToAnalyzeQueueAdapter = new PhotoToAnalyzeQueueAdapter(); photoToAnalyzeQueueAdapter.Init(); string blobBaseUrl = ConfigurationManager.AppSettings["BlobBaseUrl"]; List <PostEntity> posts = postsTableAdapter.GetAll(blogname); log.Info($"Loaded {posts.Count} posts"); int messageCount = 0; foreach (PostEntity postEntity in posts) { if (string.IsNullOrEmpty(postEntity.PhotoBlobUrls)) { continue; } List <Photo> sitePhotos = JsonConvert.DeserializeObject <List <Photo> >(postEntity.PhotoBlobUrls); foreach (Photo photo in sitePhotos) { List <PhotoSize> sortedSizes = photo.Sizes.OrderByDescending(x => x.Nominal).ToList(); PhotoSize original = sortedSizes.FirstOrDefault(); if (original == null) { continue; } string url = blobBaseUrl + "/" + original.Container + "/" + photo.Name + "_" + original.Nominal + "." + photo.Extension; PhotoToAnalyze message = new PhotoToAnalyze { Blog = blogname, PostDate = postEntity.Date, Url = url }; photoToAnalyzeQueueAdapter.Send(message); log.Info($"Published PhotoToAnalyze message with URL {url}"); messageCount++; } } return(req.CreateResponse(HttpStatusCode.OK, $"Processed {posts.Count} posts, sent {messageCount} messages")); }
public static HttpResponseMessage Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "analyzerandomphotos")] HttpRequestMessage req, TraceWriter log) { Startup.Init(); PostsTableAdapter postsTableAdapter = new PostsTableAdapter(); postsTableAdapter.Init(log); ImageAnalysisTableAdapter imageAnalysisTableAdapter = new ImageAnalysisTableAdapter(); imageAnalysisTableAdapter.Init(); PhotoToAnalyzeQueueAdapter photoToAnalyzeQueueAdapter = new PhotoToAnalyzeQueueAdapter(); photoToAnalyzeQueueAdapter.Init(); string blobBaseUrl = ConfigurationManager.AppSettings["BlobBaseUrl"]; int blogsLimit = 50; int photosInBlogLimit = 10; BlogInfoTableAdapter blogInfoTableAdapter = new BlogInfoTableAdapter(); blogInfoTableAdapter.Init(); List <BlogStats> blogStats = blogInfoTableAdapter.GetBlogStats(); log.Info($"Got {blogStats.Count} blogs to index"); Random random = new Random(); blogStats.Shuffle(random); blogStats = blogStats.Take(blogsLimit).ToList(); int totalCount = 0; foreach (string blogname in blogStats.Select(x => x.RowKey)) { int analyzedInBlogCount = 0; List <PostEntity> noteCounts = postsTableAdapter.GetPostNoteCounts(blogname).OrderByDescending(x => x.NoteCount).ToList(); log.Info($"Got note counts for {noteCounts.Count} posts in blog {blogname}"); foreach (PostEntity noteCountPost in noteCounts) { PostEntity postEntity = postsTableAdapter.GetPost(blogname, noteCountPost.RowKey); if (postEntity == null) { log.Warning($"Post {blogname}/{noteCountPost.RowKey} not found, skipping"); continue; } if (string.IsNullOrEmpty(postEntity.PhotoBlobUrls)) { continue; } List <Photo> sitePhotos = JsonConvert.DeserializeObject <List <Photo> >(postEntity.PhotoBlobUrls); foreach (Photo photo in sitePhotos) { List <PhotoSize> sortedSizes = photo.Sizes.OrderByDescending(x => x.Nominal).ToList(); PhotoSize original = sortedSizes.FirstOrDefault(); if (original == null) { continue; } string url = blobBaseUrl + "/" + original.Container + "/" + photo.Name + "_" + original.Nominal + "." + photo.Extension; if (imageAnalysisTableAdapter.GetImageAnalysis(url) != null) { log.Info($"Image {url} already analyzed"); continue; } PhotoToAnalyze message = new PhotoToAnalyze { Blog = blogname, PostDate = postEntity.Date, Url = url }; photoToAnalyzeQueueAdapter.Send(message); log.Info($"Published PhotoToAnalyze message with URL {url}"); analyzedInBlogCount++; totalCount++; } if (analyzedInBlogCount >= photosInBlogLimit) { break; } } } return(req.CreateResponse(HttpStatusCode.OK, $"Will analyze {totalCount} new photos")); }
public static HttpResponseMessage Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "analyze-from-likes/{blogname}")] HttpRequestMessage req, string blogname, TraceWriter log) { Startup.Init(); LikeIndexTableAdapter likeIndexTableAdapter = new LikeIndexTableAdapter(); likeIndexTableAdapter.Init(); PostsTableAdapter postsTableAdapter = new PostsTableAdapter(); postsTableAdapter.Init(log); ImageAnalysisTableAdapter imageAnalysisTableAdapter = new ImageAnalysisTableAdapter(); imageAnalysisTableAdapter.Init(); PhotoToAnalyzeQueueAdapter photoToAnalyzeQueueAdapter = new PhotoToAnalyzeQueueAdapter(); photoToAnalyzeQueueAdapter.Init(); string blobBaseUrl = ConfigurationManager.AppSettings["BlobBaseUrl"]; string afterParam = req.GetQueryNameValuePairs().FirstOrDefault(q => q.Key.Equals("after", StringComparison.OrdinalIgnoreCase)).Value; List <LikeIndexEntity> likes; if (!string.IsNullOrEmpty(afterParam) && long.TryParse(afterParam, out long afterTimestamp)) { log.Info($"Getting likes newer than timestamp {afterTimestamp}"); likes = likeIndexTableAdapter.GetNewerThan(blogname, afterTimestamp); } else { likes = likeIndexTableAdapter.GetAll(blogname); } log.Info($"Loaded {likes.Count} posts"); int messageCount = 0; foreach (LikeIndexEntity like in likes) { if (like.LikedBlogName == null || like.LikedPostId == null) { continue; } PostEntity postEntity = postsTableAdapter.GetPost(like.LikedBlogName, like.LikedPostId); if (postEntity == null) { log.Warning($"Post {like.LikedBlogName}/{like.LikedPostId} not found, skipping"); continue; } if (string.IsNullOrEmpty(postEntity.PhotoBlobUrls)) { continue; } List <Photo> sitePhotos = JsonConvert.DeserializeObject <List <Photo> >(postEntity.PhotoBlobUrls); foreach (Photo photo in sitePhotos) { List <PhotoSize> sortedSizes = photo.Sizes.OrderByDescending(x => x.Nominal).ToList(); PhotoSize original = sortedSizes.FirstOrDefault(); if (original == null) { continue; } string url = blobBaseUrl + "/" + original.Container + "/" + photo.Name + "_" + original.Nominal + "." + photo.Extension; if (imageAnalysisTableAdapter.GetImageAnalysis(url) != null) { log.Info($"Image {url} already analyzed"); continue; } PhotoToAnalyze message = new PhotoToAnalyze { Blog = blogname, PostDate = postEntity.Date, Url = url }; photoToAnalyzeQueueAdapter.Send(message); log.Info($"Published PhotoToAnalyze message with URL {url}"); messageCount++; } } return(req.CreateResponse(HttpStatusCode.OK, $"Processed {likes.Count} posts, sent {messageCount} messages")); }
public static async Task Run([TimerTrigger("0 15 * * * *")] TimerInfo myTimer, TraceWriter log) { Startup.Init(); PhotoToAnalyzeQueueAdapter photoToAnalyzeQueueAdapter = new PhotoToAnalyzeQueueAdapter(); photoToAnalyzeQueueAdapter.Init(); CloudQueueMessage message = null; PhotoToAnalyze photoToAnalyze = null; try { ImageAnalysisTableAdapter imageAnalysisTableAdapter = new ImageAnalysisTableAdapter(); imageAnalysisTableAdapter.Init(); BlogInfoTableAdapter blogInfoTableAdapter = new BlogInfoTableAdapter(); blogInfoTableAdapter.Init(); int processedCount = 0; do { message = await photoToAnalyzeQueueAdapter.GetNextMessage(); if (message == null) { return; } photoToAnalyze = JsonConvert.DeserializeObject <PhotoToAnalyze>(message.AsString); if (imageAnalysisTableAdapter.GetImageAnalysis(photoToAnalyze.Url) != null) { log.Info($"Image {photoToAnalyze.Url} already analyzed, aborting"); await UpdateBlogInfo(photoToAnalyze, blogInfoTableAdapter); continue; } string failure = await ImageAnalyzer.AnalyzePhoto(log, photoToAnalyze, imageAnalysisTableAdapter); if (string.IsNullOrEmpty(failure)) { await UpdateBlogInfo(photoToAnalyze, blogInfoTableAdapter); } else { photoToAnalyze.Error = failure; await photoToAnalyzeQueueAdapter.SendToPoisonQueue(photoToAnalyze); log.Info($"Message for {photoToAnalyze.Url} stored to poison queue"); } processedCount++; await photoToAnalyzeQueueAdapter.DeleteMessage(message); } while (processedCount < 10); } catch (Exception ex) { log.Error("Error in ProcessPhotosToAnalyze: " + ex.Message, ex); if (message != null && photoToAnalyze != null) { photoToAnalyze.Error = ex.Message; photoToAnalyze.StackTrace = ex.StackTrace.Substring(0, Math.Max(36000, ex.StackTrace.Length)); await photoToAnalyzeQueueAdapter.SendToPoisonQueue(photoToAnalyze); log.Info($"Message for {photoToAnalyze.Url} stored to poison queue"); await photoToAnalyzeQueueAdapter.DeleteMessage(message); log.Info($"Failed message deleted successfully from main queue"); message = null; } } }