Skip to content

Instantly share code, notes, and snippets.

@codingoutloud
Created February 13, 2013 20:02
Show Gist options
  • Save codingoutloud/4947695 to your computer and use it in GitHub Desktop.
Save codingoutloud/4947695 to your computer and use it in GitHub Desktop.
Use Windows Azure Blob to create a semaphore spanning the cloud.
// intended to be called only ONCE in real installations - or for a clean test run when no Jobs container exists
public static void GloballyInitializeJobManager(bool quiet)
{
var blobContainer = AzureStorageAccess.GetBlobContainer(JobContainerName);
bool didNotExistCreated = blobContainer.CreateIfNotExist();
if (!quiet) System.Diagnostics.Debug.Assert(didNotExistCreated); // else, we probably should not be calling this method
var blob = blobContainer.GetBlobReference(JobGlobalJobIdSequencePath);
if (!blob.Exists())
{
blob.UploadText(JobGlobalJobIdSequenceStartingValue);
blob.Properties.ContentType = "text/plain";
blob.SetProperties();
}
}
public static string GetUniqueJobId()
{
// Nod to http://blog.smarx.com/posts/leasing-windows-azure-blobs-using-the-storage-client-library
var blobContainer = AzureStorageAccess.GetBlobContainer(JobContainerName);
bool didNotExistCreated = blobContainer.CreateIfNotExist();
var blob = blobContainer.GetBlobReference(JobGlobalJobIdSequencePath);
if (!blob.Exists())
{
blob.UploadText(JobGlobalJobIdSequenceStartingValue);
}
// TODO: ??? needs to handle case where it cannot initially Acquire Lease due to resource contention
string leaseId = null;
int retryCount = 0;
var random = new Random((int)DateTime.Now.Ticks);
var timeBeforeRetries = DateTime.UtcNow;
while (leaseId == null && retryCount < 100 && (DateTime.UtcNow < timeBeforeRetries.AddMinutes(2)))
{
try
{
leaseId = blob.AcquireLease(); // lease is for 60 seconds and is renewable
}
catch (System.Net.WebException wex)
{
retryCount++;
int sleepMilliseconds = random.Next(50, 1000);
System.Threading.Thread.Sleep(sleepMilliseconds);
System.Diagnostics.Trace.WriteLine(String.Format(
"About to attempt retry {0} after sleeping {1} ms [exception status: {2}; exception message: {3}]",
retryCount, sleepMilliseconds, wex.Status, wex.Message));
}
}
try { var leaseId2 = blob.AcquireLease(); }
catch { }
var blobContent = blob.DownloadText();
// increment string to next one
long jobId = Convert.ToInt64(blobContent);
jobId++;
string jobIdString = jobId.ToString();
blob.UploadText(jobIdString, leaseId); // extension method
// that writing new data to the blob turns this to application/octet-stream:
blob.Properties.ContentType = "text/plain";
blob.SetProperties(); // TODO: extension for passing leaseid
blob.ReleaseLease(leaseId);
return jobIdString;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment