Friday, December 21, 2007

Quartz.Net composite keys

At the moment I'm trying to integrate Quartz.Net scheduler with our business rule engine. Quartz.Net is very promising, as it has a comprehensive set of scheduling capabilities, and, what is more important "Quartz.NET can be instantiated as a cluster of stand-alone programs (with load-balance and fail-over capabilities)

Clustering and load balancing is what we really need, and do not want to invest my precious time doing same bicycle again.

So far so good, until you come to database, and notice that all Quartz.Net database structure has taken a somewhat strange way to define primary and foreign keys.

Let us have an example :



CREATE TABLE QRTZ_JOB_DETAILS (
JOB_NAME VARCHAR(60) NOT NULL,
JOB_GROUP VARCHAR(60) NOT NULL,
DESCRIPTION VARCHAR(120),
JOB_CLASS_NAME VARCHAR(128) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_VOLATILE VARCHAR(1) NOT NULL,
IS_STATEFUL VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB,
CONSTRAINT PK_QRTZ_JOB_DETAILS PRIMARY KEY (JOB_NAME,JOB_GROUP)
);



Everythin is sping'n'span except two columns "JOB_NAME" and JOB_GROUP, which apparently describe an ID of JobDetail. And it goes for all tables like this where JobDetail, Trigger (which is the main concept of whole scheduler), and listeners.

Why do I care about it? Because it makes more difficult to use such database in our project:

  1. Having a composite primary key (name and group) makes mapping of tables to POCO more compliated

  2. Primary key is not auto-generated by database, but rather controlled by client-side, which puts more responsibility on it.

  3. More responsibility means more code. More code means more stuff look after and more time spent on maintaining it

  4. Primary keys should NOT have any business meaning attached to it. Now properties Name and Group definetely carry meaning

  5. Say, you have a group of triggers. That group contains 1000 triggers. If business situation changes, and new business rules require you to immediately pause 100 of those triggers, what you have to do is to change group name for those triggers. Now if you change the group of a trigger, you will get unexpected behaviour, since your foreign keys will become incosistent. One example would be TriggerListeners not referencing those 100 triggers

  6. A name of a jobDetail should be it's name, and not a primary key. It's like saying that Darius is an ID of my person. Who knows, maybe I will change my name in some distant future



That's the first impression that pops in my mind when I see such database structure. (Yes, impression change in the long run, especially if someone gives very strong arguments of why I should do so)

1 comment:

Vikas Gandhi said...

I would be certainly glad if u would be kind enough to share your experience. I was interested in Quartz.net and was not able to comprehend benifits of its enterprize level support like clustering. Good of u can spare yor thoughts/experience on this.