├── test
└── tr
│ └── on_test.clj
├── .gitignore
├── project.clj
├── .travis.yml
├── README.md
└── src
└── tr
└── on.clj
/test/tr/on_test.clj:
--------------------------------------------------------------------------------
1 | (ns tr.on-test
2 | (:require [tr.on :refer :all]
3 | [clojure.test :refer :all]))
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /doc
2 | /target
3 | /classes
4 | /checkouts
5 | pom.xml
6 | pom.xml.asc
7 | *.jar
8 | *.class
9 | /.lein-*
10 | /.nrepl-port
11 |
--------------------------------------------------------------------------------
/project.clj:
--------------------------------------------------------------------------------
1 | (defproject spootnik/tron "0.5.4"
2 | :description "TRON: Task Run ON"
3 | :url "https://github.com/pyr/tron"
4 | :dependencies [[org.clojure/clojure "1.7.0"]])
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: clojure
3 | lein: lein2
4 | jdk:
5 | - oraclejdk8
6 | - oraclejdk7
7 | - openjdk7
8 | branches:
9 | except:
10 | - gh-pages
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | TRON: Task Run ON
2 | =================
3 |
4 | [](http://travis-ci.org/pyr/tron)
5 |
6 |
7 | TRON lets you schedule tasks for execution using a Java
8 | ScheduledThreadPoolExecutor under the hood. The name is
9 | to make the parallel with UNIX's CRON a bit more evident.
10 |
11 | ## Usage
12 |
13 | TRON exposes very few functions, here is a small example:
14 |
15 | (ns sandbox
16 | (:require [tr.on :as tron]))
17 |
18 | (defn- periodic [] (println "periodic"))
19 | (defn- ponctual [] (println "ponctual"))
20 |
21 | ;; Run the fonction 10 seconds from now
22 | (tron/once ponctual 10000)
23 |
24 | ;; Run the periodic function every second
25 | ;; after the last call
26 | (tron/periodically :foo periodic 1000)
27 |
28 | ;; Run the periodic function every 10 second
29 | (tron/fixed-periodically :foo periodic 10000)
30 |
31 | ;; Cancel the periodic run 5 seconds from now
32 | (tron/once #(tron/cancel :foo) 5000)
33 |
34 | ;; Execute the followin expressions periodically
35 | (tron/do-periodically 5000
36 | (println "hello"))
37 |
38 | ## Installation
39 |
40 | The easiest way to use TRON in your own projects is via Leiningen.
41 | Add the following dependency to your project.clj file:
42 |
43 | [spootnik/tron "0.5.4"]
44 |
45 | If you would rather use maven, you need to specify the clojars
46 | repository dependency and import the tron artifact
47 |
48 |
49 | clojars.org
50 | http://clojars.org/repo
51 |
52 |
53 |
54 | spootnik
55 | tron
56 | 0.5.4
57 |
58 |
59 | ## License
60 |
61 | Copyright (C) 2011 Pierre-Yves Ritschard
62 |
63 | Distributed under the MIT License
64 |
65 | Permission to use, copy, modify, and distribute this software for any
66 | purpose with or without fee is hereby granted, provided that the above
67 | copyright notice and this permission notice appear in all copies.
68 |
69 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
70 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
71 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
72 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
73 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
74 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
75 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
76 |
--------------------------------------------------------------------------------
/src/tr/on.clj:
--------------------------------------------------------------------------------
1 | (ns tr.on
2 | "TRON: Task Run ON
3 |
4 | Simple library to schedule jobs on a Java ScheduledThreadPoolExecutor.
5 | Jobs can be scheduled for recurrent execution or for single-time runs.
6 | Jobs can have nicknames to be later decomissioned."
7 | (:import (java.util.concurrent ScheduledThreadPoolExecutor TimeUnit)))
8 |
9 | (defonce
10 | ^{:private true
11 | :doc "Number of threads for the scheduler."}
12 | poolsize (atom 1))
13 |
14 | (defonce
15 | ^{:private true
16 | :doc "Thread pool for the scheduler."}
17 | pool (atom nil))
18 |
19 | (defonce
20 | ^{:private true
21 | :doc "Running tasks on the scheduler."}
22 | tasks (atom {}))
23 |
24 | (defonce
25 | ^{:private true
26 | :doc "Shortcut for milliseconds."}
27 | usecs TimeUnit/MILLISECONDS)
28 |
29 | (defn- get-pool
30 | "Initiate a thread-pool for periodic tasks."
31 | []
32 | (swap! pool #(or % (ScheduledThreadPoolExecutor. @poolsize))))
33 |
34 | (defn periodically
35 | "Schedule a function for periodic execution.
36 | There are four different calling modes and three
37 | arities to this function:
38 |
39 | * `nickname f init delay`: provide a nickname to the task
40 | for later removal. the task will be executed after an
41 | initial delay and will recur every delay milliseconds.
42 | * `nickname f delay`: execute the same steps, but launch
43 | the first occurence right away.
44 | * `f init delay`: do not provide a nickname for this tasks
45 | * `f delay`: do not provide a nickname and start the first
46 | occurence right away."
47 | ([nickname f init delay]
48 | (let [task (.scheduleWithFixedDelay (get-pool) f init delay usecs)]
49 | (swap! tasks assoc nickname task)))
50 | ([arg1 arg2 arg3]
51 | (if (= (class arg1) clojure.lang.Keyword)
52 | (let [nickname arg1, f arg2, delay arg3]
53 | (periodically nickname f 0 delay))
54 | (let [f arg1, init arg2, delay arg3]
55 | (.scheduleWithFixedDelay (get-pool) f init delay usecs))))
56 | ([f delay]
57 | (periodically f 0 delay)))
58 |
59 | (defn fixed-periodically
60 | "Schedule a function for fixed periodic execution.
61 | There are four different calling modes and three
62 | arities to this function:
63 |
64 | * `nickname f init delay`: provide a nickname to the task
65 | for later removal. the task will be executed after an
66 | initial delay and will recur every delay milliseconds.
67 | * `nickname f delay`: execute the same steps, but launch
68 | the first occurence right away.
69 | * `f init delay`: do not provide a nickname for this tasks
70 | * `f delay`: do not provide a nickname and start the first
71 | occurence right away."
72 | ([nickname f init delay]
73 | (let [task (.scheduleAtFixedRate (get-pool) f init delay usecs)]
74 | (swap! tasks assoc nickname task)))
75 | ([arg1 arg2 arg3]
76 | (if (= (class arg1) clojure.lang.Keyword)
77 | (let [nickname arg1, f arg2, delay arg3]
78 | (periodically nickname f 0 delay))
79 | (let [f arg1, init arg2, delay arg3]
80 | (.scheduleAtFixedRate (get-pool) f init delay usecs))))
81 | ([f delay]
82 | (fixed-periodically f 0 delay)))
83 |
84 | (defmacro do-periodically
85 | "Wrap expressions in a function and execute them at the
86 | given interval"
87 | [delay & exprs]
88 | `(periodically (fn [] (do ~@exprs)) ~delay))
89 |
90 | (defn once
91 | "Schedule a function for one-time execution. Optionnaly
92 | provide a nickname for removal."
93 | ([nickname f delay]
94 | (let [cb (fn [] (f) (swap! tasks dissoc nickname))
95 | task (.schedule (get-pool) cb (long delay) usecs)]
96 | (swap! tasks assoc nickname task)))
97 | ([f delay]
98 | (.schedule (get-pool) f (long delay) usecs)))
99 |
100 | (defn shutdown
101 | "Terminate all scheduled tasks."
102 | []
103 | (swap! pool (fn [p] (if p (.shutdown p)) nil)))
104 |
105 | (defn cancel
106 | "Remove a task from the scheduled thread pool."
107 | [nickname]
108 | (when-let [task (@tasks nickname)]
109 | (swap! tasks dissoc nickname)
110 | (doto (get-pool)
111 | (.remove task))))
112 |
113 | (defn init
114 | "Set the number of periodic tasks which can be executed simultaneously."
115 | ([number]
116 | (shutdown)
117 | (swap! poolsize (fn [_] number)))
118 | ([]
119 | (init 1)))
120 |
--------------------------------------------------------------------------------