public async Task<IHttpActionResult> GetPhotoModel(string id)
        {
            var cache = RedisCache.Connection.GetDatabase();
            var repo = new RedisRepository(cache);

            //Get a single item from the cache based on its ID
            var photo = await repo.GetPhotoByIDAsync(id);

            if (null == photo)
            {
                //Not in the cache.  Retrieve from storage.
                string connectionString = SettingsHelper.LocalStorageConnectionString;
                string owner = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
                var storageRepo = new StorageRepository(connectionString);
                photo = await storageRepo.GetPhotoFromTableAsync( DAL.Azure.StorageConfig.PhotosBlobContainerName, owner, id);
                if (null == photo)
                {
                    //Not found in cache or storage.                      
                }
                else
                {                    
                    //Update the cache using the cache aside pattern.
                    await repo.AddPhotoToUserCacheAsync(photo);
                }
            }
            if (null != photo)
            {
                return Ok(photo);
            }
            else
            {
                return NotFound();
            }
        }
示例#2
0
        internal static async Task CreateThumbnailAsync(StorageRepository repo, string fileName, TextWriter log)
        {
            using (var memStream = await repo.GetBlob(StorageConfig.PhotosBlobContainerName, fileName))
            {
                MemoryStream thumbnail = null;
                try
                {
                    thumbnail = PhotoEditor.ProcessImage(memStream);
                    await repo.UploadBlobAsync(thumbnail, StorageConfig.ThumbnailsBlobContainerName, fileName);
                }
                catch (Exception oops)
                {
                    await log.WriteAsync(oops.Message);
                    throw oops;
                }
                finally
                {
                    if (null != thumbnail)
                    {
                        thumbnail.Dispose();
                    }
                }

            }
        }
        public async Task<IHttpActionResult> Get()
        {
            var cache = RedisCache.Connection.GetDatabase();
            var repo = new RedisRepository(cache);

            string owner = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;

            var items = await repo.GetPhotosForUserAsync(owner);
            //Do this so we can get the count
            List<IPhotoModel> typedItems = new List<IPhotoModel>(items);
            
            if(typedItems.Count == 0)
            {
                //Nothing in cache... head off to storage.
                var storageRepo = new StorageRepository(SettingsHelper.LocalStorageConnectionString);
                
                var photos = await storageRepo.GetPhotosFromTableAsync( DAL.Azure.StorageConfig.TableName, owner);
                foreach (var photo in photos)
                {
                    //TODO: Find a MUCH better algorithm than
                    //      iterating every item and calling
                    //      Redis 3 times in a row for each
                    //      item.  This is PAINFUL.
                    await repo.AddPhotoToCachesAsync(photo);
                }
                items = photos;                
            }
            return Ok(items);
        }
示例#4
0
        internal static async Task ReplicateBlobAsync(PhotoModel model, TextWriter log)
        {
            //The source connection string needs to be in AppSettings using the
            //storage account name.
            var sourceConnectionString = ConfigurationManager.AppSettings[model.StorageAccountName];

            //The target connection string is the local region's storage account
            var targetConnectionString = SettingsHelper.LocalStorageConnectionString;

            //Copy from the upload container to the photos container,
            //    potentially across storage accounts
            await log.WriteLineAsync("sourceConnectionString: " + sourceConnectionString);
            await log.WriteLineAsync("targetConnectionString: " + targetConnectionString);

            var storageRepo = new StorageRepository(sourceConnectionString);
            var container = await storageRepo.ReplicateBlobAsync(
                targetConnectionString,
                StorageConfig.UserUploadBlobContainerName,
                StorageConfig.PhotosBlobContainerName,
                model.ServerFileName, log);

            //Monitor the copy operation and wait for it to finish
            //before proceeding
            await storageRepo.MonitorCopy(container, model.ServerFileName, log);
        }
        public async Task<IHttpActionResult> Get()
        {
            var cache = RedisCache.Connection.GetDatabase();
            var repo = new RedisRepository(cache);
            var items = await repo.GetAllPhotosAsync();
            
            List<IPhotoModel> typedItems = new List<IPhotoModel>(items);
            if(typedItems.Count == 0)
            {
                //Pull from storage.  This is a cross-partition query,
                //  and will be slower than using Redis.
                var storageConnectionString = SettingsHelper.LocalStorageConnectionString;
                var storageRepo = new StorageRepository(storageConnectionString);
                typedItems = await storageRepo.GetLatestFromTableStorageAsync();
                if(typedItems.Count > 0)
                {
                    foreach (var item in typedItems)
                    {
                        //Add to cache as cache-aside pattern
                        await repo.AddPhotoToAllUsersCacheAsync(item);
                    }
                    items = typedItems;
                }
            }


            return Ok(items);
        }
示例#6
0
        internal static async Task SaveToTableStorageAsync(PhotoModel p, TextWriter log)
        {
            var storageConnectionString = SettingsHelper.LocalStorageConnectionString;
            var repo = new StorageRepository(storageConnectionString);
            var result = await repo.SaveToTableStorageAsync(DAL.Azure.StorageConfig.TableName, p);

            await log.WriteLineAsync("Save to table HTTP result: " + result);
        }
示例#7
0
        // This function will get triggered/executed when a new message is written 
        // on an Azure Queue called queue.
        public static async Task ProcessQueueMessage(
            [QueueTrigger("uploadqueue")] string message,
            TextWriter log)
        {
            log.WriteLineAsync(message).Wait();

            var m = message.Split(',');
            await log.WriteAsync("Message received: " + m);

            var model = new PhotoModel
            {
                ID = m[0],
                ServerFileName = m[1],
                StorageAccountName = m[2],
                Owner = m[3],
                OwnerName = m[4],
                BlobURL = m[5],
                OriginRegion = m[6]
            };

            //Copy blob from source to destination
            await log.WriteAsync("Replicating blob...");
            await Helpers.ReplicateBlobAsync(model, log);

            try
            {


                //Change the blob URL to point to the new location!    
                await log.WriteAsync("Getting blob URIs");
                string storageConnectionString = SettingsHelper.LocalStorageConnectionString;
                var repo = new StorageRepository(storageConnectionString);
                model.BlobURL = repo.GetBlobURI(model.ServerFileName, StorageConfig.PhotosBlobContainerName).ToString();
                model.ThumbnailURL = repo.GetBlobURI(model.ServerFileName, StorageConfig.ThumbnailsBlobContainerName).ToString();

                //Create thumbnail
                await log.WriteAsync("Creating thumbnail");
                await Helpers.CreateThumbnailAsync(repo, model.ServerFileName, log);

                //Store in table storage
                await log.WriteAsync("Saving to table storage");
                await Helpers.SaveToTableStorageAsync(model, log);

                //Add to Redis cache
                await log.WriteAsync("Saving to Redis");
                await Helpers.SaveToRedisAsync(model, log);
            }
            catch (Exception oops)
            {
                await log.WriteLineAsync(oops.Message);
            }
        }
示例#8
0
        public static async Task ProcessBroadcastQueue(
            [QueueTrigger("broadcastqueue")] string message,
            TextWriter log)
        {
            //Send a queue message to each storage account registered
            //in AppSettings prefixed with "Storage"

            foreach (string key in ConfigurationManager.AppSettings.Keys)
            {
                if (key.ToLower().StartsWith("storage"))
                {
                    //This is a storage configuration  
                    var repo = new StorageRepository(ConfigurationManager.AppSettings[key]);
                    await repo.SendQueueMessageAsync(message);
                }
            }
        }
        public IHttpActionResult Get(string extension)
        {
            Regex rg = new Regex(@"^[a-zA-Z0-9]{1,3}$");
            if(!rg.IsMatch(extension))
            {
                throw new HttpResponseException(System.Net.HttpStatusCode.BadRequest);
            }

            string connectionString = SettingsHelper.LocalStorageConnectionString;
            var account = CloudStorageAccount.Parse(connectionString);
            StorageRepository repo = new StorageRepository(account);

            //Get the SAS token for the container.  Allow writes for 2 minutes
            var sasToken = repo.GetBlobContainerSASToken();

            //Get the blob so we can get the full path including container name
            var id = Guid.NewGuid().ToString();
            var newFileName = id + "." + extension;

            string blobURL = repo.GetBlobURI(
                newFileName, 
                DAL.Azure.StorageConfig.UserUploadBlobContainerName).ToString();


            //This function determines which storage account the blob will be
            //uploaded to, enabling the future possibility of sharding across 
            //multiple storage accounts.
            var client = account.CreateCloudBlobClient();

            var response = new StorageResponse
            {
                ID = id,
                StorageAccountName = client.BaseUri.Authority.Split('.')[0],
                BlobURL = blobURL,                
                BlobSASToken = sasToken,
                ServerFileName = newFileName
            };

            return Ok(response);
        }
示例#10
0
        /// <summary>
        /// Notify the backend that a new file was uploaded
        /// by sending a queue message.
        /// </summary>
        /// <param name="value">The name of the blob to be processed</param>
        /// <returns>Void</returns>
        public async Task Post(CompleteRequest item)
        {
            string owner = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
            //Get the owner name field
            string ownerName = ClaimsPrincipal.Current.FindFirst("name").Value;
            //Replace any commas with periods
            ownerName = ownerName.Replace(',', '.');

            string message = string.Format(
                "{0},{1},{2},{3}, {4}, {5}, {6}", 
                item.ID, 
                item.ServerFileName, 
                item.StorageAccountName, 
                owner, 
                ownerName, 
                item.BlobURL, 
                SettingsHelper.CurrentRegion);

            //Send a queue message to the local storage account 
            //The local web job will pick it up and broadcast to 
            //all storage accounts in appSettings prefixed with "Storage"

            var repo = new StorageRepository(SettingsHelper.LocalStorageConnectionString);
            await repo.SendBroadcastQueueMessageAsync(message);
                        
        }