PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/AzureSamples/Thumbnails_Dev11/Thumbnails_WorkerRole/WorkerRole.fs

#
F# | 153 lines | 101 code | 35 blank | 17 comment | 8 complexity | 27eeaa57138141ecd34c7d159e7cbaec MD5 | raw file
Possible License(s): BSD-3-Clause
  1. namespace Microsoft.Samples.ServiceHosting.Thumbnails
  2. open System
  3. open System.Collections.Generic
  4. open System.Configuration
  5. open System.Diagnostics
  6. open System.Drawing
  7. open System.IO
  8. open System.Text
  9. open System.Linq
  10. open System.Net
  11. open Microsoft.WindowsAzure
  12. open Microsoft.WindowsAzure.Diagnostics
  13. open Microsoft.WindowsAzure.ServiceRuntime
  14. open Microsoft.WindowsAzure.StorageClient
  15. type public WorkerRole() =
  16. inherit RoleEntryPoint()
  17. [<DefaultValue>]
  18. val mutable width : int
  19. [<DefaultValue>]
  20. val mutable height : int
  21. [<DefaultValue>]
  22. val mutable configSetter : string * bool -> unit
  23. member private this.CreateThumbnail( input : Stream ) =
  24. let orig = new Bitmap(input)
  25. if(orig.Width > orig.Height) then
  26. this.width <- 128
  27. this.height <- 128 * orig.Height / orig.Width
  28. else
  29. this.height <- 128
  30. this.width <- 128 * orig.Width / orig.Height
  31. let thumb = new Bitmap(this.width,this.height)
  32. use graphic = Graphics.FromImage(thumb)
  33. graphic.InterpolationMode <- System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
  34. graphic.SmoothingMode <- System.Drawing.Drawing2D.SmoothingMode.AntiAlias
  35. graphic.PixelOffsetMode <- System.Drawing.Drawing2D.PixelOffsetMode.HighQuality
  36. graphic.DrawImage(orig,0,0,this.width,this.height)
  37. let ms = new MemoryStream()
  38. thumb.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg)
  39. ms.Seek(0L,SeekOrigin.Begin) |> ignore
  40. ms
  41. override this.OnStart() =
  42. // This code sets up a handler to update CloudStorageAccount instances when their corresponding
  43. // configuration settings change in the service configuration file.
  44. CloudStorageAccount.SetConfigurationSettingPublisher(
  45. new Action<string,Func<string,bool>>(
  46. fun (configName:string) (configSetter:Func<string,bool>) ->
  47. // Provide the configSetter with the initial value
  48. configSetter.Invoke(RoleEnvironment.GetConfigurationSettingValue(configName)) |> ignore
  49. RoleEnvironment.Changed.Add(fun (arg : RoleEnvironmentChangedEventArgs) ->
  50. if (arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange>().Any(fun change -> change.ConfigurationSettingName = configName)) then
  51. if (not (configSetter.Invoke(RoleEnvironment.GetConfigurationSettingValue(configName)))) then
  52. // In this case, the change to the storage account credentials in the
  53. // service configuration is significant enough that the role needs to be
  54. // recycled in order to use the latest settings. (for example, the
  55. // endpoint has changed)
  56. RoleEnvironment.RequestRecycle()
  57. )
  58. ))
  59. base.OnStart()
  60. override this.Run() =
  61. let storageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("DataConnectionString"))
  62. let blobStorage = storageAccount.CreateCloudBlobClient()
  63. let container = blobStorage.GetContainerReference("photogallery")
  64. let queueStorage = storageAccount.CreateCloudQueueClient()
  65. let queue = queueStorage.GetQueueReference("thumbnailmaker")
  66. Trace.TraceInformation("Creating container and queue...")
  67. // If the Start() method throws an exception, the role recycles.
  68. // If this sample is run locally and the development storage tool has not been started, this
  69. // can cause a number of exceptions to be thrown because roles are restarted repeatedly.
  70. // Lets try to create the queue and the container and check whether the storage services are running
  71. // at all.
  72. let mutable containerAndQueueCreated = false
  73. while(not containerAndQueueCreated) do
  74. try
  75. container.CreateIfNotExist() |> ignore
  76. let mutable permissions = container.GetPermissions()
  77. permissions.PublicAccess <- BlobContainerPublicAccessType.Container
  78. container.SetPermissions(permissions)
  79. permissions <- container.GetPermissions()
  80. queue.CreateIfNotExist() |> ignore
  81. containerAndQueueCreated <- true
  82. with
  83. | :? StorageClientException as e ->
  84. if (e.ErrorCode = StorageErrorCode.TransportError) then
  85. Trace.TraceError(String.Format("Connect failure! The most likely reason is that the local "+
  86. "Development Storage tool is not running or your storage account configuration is incorrect. "+
  87. "Message: '{0}'", e.Message))
  88. System.Threading.Thread.Sleep(5000);
  89. else
  90. raise e
  91. Trace.TraceInformation("Listening for queue messages...")
  92. // Now that the queue and the container have been created in the above initialization process, get messages
  93. // from the queue and process them individually.
  94. while (true) do
  95. try
  96. let msg = queue.GetMessage()
  97. if (box(msg) <> null) then
  98. let path = msg.AsString
  99. let thumbnailName = System.IO.Path.GetFileNameWithoutExtension(path) + ".jpg"
  100. Trace.TraceInformation(String.Format("Dequeued '{0}'", path))
  101. let content = container.GetBlockBlobReference(path)
  102. let thumbnail = container.GetBlockBlobReference("thumbnails/" + thumbnailName)
  103. let image = new MemoryStream()
  104. content.DownloadToStream(image)
  105. image.Seek(0L, SeekOrigin.Begin) |> ignore
  106. thumbnail.Properties.ContentType <- "image/jpeg"
  107. thumbnail.UploadFromStream(this.CreateThumbnail(image))
  108. Trace.TraceInformation(String.Format("Done with '{0}'", path))
  109. queue.DeleteMessage(msg)
  110. else
  111. System.Threading.Thread.Sleep(1000)
  112. // Explicitly catch all exceptions of type StorageException here because we should be able to
  113. // recover from these exceptions next time the queue message, which caused this exception,
  114. // becomes visible again.
  115. with
  116. | _ as e ->
  117. System.Threading.Thread.Sleep(5000)
  118. Trace.TraceError(String.Format("Exception when processing queue item. Message: '{0}'", e.Message))