Skip to content

Commit

Permalink
Got a backup job working! Now on to Async Completion management
Browse files Browse the repository at this point in the history
  • Loading branch information
analogrelay committed Nov 26, 2013
1 parent 3a720ed commit 8ce9577
Show file tree
Hide file tree
Showing 28 changed files with 636 additions and 67 deletions.
35 changes: 35 additions & 0 deletions src/NuGetGallery.Backend/BackendConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
Expand Down Expand Up @@ -102,6 +103,40 @@ public static BackendConfiguration CreateAzure()
key => RoleEnvironment.GetConfigurationSettingValue(key));
}

public SqlConnectionStringBuilder GetSqlServer(KnownSqlServer server)
{
switch (server)
{
case KnownSqlServer.Primary:
return PrimaryDatabase;
case KnownSqlServer.Warehouse:
return WarehouseDatabase;
default:
throw new InvalidOperationException(String.Format(
CultureInfo.CurrentCulture,
Strings.BackendConfiguration_UnknownSqlServer,
server.ToString()));
}
}

public CloudStorageAccount GetStorageAccount(KnownStorageAccount account)
{
switch (account)
{
case KnownStorageAccount.Primary:
return PrimaryStorage;
case KnownStorageAccount.Backup:
return BackupStorage;
case KnownStorageAccount.Diagnostics:
return DiagnosticsStorage;
default:
throw new InvalidOperationException(String.Format(
CultureInfo.CurrentCulture,
Strings.BackendConfiguration_UnknownStorageAccount,
account.ToString()));
}
}

private static CloudStorageAccount TryGetStorageAccount(string name)
{
string val = RoleEnvironment.GetConfigurationSettingValue(name);
Expand Down
21 changes: 21 additions & 0 deletions src/NuGetGallery.Backend/Helpers/DapperExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dapper
{
public static class DapperExtensions
{
public static Task ExecuteAsync(this SqlConnection connection, string sql)
{
SqlCommand cmd = connection.CreateCommand();
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
return cmd.ExecuteNonQueryAsync();
}
}
}
21 changes: 21 additions & 0 deletions src/NuGetGallery.Backend/Helpers/DateTimeOffsetExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace System
{
public static class DateTimeOffsetExtensions
{
public static bool IsOlderThan(this DateTimeOffset self, TimeSpan age)
{
return (DateTimeOffset.UtcNow - self) > age;
}

public static bool IsYoungerThan(this DateTimeOffset self, TimeSpan age)
{
return (DateTimeOffset.UtcNow - self) < age;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace System.Data.SqlClient
{
public static class SqlConnectionStringBuilderExtensions
{
public static SqlConnectionStringBuilder ChangeDatabase(this SqlConnectionStringBuilder self, string newDatabaseName)
{
return new SqlConnectionStringBuilder(self.ConnectionString)
{
InitialCatalog = newDatabaseName
};
}

public static Task<SqlConnection> ConnectTo(this SqlConnectionStringBuilder self)
{
return ConnectTo(self.ConnectionString);
}

public static Task<SqlConnection> ConnectToMaster(this SqlConnectionStringBuilder self)
{
return ConnectTo(self, "master");
}

public static Task<SqlConnection> ConnectTo(this SqlConnectionStringBuilder self, string databaseName)
{
var newConnectionString = new SqlConnectionStringBuilder(self.ConnectionString)
{
InitialCatalog = databaseName
};
return ConnectTo(newConnectionString.ConnectionString);
}

private static async Task<SqlConnection> ConnectTo(string connection)
{
var c = new SqlConnection(connection);
await c.OpenAsync().ConfigureAwait(continueOnCapturedContext: false);
return c;
}
}
}
53 changes: 44 additions & 9 deletions src/NuGetGallery.Backend/Infrastructure/Job.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
using System.Threading.Tasks;
using NuGetGallery.Backend.Monitoring;
using NuGetGallery.Jobs;
using System.Diagnostics;
using System.Data.SqlClient;

namespace NuGetGallery.Backend
{
Expand All @@ -17,9 +19,11 @@ public abstract class Job
private static readonly Regex NameExtractor = new Regex(@"^(?<shortname>.*)Job$");

public virtual string Name { get; private set; }
public JobInvocation Invocation { get; protected set; }
public BackendConfiguration Config { get; protected set; }
public JobInvocationContext Context { get; protected set; }

public JobInvocation Invocation { get { return Context.Invocation; } }
public BackendConfiguration Config { get { return Context.Config; } }

protected Job()
{
Name = InferName();
Expand All @@ -31,15 +35,14 @@ protected Job(string name)
Name = name;
}

public virtual async Task<JobResult> Invoke(JobInvocation invocation, BackendConfiguration config)
public virtual async Task<JobResult> Invoke(JobInvocationContext context)
{
// Bind invocation information
Invocation = invocation;
Config = config;
BindProperties(invocation.Request.Parameters);
Context = context;
BindProperties(Invocation.Request.Parameters);

// Invoke the job
WorkerEventSource.Log.JobStarted(invocation.Request.Name, invocation.Id);
WorkerEventSource.Log.JobStarted(Invocation.Request.Name, Invocation.Id);
JobResult result;
try
{
Expand All @@ -53,11 +56,11 @@ public virtual async Task<JobResult> Invoke(JobInvocation invocation, BackendCon

if (result.Status != JobStatus.Faulted)
{
WorkerEventSource.Log.JobCompleted(invocation.Request.Name, invocation.Id);
WorkerEventSource.Log.JobCompleted(Invocation.Request.Name, Invocation.Id);
}
else
{
WorkerEventSource.Log.JobFaulted(invocation.Request.Name, result.Exception, invocation.Id);
WorkerEventSource.Log.JobFaulted(Invocation.Request.Name, result.Exception, Invocation.Id);
}

// Return the result
Expand Down Expand Up @@ -93,8 +96,17 @@ protected virtual void BindProperty(PropertyDescriptor prop, string value)
prop.SetValue(this, convertedValue);
}

private IList<TypeConverter> _converters = new List<TypeConverter>() {
new SqlConnectionStringBuilderConverter()
};

protected virtual object ConvertPropertyValue(PropertyDescriptor prop, string value)
{
var converter = _converters.FirstOrDefault(c => c.CanConvertFrom(typeof(string)) && c.CanConvertTo(prop.PropertyType));
if (converter != null)
{
return converter.ConvertFromString(value);
}
return prop.Converter.ConvertFromString(value);
}

Expand All @@ -108,5 +120,28 @@ private string InferName()
}
return name;
}

private class SqlConnectionStringBuilderConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}

public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(SqlConnectionStringBuilder);
}

public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
string strVal = value as string;
if (strVal == null)
{
return null;
}
return new SqlConnectionStringBuilder(strVal);
}
}
}
}
3 changes: 2 additions & 1 deletion src/NuGetGallery.Backend/Infrastructure/JobDispatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@ public virtual async Task<JobResponse> Dispatch(JobInvocation invocation)

WorkerEventSource.Log.DispatchingRequest(invocation);
JobResult result = null;
var context = new JobInvocationContext(invocation, Config, _monitor);
try
{
result = await job.Invoke(invocation, Config);
result = await job.Invoke(context);
}
catch (Exception ex)
{
Expand Down
23 changes: 23 additions & 0 deletions src/NuGetGallery.Backend/Infrastructure/JobInvocationContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NuGetGallery.Backend.Monitoring;
using NuGetGallery.Jobs;

namespace NuGetGallery.Backend
{
public class JobInvocationContext
{
public JobInvocation Invocation { get; private set; }
public BackendConfiguration Config { get; private set; }
public BackendMonitoringHub Monitor { get; private set; }

public JobInvocationContext(JobInvocation invocation, BackendConfiguration config, BackendMonitoringHub monitor)
{
Invocation = invocation;
Config = config;
Monitor = monitor;
}
}
}
Loading

0 comments on commit 8ce9577

Please sign in to comment.