Hugoware

The product of a web developer with a little too much caffeine

Work Sequences Using Lambdas

with 2 comments

Occasionally I’ll run into some code that I want to “undo” in case the entire thing doesn’t go as planned. Normally placing this code into a separate class and then performing each work item one at a time works pretty well. You have to keep track of your progress so you know where to rollback from but overall it isn’t a very complicated process.

I had pretty much the same scenario the other day, but this time I thought I’d approach it a little differently. Instead of writing the sequence management into the class I was using I decided to see if I could come up with the same concept using lambdas instead.

[Download Source Code: WorkSequence.cs] : Hosted on gist.github.

The idea is to make some reusable code that can be used within a class to handle sequences of code. Let’s look at a sample of how you might use this code – We’re going to pretend this code is part of a class responsible for moving some data around. If one transfer fails then all of the work should be reverted.

string path = Path.Combine(@"\\server\share\", this.FileName);

//creating a default sequence
WorkSequence work = new WorkSequence();

//when a rollback takes place
work.Error += (sequence, item, index) => {
    string name = item.GetPerformMethod().Name;
    Console.WriteLine("Failed item {0}", name);
};

//when the work finished
work.Complete += (sequence) => {
    Console.WriteLine("Finished work!");
};

//1. calling a method without a rollback step
work.Add(this.GenerateLibrary);

//2. calling a method that has an undo step
work.Add(this.CreatePackage, this.RemoveTempCacheFile);

//3. calling methods that have arguments
work.Add(() => this.Transfer(path), () => File.Delete(path));

//4. calling a method using different credentials
work.Add(this.Archive, new ImpersonationContext("domain\\name", "passw0rd"));

//5. starts executing the work
work.Perform();

//6. or an async call
work.PerformAsync((sequence) => {
    Console.WriteLine("Finished in sequence");
});

The general idea for this code is to set the work that you need to do and then an optional ‘rollback’ option in case there is a problem. You’ll notice that none of the methods accept arguments. Instead, you can provide an action that invokes the action and then provides the arguments (in #3).

As each item is fired an index is used to keep track of the position in the sequence. That way, if there is an error, only the work that has actually executed will have the rollback method fired.

You’ll also notice that I’m using the code I recently published so you can provide credentials to use for impersonation. This can be per method or applied as a ‘default’ for the entire sequence.

Finally, you can either invoke the process and wait for all of the work to complete or fire it up in an asynchronously. You can provide a callback method or assign an event to fire off once the work has completed.

Not sure if there is a built in class to handle this kind of work but I’ve found it useful so far – Enjoy!

Advertisements

Written by hugoware

April 19, 2010 at 11:29 pm

2 Responses

Subscribe to comments with RSS.

  1. You got me thinking: with each action you could potentially serialize important objects to JSON and store them in Mongo, identifiying each sequence with a transaction key such as a hask of the date + time + user or somthing similar. That way you can return later and replay the steps as the user or process did.

    This could be a great way to debug / test complex actions that your system needs to complete. Your rollback can then set any object back to any step that you wish.

    On the CSMongo front, I’ve been cooking with the driver and hope to get something posted soon. So far I haven’t had any issues.

    ActiveEngine Sensei

    April 22, 2010 at 6:13 am

    • That is a very interesting idea especially since MongoDB is so flexible – you could store any combination of parameters on the fly.

      Interestingly, you can also serialize the anonymous methods and store them in your database (if you’re crazy that is) – I don’t really think it is a viable option since deserialization can be tricky, but if you figured out a way to do it you could technically store the actual bytes to execute as part of the rollback option — Crazy!

      hugoware

      April 23, 2010 at 8:41 am


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: