« Return to Thread: Refactoring Authenticated/Identified

Refactoring Purging

by Steven Grimm :: Rate this Message:

Reply to Author | View in Thread

First a quick update for everyone reading this: I've done a first round
of the Authenticated refactoring, making the selection of the
SessionManager and SessionValidator completely dynamic based on element
configuration. There are no more Mixed element classes since they are
just the database elements with the memory-based session classes
configured in. Application code that uses rife/authenticated/mixed.xml
won't notice the difference.

But now for the real reason I'm writing this: While I was thinking about
what I want to use this newfound configuration for, I had an idea about
how to factor out the Purging stuff too.

What I want to do is put a caching layer on top of the user and session
data so I don't have to hit the database to fetch the data for a user
who's currently logged in. But I *do* want a database sitting under the
cache; whenever there's a cache miss the database should be consulted
and the cache should be populated.

So basically I want to wrap a caching facade object around the
underlying database-capable objects. And it would be great to allow a
stack of these facades, much in the same way we can stack child-trigger
elements if we want to.

Once that general mechanism is in place, purging is just another thing
that can be layered on top of a SessionManager and/or RememberManager.
In fact, the current implementations of PurgingSessionManager and
PurgingRememberManager barely need to change at all; the only difference
is how the system knows to instantiate them and what to wrap them
around. And the purging behavior could be layered on top of, say, my
caching wrapper.

I think the general principle is probably not that controversial. The
interesting question is, what does the configuration look like? And
that's where I'm less certain.

Spring actually has a reasonable syntax for configuring which beans are
wrapped in which others -- you define the underlying bean, then define
the wrapper bean and configure the underlying bean as a property of the
wrapping bean. But since RIFE doesn't have an equivalent configuration
mechanism for low-level objects, I think that might be a bit too
heavyweight of a change to introduce. On the other hand, if we're
willing to bite that bullet, it probably *is* the most flexible way to
go about this.

Instead, though, maybe something simpler is in order. Something like
this (using some of the new properties I've introduced in my
refactoring; hopefully it's easy enough to follow.) This is a definition
for an element that uses a purging wrapper around a caching wrapper
around a database session manager.

First, database.xml (minus the stuff not related to session managers,
for the sake of example):

<element extends="rife/authenticated/authenticated.xml">
    <property
name="sessionmanagerfactory_class">DatabaseSessionsFactory</property>
    <property name="datasource"></property>
    <property name="sessionmanager_wrap_prefix">db_</property>
</element>

This is just like a normal (post-refactoring) session manager
declaration: a factory class and the parameters it needs to instantiate
its objects. The new thing is the last property; the easiest way to
explain it is by proceeding to the next element, databasecaching.xml:

<element extends="rife/authenticated/database.xml">
    <property
name="db_sessionmanagerfactory_class">SessionManagerWrapperFactory</property>
    <property
name="db_sessionmanager_class">CachingSessionManagerWrapper</property>
    <property name="db_cache_size">1M</property>
    <property name="db_cache_expiration">LRU</property>
    <property name="db_sessionmanager_wrap_prefix">cached_</property>
</element>

Here all the properties are prefixed with the wrap prefix defined by the
element we're wrapping. This prevents namespace collisions. All the
classes involved will be able to take prefix arguments and will know to
strip off their prefixes when looking up their properties. With that in
mind, this looks similar to the initial element: we define a factory
class (in this case, one that knows how to produce wrapper classes; it
will pass the underlying database session manager to the wrapper's
constructor) and tell the factory what underlying class to make. That
underlying class has some properties. Then we define the next prefix in
case there's another element in the chain, which in this case is in
databasecachingpurging.xml:

<element extends="rife/authenticated/databasecaching.xml">
    <property
name="cached_sessionmanagerfactory_class">SessionManagerWrapperFactory</property>
    <property
name="cached_sessionmanager_class">PurgingSessionManagerWrapper</property>
    <property name="cached_purge_frequency">...</property>
    <property name="cached_sessionmanager_wrap_prefix">purged_</property>
</element>

Another wrapper as before, which also defines a prefix for the next link
in the chain. But this time there isn't one. The session manager setup
code will look for a "purged_sessionmanagerfactory_class" property on
the current element, not see one, and will return the
PurgingSessionManagerWrapper object to the caller.

I admit the notion of using prefixes is a little wacky; you really
*should* be able to use the same properties at each level so you don't
have to change your element's properties just to wrap a different
parent. But (as I just confirmed with Geert on IRC) the namespace of
element properties is flat, so you pretty much have to do something like
this to represent an arbitrary chain of parameterized objects.

As with my current round of refactoring, this new flexibility is
completely hidden from applications that just want to use the pre-canned
"databaseunpurged.xml" or whatever. They continue to extend those XML
files as before, blissfully unaware that stuff has gotten more dynamic
under the covers.

What do you guys think?

-Steve
_______________________________________________
Rife-devel mailing list
Rife-devel@...
http://lists.uwyn.com/mailman/listinfo/rife-devel

 « Return to Thread: Refactoring Authenticated/Identified

LightInTheBox - Buy quality products at wholesale price
 
 
 
Google
rifers.org web