+ synchronized (queue) {
+ logger.trace("Enqueuing {} job", job.getClass().getSimpleName());
+ queue.add(job);
+ }
+
+ runNextJob();
+ }
+
+ private void runNextJob() {
+ Job job;
+ synchronized (queue) {
+ if (running != null) {
+ return;
+ }
+ job = queue.poll();
+ running = job;
+ }
+
+ if (job == null) {
+ synchronized (this) {
+ this.notifyAll();
+ }
+ return;
+ }
+ logger.debug("Running {} job", job.getClass().getSimpleName());
+ executorService.execute(() -> {
+ try {
+ job.run(context);
+ } catch (Throwable e) {
+ logger.warn("Job {} failed", job.getClass().getSimpleName(), e);
+ } finally {
+ synchronized (queue) {
+ running = null;
+ }
+ runNextJob();
+ }
+ });