-
Notifications
You must be signed in to change notification settings - Fork 0
/
date.clj
53 lines (47 loc) · 1.64 KB
/
date.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
(ns iny.http.date
(:import [java.util
Date
TimeZone
Locale]
[java.text
SimpleDateFormat]
[java.util.concurrent
TimeUnit]
[java.util.concurrent.atomic
AtomicReference]
[io.netty.util
AsciiString]
[io.netty.util.concurrent
FastThreadLocal]
[io.netty.channel
ChannelHandlerContext]))
(defonce ^FastThreadLocal date-format (FastThreadLocal.))
(defonce ^FastThreadLocal date-value (FastThreadLocal.))
(defmacro ref-get-or-set [^FastThreadLocal ftl or-value]
`(if-let [^AtomicReference ref# (.get ~ftl)]
(.get ref#)
(let [new-ref# (AtomicReference. ~or-value)]
(.set ~ftl new-ref#)
(.get new-ref#))))
(defn ^SimpleDateFormat header-date-format
"SimpleDateFormat isn't thread-safe so it has to be made for each worker"
[]
(doto (SimpleDateFormat. "EEE, dd MMM yyyy HH:mm:ss z" Locale/ENGLISH)
(.setTimeZone (TimeZone/getTimeZone "GMT"))))
(defn formatted-header-date []
(let [^SimpleDateFormat format
(ref-get-or-set date-format (header-date-format))]
(AsciiString. (.format format (Date.)))))
(defn ^CharSequence date-header-value []
(ref-get-or-set date-value (formatted-header-date)))
(defn schedule-date-value-update
[^ChannelHandlerContext ctx]
(let [ref (AtomicReference. (formatted-header-date))]
; header date is accurate to seconds
; so have it update every second
(.set date-value ref)
(.scheduleAtFixedRate (.executor ctx)
#(.set ref (formatted-header-date))
1000
1000
TimeUnit/MILLISECONDS)))