Skip to content

Commit f1d1ed3

Browse files
authored
Merge pull request #16 from factorhouse/update-deps
Update deps
2 parents 623ce59 + 0e9e09d commit f1d1ed3

File tree

22 files changed

+1091
-115
lines changed

22 files changed

+1091
-115
lines changed

cronut-integrant/README.md

Lines changed: 439 additions & 0 deletions
Large diffs are not rendered by default.

cronut-integrant/dev-resources/config.edn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
:test.job/one {:dep-one #ig/ref :dep/one}
44

5-
:test.job/two {:identity ["test-group" "test-name"]
5+
:test.job/two {:identity ["name1" "group2"]
66
:description "test job"
77
:recover? true
88
:durable? false

cronut-integrant/project.clj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77
:license {:name "Apache 2.0 License"
88
:url "https://github.com/factorhosue/slipway/blob/main/LICENSE"}
99

10-
:plugins [[dev.weavejester/lein-cljfmt "0.13.1"]]
10+
:plugins [[dev.weavejester/lein-cljfmt "0.13.4"]]
1111

12-
:dependencies [[org.clojure/clojure "1.12.1"]
12+
:dependencies [[org.clojure/clojure "1.12.3"]
1313
[org.clojure/tools.logging "1.3.0"]]
1414

1515
:profiles {:dev {:resource-paths ["dev-resources"]
1616
:dependencies [[integrant "0.13.1"]
17-
[ch.qos.logback/logback-classic "1.5.18"]
17+
[ch.qos.logback/logback-classic "1.5.19"]
1818
[org.slf4j/slf4j-api "2.0.17"]
1919
[org.clojure/core.async "1.8.741"]
20-
[clj-kondo "2025.06.05"]]}
20+
[clj-kondo "2025.09.22" :exclusions [org.clojure/tools.reader]]]}
2121
:jakarta {:dependencies [[io.factorhouse/cronut "1.0.0"]]}
2222
:javax {:dependencies [[io.factorhouse/cronut-javax "1.0.0"]]}
2323
:smoke {:pedantic? :abort}}

cronut-integrant/test/cronut/integration_test.clj

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
(:import (java.util UUID)
88
(org.quartz Job)))
99

10-
(defrecord TestDefrecordJobImpl [identity description recover? durable? test-dep disallowConcurrentExecution?]
10+
(defrecord TestDefrecordJobImpl [identity description recover? durable? test-dep disallow-concurrent-execution?]
1111
Job
1212
(execute [this _job-context]
1313
(log/info "Defrecord Impl:" this)))
@@ -36,10 +36,15 @@
3636
(log/info rand-id "Finished")))))
3737

3838
(defn init-system
39-
"Convenience for starting integrant systems with cronut data-readers"
39+
"Example of starting integrant cronut systems with data-readers"
4040
([]
4141
(init-system (slurp (io/resource "config.edn"))))
4242
([config]
4343
(init-system config nil))
4444
([config readers]
45-
(ig/init (ig/read-string {:readers (merge cig/data-readers readers)} config))))
45+
(ig/init (ig/read-string {:readers (merge cig/data-readers readers)} config))))
46+
47+
(defn halt-system
48+
"Example of stopping integrant cronut systems"
49+
[system]
50+
(ig/halt! system))

cronut-javax/README.md

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
# Cronut Javax: A Clojure Companion to Quartz (Legacy Javax Support)
2+
3+
[![Cronut Test](https://github.com/factorhouse/cronut/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/factorhouse/cronut/actions/workflows/ci.yml)
4+
[![Clojars Project](https://img.shields.io/clojars/v/io.factorhouse/cronut.svg)](https://clojars.org/io.factorhouse/cronut)
5+
6+
# Summary
7+
8+
[Cronut](https://github.com/factorhouse/cronut) provides a data-first [Clojure](https://clojure.org/) wrapper
9+
for [Quartz Scheduler](https://github.com/quartz-scheduler/quartz) version `2.4.0`, compatible
10+
with [Javax](https://jakarta.ee/blogs/javax-jakartaee-namespace-ecosystem-progress/).
11+
12+
Cronut supports **in-memory** scheduling of jobs within a single JVM. JDBC and distributed jobstore are not supported.
13+
14+
## Related Projects
15+
16+
| Project | Desription | Clojars Project |
17+
|---------------------------------------------------------------------|---------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
18+
| [cronut](https://github.com/factorhouse/cronut) | Cronut with [Jakarta](https://en.wikipedia.org/wiki/Jakarta_EE) support | [![Clojars Project](https://img.shields.io/clojars/v/io.factorhouse/cronut-javax.svg)](https://clojars.org/io.factorhouse/cronut-javax) |
19+
| [cronut-integrant](https://github.com/factorhouse/cronut-integrant) | [Integrant](https://github.com/weavejester/integrant) bindings for Cronut | [![Clojars Project](https://img.shields.io/clojars/v/io.factorhouse/cronut-integrant.svg)](https://clojars.org/io.factorhouse/cronut-integrant) |
20+
21+
# Contents
22+
23+
# Usage
24+
25+
A quartz `scheduler` runs a `job` on a schedule defined by a `trigger`.
26+
27+
## Scheduler
28+
29+
Cronut provides access to the Quartz Scheduler, exposed via the `cronut/scheduler` function.
30+
31+
Create a scheduler with the following configuration:
32+
33+
1. `:concurrent-execution-disallowed?`: (optional, default false) - run all jobs with @DisableConcurrentExecution
34+
2. `:update-check?`: (optional, default false) - check for Quartz updates on system startup.
35+
36+
````clojure
37+
(cronut/scheduler {:concurrent-execution-disallowed? true
38+
:update-check? false})
39+
````
40+
41+
### Scheduler lifecycle
42+
43+
Once created, you can:
44+
45+
* `cronut/start`: start the scheduler
46+
* `cronut/start-delayed`: start the scheduler with a delay
47+
* `cronut/standy`: temporarily halt the firing of triggers by the scheduler
48+
* `cronut/shutdown`: stop the scheduler
49+
* `cronut/pause-all`: pause all triggers
50+
* `cronut/resume-all`: resume all triggers
51+
* `cronut/clear`: clear all scheduling data of jobs and triggers
52+
53+
### Scheduling jobs
54+
55+
To schedule jobs, you can
56+
57+
* `cronut/schedule-job`: schedule a single job
58+
* `cronut/schedule-jobs`: schedule multiple jobs at once
59+
* `cronut/pause-job`: pause a job
60+
* `cronut/resume-job`: resume a paused job
61+
* `cronut/unschedule-job`: remove a trigger from the scheduler
62+
* `cronut/delete-job`: remove a job and all associated triggers from the scheduler
63+
* `cronut/pause-trigger`: pause a trigger
64+
* `cronut/resume-trigger`: resume a paused trigger
65+
66+
## Jobs
67+
68+
Each cronut job must implement the `org.quartz.Job` interface.
69+
70+
The expectation being that every job will reify that interface either directly via `reify` or by returning a `defrecord`
71+
that implements the interface.
72+
73+
Cronut supports further Quartz configuration of jobs (identity, description, recovery, and durability) by expecting
74+
those values to be assoc'd onto your job. You do not have to set them (in fact in most cases you can likely ignore
75+
them), however if you do want that control you will likely use the `defrecord` approach as opposed to `reify`.
76+
77+
Concurrent execution can be controlled on a per-job bases with the `disallow-concurrent-execution?` flag.
78+
79+
### Job example
80+
81+
````clojure
82+
(defrecord TestDefrecordJobImpl [identity description recover? durable?]
83+
Job
84+
(execute [this _job-context]
85+
(log/info "Defrecord Impl:" this)))
86+
87+
88+
(let [scheduler (cronut/scheduler {:concurrent-execution-disallowed? true
89+
:update-check? false})
90+
defrecord-job (map->TestDefrecordJobImpl {:identity ["name1" "group2"]
91+
:description "test job"
92+
:recover? true
93+
:durable? false})
94+
reify-job (reify Job
95+
(execute [_this _job-context]
96+
(let [rand-id (str (UUID/randomUUID))]
97+
(log/info rand-id "Reified Impl"))))]
98+
99+
(cronut/schedule-job scheduler (trigger/interval 1000) defrecord-job)
100+
101+
(cronut/schedule-job scheduler
102+
(trigger/builder {:type :cron
103+
:cron "*/5 * * * * ?"
104+
:misfire :do-nothing})
105+
reify-job))
106+
````
107+
108+
## Triggers
109+
110+
Cronut triggers are of type `org.quartz.Trigger`, the following functions are provided to simplify trigger creation:
111+
112+
#### `cronut.trigger/cron`: Simple Cron Scheduling
113+
114+
A job is scheduled to run on a cron by using the `cronut.trigger/cron` function with a valid cron expression.
115+
116+
The job will start immediately when the system is initialized, and runs in the default system time-zone
117+
118+
````clojure
119+
(cronut.trigger/cron "*/8 * * * * ?")
120+
````
121+
122+
#### `cronut.trigger/interval`: Simple Interval Scheduling
123+
124+
A job is scheduled to run periodically by using the `cronut.trigger/interval` function with a milliseconds value
125+
126+
````clojure
127+
(cronut.trigger/interval 3500)
128+
````
129+
130+
#### `cronut.trigger/builder`: Full trigger definition
131+
132+
Both `cronut.trigger/cron` and `cronut.trigger/interval` are effectively shortcuts to full trigger definition with
133+
sensible defaults.
134+
135+
The `cronut.trigger/builder` function supports the full set of Quartz configuration triggers:
136+
137+
````clojure
138+
;; interval
139+
(cronut.trigger/builder {:type :simple
140+
:interval 3000
141+
:repeat :forever
142+
:identity ["trigger-two" "test"]
143+
:description "sample simple trigger"
144+
:start #inst "2019-01-01T00:00:00.000-00:00"
145+
:end #inst "2019-02-01T00:00:00.000-00:00"
146+
:misfire :ignore
147+
:priority 5})
148+
149+
;;cron
150+
(cronut.trigger/builder {:type :cron
151+
:cron "*/6 * * * * ?"
152+
:identity ["trigger-five" "test"]
153+
:description "sample cron trigger"
154+
:start #inst "2018-01-01T00:00:00.000-00:00"
155+
:end #inst "2029-02-01T00:00:00.000-00:00"
156+
:time-zone "Australia/Melbourne"
157+
:misfire :fire-and-proceed
158+
:priority 4})
159+
````
160+
161+
## Concurrent execution
162+
163+
### Global concurrent execution
164+
165+
Set `:concurrent-execution-disallowed?` on the scheduler to disable concurrent execution of all jobs.
166+
167+
### Job-specific concurrent execution
168+
169+
Set `:disallow-concurrent-execution?` on a specific job to disable concurrent execution of that job only.
170+
171+
### Misfire configuration
172+
173+
If you disable concurrent job execution ensure you understand Quartz Misfire options and remember to set
174+
`org.quartz.jobStore.misfireThreshold=[some ms value]` in your quartz.properties file. See Quartz documentation for more
175+
information.
176+
177+
See our test-resources/config.edn and test-resources/org/quartz/quartz.properties for examples of misfire threshold and
178+
behaviour configuration.
179+
180+
# Example system
181+
182+
See: integration test source: [test/cronut/integration-test.clj](test/cronut/integration_test.clj).
183+
184+
````clojure
185+
(ns cronut.integration-test
186+
(:require [clojure.core.async :as async]
187+
[clojure.tools.logging :as log]
188+
[cronut :as cronut]
189+
[cronut.trigger :as trigger])
190+
(:import (java.util UUID)
191+
(org.quartz Job)))
192+
193+
(defrecord TestDefrecordJobImpl [identity description recover? durable? test-dep disallowConcurrentExecution?]
194+
Job
195+
(execute [this _job-context]
196+
(log/info "Defrecord Impl:" this)))
197+
198+
(def reify-job (reify Job
199+
(execute [_this _job-context]
200+
(let [rand-id (str (UUID/randomUUID))]
201+
(log/info rand-id "Reified Impl (Job Delay 7s)")
202+
(async/<!! (async/timeout 7000))
203+
(log/info rand-id "Finished")))))
204+
205+
;(do (require '[cronut.integration-test :as it])
206+
; (it/test-system))
207+
(defn test-system
208+
[]
209+
(let [scheduler (cronut/scheduler {:concurrent-execution-disallowed? true})]
210+
(cronut/clear scheduler)
211+
212+
(async/<!! (async/timeout 2000))
213+
214+
(log/info "scheduling defrecord job on 1s interval")
215+
(cronut/schedule-job scheduler
216+
(trigger/interval 1000)
217+
(map->TestDefrecordJobImpl {:identity ["name1" "group2"]
218+
:description "test job"
219+
:recover? true
220+
:durable? false}))
221+
222+
;; demonstrate scheduler can start with jobs, and jobs can start after scheduler
223+
(cronut/start scheduler)
224+
225+
(async/<!! (async/timeout 2000))
226+
227+
;; demonstrates concurrency disallowed (every second job runs, 10s interval between jobs that should run every 5s)
228+
(log/info "scheduling reify/7s/no-misfire job on 5s interval")
229+
(cronut/schedule-job scheduler
230+
(trigger/builder {:type :cron
231+
:cron "*/5 * * * * ?"
232+
:misfire :do-nothing})
233+
reify-job)
234+
235+
(async/<!! (async/timeout 15000))
236+
237+
(log/info "deleting job group2.name1")
238+
(cronut/delete-job scheduler "name1" "group2")
239+
240+
(async/<!! (async/timeout 15000))
241+
242+
(cronut/shutdown scheduler)))
243+
````
244+
245+
# License
246+
247+
Distributed under the Apache 2.0 License.
248+
249+
Copyright (c) [Factor House](https://factorhouse.io)

cronut-javax/dev-resources/config.edn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
:test.job/one {:dep-one #ig/ref :dep/one}
44

5-
:test.job/two {:identity ["test-group" "test-name"]
5+
:test.job/two {:identity ["name1" "group2"]
66
:description "test job"
77
:recover? true
88
:durable? false

cronut-javax/project.clj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77
:license {:name "Apache 2.0 License"
88
:url "https://github.com/factorhosue/slipway/blob/main/LICENSE"}
99

10-
:plugins [[dev.weavejester/lein-cljfmt "0.13.1"]]
10+
:plugins [[dev.weavejester/lein-cljfmt "0.13.4"]]
1111

12-
:dependencies [[org.clojure/clojure "1.12.1"]
12+
:dependencies [[org.clojure/clojure "1.12.3"]
1313
[org.clojure/tools.logging "1.3.0"]
1414
[org.quartz-scheduler/quartz "2.4.0" :exclusions [org.slf4j/slf4j-api]]]
1515

1616
:profiles {:dev {:resource-paths ["dev-resources"]
1717
:dependencies [[ch.qos.logback/logback-classic "1.3.15"]
1818
[org.slf4j/slf4j-api "2.0.17"]
1919
[org.clojure/core.async "1.8.741"]
20-
[clj-kondo "2025.06.05"]]}
20+
[clj-kondo "2025.09.22" :exclusions [org.clojure/tools.reader]]]}
2121
:smoke {:pedantic? :abort}}
2222

2323
:aliases {"check" ["with-profile" "+smoke" "check"]

0 commit comments

Comments
 (0)