[Haskell-cafe] transactional cache

Alberto G. Corona agocorona at gmail.com
Tue May 16 08:10:46 EDT 2006

Finally i did it. The transactional cache uses STM, no blocking MVars.

I created has a simple interface, the transactional "plumbing" is
hidden in the TransactCacheSTM module.  The usage is simple:

withResources [object1, object2,..] process
         process[maybeObject1,maybeObject2.....]= [newObject1,newObect2...]

"process" run atomically, object1,object2.. are partially defined,
just with the fields neccesary to retrieve them. newObjects are the
resulting objects that replace the previous content in the cache. Non
existing objects are created.

the objects must implement "IResource" type class procedures for
reading, writing and obtaining a unique key so that the objects can be
read to, write from and do search from the cache. No other asumptions
are made about the object types or storages.

In the following example, client Alberto buy a computer. the total
amount due by Alberto is increased with the computer price. The
quantity of the item "computer" in stock is decreased.

withResources[Client{name="Alberto"}, Item{iname="computer"} buy
      buy[Nothing,_]= error "Client does not exist"
      buy[_,Nothing]= error "Item does not exist"
      buy[Just client, Just item]= [client{total client=total client+
price item},

The resulting code is transactional and clean. The  object is read if
not already in the cache using the user defined procedure for that
object (either a sql query or read from a file).

The write is delayed depending on object usage in the cache and the
cache size. I also defined ordinary, non transactional object
retrieval (getResources :: [Resource]->IO[Resource]  )

To have real ACID transactions, I also defined a procedure for atomic
write of the entire cache to disk, in order to have  coherent content
in permanent storage,

(I´m using it on a portal 100% coded in Haskell (I love Haskell since
i knew it five months ago).  this trhansactional cache makes the data
handling in my portal a lot easier. I use XML files, no boring
database tables are necessary.

I will put online the transactional cache sometime later, but by now I
will send te code by mail to anyone interested.

Message: 8
Date: Sat, 13 May 2006 12:26:42 +0900
From: "Evan Martin" <martine at danga.com>
Subject: Re: [Haskell-cafe] RE: transactional cache
To: "Alberto G. Corona" <agocorona at gmail.com>
Cc: haskell-cafe at haskell.org
       <3a6f89fc0605122026y6727d55cl61e60a101c73e93e at mail.gmail.com>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

On 5/13/06, Alberto G. Corona <agocorona at gmail.com> wrote:
> > notglobal = newIORef True
> > main = do a <- notglobal
> >         b <- notglobal
> Thanks. I got the poit more or less; Each invocation creates a new
> IORef instance.

Another way of looking at this, that might be more instructive, is
that notglobal is defined to be the action of creating a new IO ref.
You can see that in its type:
 > :t newIORef True
 newIORef True :: IO (IORef Bool)
I read that type as "an IO operation that produces an IORef Bool when executed".

Then the code in main "executes" notglobal twice.

Another way of looking at this is that you can always substitute the
right side of an equals sign in for the left side.  If you do that on
this code this makes it plain that a and b will be different.
(unsafePerformIO breaks this substitution rule.)

More information about the Haskell-Cafe mailing list