views:

193

answers:

3

We have an application running as a Windows service on a production server. The application is partitioned into several assemblies mostly on deployment boundaries. I would like to streamline the deployment of hot-fixes to application assemblies. Currently I do the following steps to deploy a hot fix. (we have a duplicate of the production environment for staging, so everything has to be done twice)

  1. Login to server
  2. Stop the service
  3. Backup currently deployed dll
  4. Replace with hotfix (Copy hotfix over existing dll)
  5. Restart service
  6. Roll back in case of unexpected load errors (has not happened, yet)

I think that what I would like is to upload (SFTP) a dll to a preset folder and have the application pick up the new dll.

One solution I've considered is to have a separate service running on the server. Let's call it a hotfix deployment service. It would watch the file system for new files and do steps 2-6 from the list above.

Any insight is appreciated. I'm open to other alternatives as well as long as they reduce the deployment friction.

+1  A: 

i would take a look at Castle Windsor as a good option for "hot plugging" assemblies.

It's an advanced and well supported IoC/DI framework that helps with many of the tasks you mention, except for actually moving the files onto the target machine. The actual plumbing would be well taken care of with CW though.

Paul Sasik
We're already using an IoC container (Unity), but I'm not sure how that would do hot-swapping of loaded types. Does Castle have anything in this area. (A quick look at the web site didn't reveal anything)
Kim Major
Yeah. You'll have to dig a bit deeper but hot swapping was one of the core goals of CW (last time i looked anyway.) Unity doesn't support hot-swapping? Surprising. But just the fact that you're already using a DI framework ought to help you migrate fairly easily.
Paul Sasik
I guess it depends on the definition of "hot swapping". For example, if you have several implementations of an interface you can resolve any given implementation. But I need to replace a concrete implementation after it has been resolved and is in use by the application. It didn't occur to me to look for this in Unity, but I'm pretty sure you can't do that. After you build the container and a type is loaded it's pretty much stuck in the appdomain (unless I'm missing something)
Kim Major
By hot swapping i mean being able to replace code and is instantiated and running, just as you expect i believe. And yes, enabling hot-swappability is dependent upon careful appdomain management because that is the granularity at which you load/unload modules in .Net
Paul Sasik
@Kim: Take a look at this blog post: http://ayende.com/Blog/archive/2007/09/22/Introducing-MonoRail.HotSwap.aspxi got a little confused about the different Castle projects. They have shuffled around since i used them last.
Paul Sasik
+3  A: 

Having a separate service is probably your best option.

You could, potentially, do this in a single service. The "trick" that would be required to making a service self-updating, though, is a bit difficult to implement.

What you would have to do is have your service start off as nothing but a very lightweight shell service. It could then start a separate, insulated AppDomain, and have that appdomain load your service's assemblies, and initialize, and run.

Later, when you wanted to update (which could trigger via any event the service can pick up, including copy of the new assemblies to an update folder [via FileSystemWatcher], explicitly telling it via networking, etc]), it would need to trigger a way to tell the internal AppDomain's type to stop, then unload the AppDomain. At this point, it could do steps 3 & 4 above. Then, it'd just need to reload the AppDomain, rerun it's initialization, etc.

Since the service would be in a separate AppDomain, this could all happen in one executable, without the service stopping. When an AppDomain is unloaded, the assemblies it loads are also unloaded.

The only requirement here that makes it difficult is that you have to make sure not to pass any types into the main AppDomain from the constructed one, or you'll load the assemblies into your main AppDomain. This would prevent you from being able to update them at runtime.

Reed Copsey
ShadowCopyFiles is huge here.
Jason Punyon
Yeah, although with the backup requirements, it may be less of an issue in this specific case.
Reed Copsey
The backup step is not a hard requirement, it's just a step I do so that I can roll back quickly. I'm not familiar with ShadowCopyFiles, have to look into that.
Kim Major
+2  A: 

From our build server, we use a powershell script to remotely stop the service, copy out the new file, and restart the service.

David
We do almost exactly this from CruiseControl.NET. (No powershell).
Jason Punyon