Skip to content

Instantly share code, notes, and snippets.

@AaronLenoir
Created May 3, 2016 21:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AaronLenoir/4ce5480ecea580d5d283c5d08e8e71b5 to your computer and use it in GitHub Desktop.
Save AaronLenoir/4ce5480ecea580d5d283c5d08e8e71b5 to your computer and use it in GitHub Desktop.
using Akka.Actor;
using System;
using System.IO;
using System.Net;
namespace Akka.DownloadActor
{
/// <summary>
/// Downloads a file from a given Uri.
/// </summary>
/// <remarks>Multiple download requests will be handled sequentially.</remarks>
public class FileDownloadActor : ReceiveActor, IWithUnboundedStash
{
#region State
private WebClient _client;
private Guid _guid;
private Uri _uri;
private string _tempPath;
private IActorRef _self;
private IActorRef _downloadRequestor;
public IStash Stash { get; set; }
#endregion
public FileDownloadActor()
{
_client = new WebClient();
_client.DownloadProgressChanged += Client_DownloadProgressChanged;
_client.DownloadFileCompleted += Client_DownloadFileCompleted;
Become(Ready);
}
#region messages
public class StartDownload
{
public Guid Guid { get; }
public Uri Uri { get; }
public StartDownload(Guid guid, Uri uri)
{ Guid = guid; Uri = uri; }
}
public class DownloadProgressed
{
public Guid Guid { get; }
public double ProgressPercentage { get; }
public DownloadProgressed(Guid guid, double progressPercentage)
{
Guid = guid;
ProgressPercentage = progressPercentage;
}
}
public class DownloadCompleted
{
public Guid Guid { get; }
public string Path { get; }
protected DownloadCompleted(Guid guid, string path)
{
Guid = guid;
Path = path;
}
}
private class DownloadCompletedInternal : DownloadCompleted
{
public DownloadCompletedInternal(Guid guid, string path) : base(guid, path) { }
}
#endregion
#region States
public void Ready()
{
Receive<StartDownload>(message => {
HandleStartDownload(message);
Become(Downloading);
});
}
public void Downloading()
{
Receive<StartDownload>(message => {
Stash.Stash();
});
Receive<DownloadCompleted>(message => {
Become(Ready);
Stash.UnstashAll();
});
}
#endregion
public void HandleStartDownload(StartDownload message)
{
_self = Self;
_downloadRequestor = Sender;
_uri = message.Uri;
_guid = message.Guid;
_tempPath = Path.GetTempFileName();
_client.DownloadFileAsync(_uri, _tempPath);
}
private void Client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
var completedMessage = new DownloadCompletedInternal(_guid, _tempPath);
_downloadRequestor.Tell(completedMessage);
_self.Tell(completedMessage);
}
private void Client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
var progressedMessage = new DownloadProgressed(_guid, e.ProgressPercentage);
_downloadRequestor.Tell(progressedMessage);
_self.Tell(progressedMessage);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment