Bevan,
every task needs to have built in "smarts" to support rollback.
Perhaps you have suggested an elegant way of providing
> transaction-like operation while not putting undue stress > on Charlie.
What if each <target> definition could include an OPTIONAL
> error recovery <target>. As long as you can get by with > target-level rollback (rather than task-level), it should > give most of the hooks you need while not being a huge, > buggy burden to implement.
Merrill
May I suggest a solution that provides full reverse-rollback functionality with out-of-the-box NAnt 0.85?
Completely flexible, configurable, and not spaghetti code. Well, IMHO. Comments welcome and invited.
Features:
* Arbitrary level of rollback control. You can specify rollback blocks per task, per target, or per set of tasks.
* 100% control over rollback behaviour. The person who knows best what needs to be done to roll a particular action back is you.
Drawbacks:
* This is all-or-nothing rollback. There's no way to specify checkpoints, or to continue processing after rolling back and recovering.
* Somewhat fragile. If anyone messes with any of the magic properties, then rollback will fail.
If someone really wanted a more robust rollback mechanism, then the idea behind what's going on below can be translated into a set of tasks with little difficulty... register a build listener to react to onfailure (or onsuccess, if you want commit support!) events and trigger rollback, you could also offer explicit rollback (and commit) tasks, as well as nested or grouped transactions. There's no need to go messing with the NAnt core to do something which is 100% process.
The solution itself! Tested to work in 0.85 rc1. Play around with the failure in the test script... move it around, and confirm that it will only roll back tasks that have been performed.
File 1: General include file "rollback.xml" <project name="Rollback"> <property name="nant.rollback.onfailure.chain" value="${nant.onfailure}" if="${property::exists('nant.onfailure')}" /> <property name="nant.rollback.onfailure.chain" value="" unless="${property::exists('nant.onfailure')}" /> <!-- If nant.onfailure is already set, set up an onfailure chain so all onfail targets are called -->
<property name="nant.onfailure" value="rollback" /> <property name="rollback.stack" value="" /> <!-- Initialise the rollback stack -->
<target name="rollback"> <echo level="Debug" message="Rollback stack = "${rollback.stack}"" /> <foreach item="String" in="${rollback.stack}" delim=" " property="rollback.target"> <if test="${string::get-length(rollback.target) > 0}"> <!-- Skip empty targets, presumably from extra delimiters --> <call target="${rollback.target}" if="${target::exists(rollback.target)}" /> <echo level="Warning" message="Rollback target ${rollback.target} unknown" unless="${target::exists(rollback.target)}" /> </if> </foreach> <if test="${target::exists(nant.rollback.onfailure.chain)}"> <!-- Continue the onfailure chain --> <call target="${nant.rollback.onfailure.chain" /> </if> </target> </project>
File 2: Specific build file "rollback-test.xml" <project name="RollbackTest" default="all"> <include buildfile="rollback.xml" />
<target name="foo.perform"> <echo message="Performing foo..." /> <property name="rollback.stack" value="${rollback.stack} foo.rollback" /> </target> <target name="foo.rollback"> <echo message="Rolling back foo!" /> </target>
<target name="bah.perform"> <echo message="Performing bah step 1..." /> <property name="rollback.stack" value="${rollback.stack} bah.rollback.1" /> <fail message="Failed!" /> <echo message="Performing bah step 2..." /> <property name="rollback.stack" value="${rollback.stack} bah.rollback.2" /> </target>
<target name="bah.rollback.1"> <echo message="Rolling back bah step 1!" /> </target> <target name="bah.rollback.2"> <echo message="Rolling back bah step 2!" /> </target>
<target name="all" depends="foo.perform, bah.perform" /> </project>
-T
------------------------------------------------------- This SF.Net email is sponsored by: IntelliVIEW -- Interactive Reporting Tool for open source databases. Create drag-&-drop reports. Save time by over 75%! Publish reports on the web. Export to DOC, XLS, RTF, etc. Download a FREE copy at http://www.intelliview.com/go/osdn_nl _______________________________________________ Nant-users mailing list Nant-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/nant-users