https://github.com/sunng87/rigui
Hierarchical Timing Wheels for Clojure and ClojureScript
https://github.com/sunng87/rigui
Last synced: 9 months ago
JSON representation
Hierarchical Timing Wheels for Clojure and ClojureScript
- Host: GitHub
- URL: https://github.com/sunng87/rigui
- Owner: sunng87
- License: epl-1.0
- Created: 2015-11-08T14:23:17.000Z (about 10 years ago)
- Default Branch: master
- Last Pushed: 2024-01-20T01:27:59.000Z (almost 2 years ago)
- Last Synced: 2025-03-27T09:11:19.824Z (10 months ago)
- Language: Clojure
- Homepage:
- Size: 87.9 KB
- Stars: 46
- Watchers: 3
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Ri Gui (日晷, Sundial)
[](https://github.com/sunng87/rigui/actions/workflows/clojure.yml)
[](https://clojars.org/rigui)
[](https://github.com/sunng87/rigui/blob/master/LICENSE)
Hierarchical Timing Wheels for Clojure and ClojureScript. This is a
general purpose timer implementation that scales. Its performance can
be tuned via parameters.
Timing wheels is designed for scenario of large scale task
scheduling. According to current [benchmark](#performance-comparison)
it provides way better accuracy for large amount of tasks emitted in
short range.

## Base Usage
Start a timer:
```clojure
(require '[rigui.core :refer [start later! every! stop cancel!]])
;; starting a timer with arguments:
;; tick size: 1ms
;; bucket per wheel: 8
;; handler function: some-handler
;; thread pool for running tasks: some-executor (for JVM only)
(def timer (start 1 8 some-handler some-executor))
```
Schedule some task/value for later:
```clojure
;; schedule some value :a with delay 1000ms
;; timer's handler function will be called with :a in 1000ms
(def task (later! timer :a 1000))
```
Note that values to scheduled within a tick will be delivered to
handler function at once, and executed on current thread.
The handler function will be called with task value as arguments when
the task expires. The run a custom task, you can start the timer as:
```clojure
(def timer (start 1 8 (fn [f] (f)) some-executor))
(later! timer #(println :a) 1000)
```
The schedule function returns a `promise`-like object, which maintains
the execution result of handler function and task value. `deref`,
blocking `deref` and `realized?` are supported.
Cancel a task:
```clojure
(cancel! timer task)
```
Schedule some task/value for a fixed interval. The value will be
delivered to handler function in fixed interval.
```clojure
(every! timer :a
1000 ;; initial delay
500 ;; interval
)
```
Stop the timer:
```clojure
;; calling stop on timer returns all the pending tasks
(stop timer)
```
Once a timer is stopped, it no longer accepts new task.
## Delayed Channel
This library also provides an experimental core.async channel that pop
the value after some delay.
```clojure
(require '[rigui.async :refer [delayed-chan delayed-value]])
(def c (delayed-chan))
;; the value will be available in 1000 milliseconds
(>!! c (delayed-value :a 1000))
;; blocked until 1000 milliseconds later
( 1, n counts from 1), that is
`tick * (bucket-count**(n-1))`. The larger `bucket-count` you set, the
more internal timers you will have. But in most case it's still less
than your task count significantly.
Let tick = 1, bucket-count = 8, the wheels could be visualized like:

A task with delay 5 will be put onto the first wheel, while a delay of
350 will be put onto the third.
*If you know good free software to draw this please kindly let me
know.*
## License
Copyright © 2015-2016 Ning Sun
Distributed under the Eclipse Public License either version 1.0 or (at
your option) any later version.