Scheduler Architecture Notes
- schedules are associated to a user
- multiple schedules per user (in order to support multiple collections)
- support multiple job types (forward looking notification job, changes notification job, etc)
- notification method should be configurable for each schedule
- must be able to handle changes in schedules (changes/additions/removals)
- schedules must be able to run on a configurable interval, on the server, taking into account user's timezone
Areas to Think About
There are a lot of moving pieces in a the scheduler framework and these are the main things to think about:
Core Scheduling and Execution
This involves the ability to schedule a job and have that job run at a configurable interval.
- Use the Quartz job scheduler, which supports multiple trigger types, custom triggers, configurable thread pool and many other enterprise features
Schedules have to be persisted and associated to a user.
- Use user preferences. There is already a mechanism for associating arbitrary data with a user in the form of key/value pairs. Not only is the model and persistence there, the protocol support is there. Defining and updating a user's schedules would be as simple as managing a set of properties. This option requires the least amount of work and would support new types of schedules in the future.
- Use custom schedule persistence, which would require changes throughout including model work/persistence layer work/service layer work/protocol layer work.
The scheduler needs to be able to determine what jobs to schedule based each user's schedule configuration.
- Define a
JobScheduler interface that includes an api to schedule a particular job type (for example a forward looking notification job or a "what changed" notification job). Provide the ability to plug in different job schedulers, which would allow additional job types to be defined and implemented easily.
The way the server works today is that when a request comes in, a Hibernate session is opened, the request is performed, and the session is closed. This keeps a session open for the duration of the request allow for lazy loading of data which is used throughout the server. For actions that are initiated on the server such as a schedule, there is no request, so no session opened, therefore no lazy loading.
- Refactor code to not rely on lazy loading (lots of work)
- Add hooks to run code before/after each scheduled job and include code that would mimic the OpenSessionInView? pattern, meaning the session would be bound for the entire job execution (minimal work), plus we need the same hooks for security (see below).
is initialized during each request by parsing credentials provided in the request. Again, with a job initiated by the server there is no way to do this. A Job thread on server needs to have SecurityContext?
otherwise calls to ContentService?
- Add ability to initialize SecurityContext? with any user and do that at beginning of job (using the same hooks as the OpenSessionInView? code). This is the most secure and mimics the job running as the user, allowing authorization checks to be done by the service layer.
- Run all jobs as a super user and do additional authorization checks(less secure and more error prone and more code duplication).
How do we handle changes to a user's schedule? For example, weekly schedule created Mon, but
changed on Wed to Daily, so Thurs job should fire.
- Use the scheduler and schedule a job that runs at a configurable interval (every hour or 2) that refreshes schedules. (easy, but less efficient)
- Provide application event infrastructure that would publish events like "UserUpdated" or "ScheduleUpdated" and have the schedule subscribed to relevant events and update schedule. (lots of work but more efficient)
A scheduled job consists of data being gathered and a way to send it to the user.
- Provide a
Notifier interface that includes an api to notify a user with results. Allow different notifier implementations to be plugged in to the scheduler. For example the first notifier implementation could be an email notifier.
I'm currently working on a prototype that will be checked in to a separate scheduler branch. The prototype consists of all these ideas and in cases where there are multiple ideas, I'm choosing the idea that requires the least amount of work in order to get something functional fairly quickly.
- 16 Apr 2008