From: Vladimir Zolotykh
Subject: extending WITH-TRANSACTION
Date: 
Message-ID: <3C5C266A.7D73E0EA@eurocom.od.ua>
Consider the following

(defclass person ()
  ((sum :initarg person-age :accessor person-sum)
   ;; ... more slots ...
   ))

(defmethod update ((person person) &optional (db *some-db*))
  
  ;; Updates database data about PERSON, particularly the slot SUM
  ;; ......
  )

(defmacro with-transaction ((db) &body body)
  (let ((abort (gensym)))
    `(let ((,abort t))
       (unwind-protect
	   (progn
	     ;; Begin transaction here...
	     (multiple-value-prog1
		 (progn ,@body)
	       (do-atomically
		 ;; Commit transaction here...
		 (setq ,abort nil))))
	 (when ,abort 
	   ;; Rollback transaction here
	   )))))

(defun not-ok (person db)
  (with-transaction (db)
    (incf (person-sum person) 1)
    (update person)))

The NOT-OK leaves PERSON object in invalid state when UPDATE failed
for some reason. E.g. NOT-OK doesn't change database record but does
the PERSON object.

The question is rather simple. Does some technique exist for dealing
with such situations ? E.g. I wonder whether it could be done in some
'centralized/localized' way like 'WITH-TRANSACTION' above for dealing
with database operations.

-- 
Vladimir Zolotykh                         ······@eurocom.od.ua

From: Alain Picard
Subject: Re: extending WITH-TRANSACTION
Date: 
Message-ID: <86ofj75qje.fsf@gondolin.local.net>
Vladimir Zolotykh <······@eurocom.od.ua> writes:


> The question is rather simple. Does some technique exist for dealing
> with such situations ? E.g. I wonder whether it could be done in some
> 'centralized/localized' way like 'WITH-TRANSACTION' above for dealing
> with database operations.

We wrote a version of with-transaction where we bind
a special variable, say, *modified-objects*, and capture
all (SETF FOO) calls to the persistent objects to PUSHNEW
the object onto *modified-objects*.  Then, the transaction
macro can call REVERT or SUCCESSFUL-TRANSACTION on all
*modified-objects* after the commit or rollback.

Is that what you mean?

-- 
It would be difficult to construe        Larry Wall, in  article
this as a feature.			 <·····················@netlabs.com>
From: Vladimir Zolotykh
Subject: Re: extending WITH-TRANSACTION
Date: 
Message-ID: <3C5CFEFE.669DE102@eurocom.od.ua>
Alain Picard wrote:
> 
> We wrote a version of with-transaction where we bind
> a special variable, say, *modified-objects*, and capture
> all (SETF FOO) calls to the persistent objects to PUSHNEW
> the object onto *modified-objects*.  Then, the transaction
> macro can call REVERT or SUCCESSFUL-TRANSACTION on all
> *modified-objects* after the commit or rollback.
> 
> Is that what you mean?
Exactly.
The most difficult part is to capture all (SETF OBJ) I presume.
Does your macro do it for you ?

-- 
Vladimir Zolotykh                         ······@eurocom.od.ua
From: Coby Beck
Subject: Re: extending WITH-TRANSACTION
Date: 
Message-ID: <8sj78.19890$Jq.844843@news2.calgary.shaw.ca>
"Vladimir Zolotykh" <······@eurocom.od.ua> wrote in message
······················@eurocom.od.ua...
> Alain Picard wrote:
> >
> > We wrote a version of with-transaction where we bind
> > a special variable, say, *modified-objects*, and capture
> > all (SETF FOO) calls to the persistent objects to PUSHNEW
> > the object onto *modified-objects*.  Then, the transaction
> > macro can call REVERT or SUCCESSFUL-TRANSACTION on all
> > *modified-objects* after the commit or rollback.
> >
> > Is that what you mean?
> Exactly.
> The most difficult part is to capture all (SETF OBJ) I presume.
> Does your macro do it for you ?
>
> --
> Vladimir Zolotykh                         ······@eurocom.od.ua

The with-transaction macro can't do that.  What you would want would be a
def-persistent-class macro that would automatically define :around or :after
methods on all persisted slots.  These methods would handle adding the
object to *modified* list.  You can generate methods to call when an object
needs to be rolled back too, if you've stored the original values, or just
update from the old, but correct entry in the DB.

You could also have a transaction mixin class that would be keeping tabs on
all of its modified slots and in your roolback code call a method that puts
all the slots back.  Then just inherit from this mixin instead of wrapping
around def-class.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Alain Picard
Subject: Re: extending WITH-TRANSACTION
Date: 
Message-ID: <86k7tt64q7.fsf@gondolin.local.net>
"Coby Beck" <·····@mercury.bc.ca> writes:

> "Vladimir Zolotykh" <······@eurocom.od.ua> wrote in message

> > The most difficult part is to capture all (SETF OBJ) I presume.
> > Does your macro do it for you ?
> >

[Snipped explanation]

Aaaaaaw, no fair.  You peeked!  :-)

Actually, we define our own method combination,
and do all the magic in an :internal-around, so clients
can continue to use the normal :before, :after and :around
methods without fear of the world breaking on them.  But
the idea is exactly as you explained.


-- 
It would be difficult to construe        Larry Wall, in  article
this as a feature.			 <·····················@netlabs.com>