I have an application running on two instances and only communication between the instances is that they operate on a single database. I have few batch jobs running on it. For example: Copy records from the database to a file and deliver the file to a server. Since there is a common database for both the instances, I'm trying to write to a table that job has been triggered. Basically, a trigger condition is such a record doesn't exist on a given table. How can I perform this atomically, i.e., check the table that job hasn't been triggered then insert into table?
Java - Cron job - if an instance triggers a batch job, prevent other instance from doing the same
1.5k views Asked by rohan At
2
There are 2 answers
0
On
Pesimistic locking can help here:
- Create a dedicated table that holds a lock record, with the last execution time
- In the scheduled execution, aquire (or create) the lock record over an injected
EntityManager
withLockModeType.PESSIMISTIC_WRITE
. - Check the execution time on the lock record: if it was recently updated, the job must have already been run on another instance
- Otherwise, execute the job, and update the last execution time on the lock record afterwards.
See Lock Modes (Java EE Tutorial) for more details an options.
Example application of such a locking mechanism: Liquibase's DATABASECHANGELOGLOCK
table, documented here.
If you have a scheduled task that needs to be launched, for example, every 15 seconds and should only run on a single instance of app, then you can use ShedLock
It's pretty simple mechanism that basically does the same that you mentioned - creates a table (actually, you need to create it once) and periodically acquires lock for it. You can set up for how much time it should be locked and some others things.
Works with both SQL and NoSQL dbs, like Postgres and Mongo and requires just one annotation
@SchedulerLock
. See below: