From: Michael Neumann Date: 2004-11-04T20:48:18+09:00 Subject: Re: [ANN] Transaction::Simple 1.2.0 On Thu, Nov 04, 2004 at 12:13:20PM +0900, Austin Ziegler wrote: > Contraindications > ----------------- > While Transaction::Simple is very useful, it has some severe limitations that > must be understood. Transaction::Simple: > > * uses Marshal. Thus, any object which cannot be Marshal-ed cannot use > Transaction::Simple. > * does not manage resources. Resources external to the object and its instance > variables are not managed at all. However, all instance variables and > objects "belonging" to those instance variables are managed. If there are > object reference counts to be handled, Transaction::Simple will probably > cause problems. > * is not thread-safe. In the ACID ("atomic, consistent, isolated, durable") > test, Transaction::Simple provides C and D, but it is up to the user of > Transaction::Simple to provide isolation. Transactions should be considered > "critical sections" in multi-threaded applications. Thread safety can be > ensured with Transaction::Simple::ThreadSafe. > * does not maintain Object#__id__ values on rewind or abort. This may change > for future versions that will be Ruby 1.8 or better only. Hm, I've written a similar library for Wee, which saves snapshots of objects, and is able to restore the old object from a snapshot. It does not use Marshal, and maintains __id__ values correctly. Snapshots are, what you call "transactions". s = StateRegistry.new v = "good morning...." # => "good morning...." p v.object_id # => xxxx s.register(v) snap1 = s.snapshot v.gsub!(/morning/, "evening") snap2 = s.snapshot v.gsub!(/good/, "superb") snap3 = s.snapshot snap1.apply p v # => "good morning...." p v.object_id # => xxxx snap2.apply p v # => "good evening...." p v.object_id # => xxxx snap3.apply p v # => "superb evening...." p v.object_id # => xxxx Of course this works with any number of registered objects. How a snapshot is taken or restored is defined per-class/object (methods take_snapshot and apply_snapshot). http://ntecs.de/viewcvs/viewcvs/Wee/trunk/lib/wee/state_registry.rb?rev=289&view=auto http://ntecs.de/viewcvs/viewcvs/Wee/trunk/lib/wee/snapshot.rb?rev=289&view=auto I guess this could be used to implement transactions: def transaction(*vars) s = StateRegistry.new vars.each do |v| s.register(v) end snap = s.snapshot begin yield rescue Exception snap.apply # restore old snapshot end end v = "good " # => "good " transaction(v) do v << "morning" raise end p v # => "good " (and same __id__) If this is not only usable for my framework, then I'll release this as an extra library. Regards, Michael