summaryrefslogtreecommitdiff
path: root/src/redisload.clj
blob: 07c127552a849704ede6d9343a4e0e6e748dc255 (plain)
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
(ns redisload
  (:use clojure.contrib.sql
        clojure.contrib.str-utils
        config
        datalayer
        utils)
  (:require redis))

(defn redis-days [n]
  (* 24 60 60))

(def tag-query "
SELECT
    u.nick as author,
    u.user_id as author_id,
    m.message_id as message_id,
    m.content as message_content,
    m.is_image as is_image,
    m.created_on as message_ts,
    r.key as room,
    r.admin_only as admin_only,
    t.created_on as tagged_on,
    u2.nick as tagger,
    u2.user_id as tagger_id
FROM users u, messages m, rooms r, tags t, users u2
WHERE
    u.user_id = m.user_id AND
    m.message_id = t.message_id AND
    r.room_id = m.room_id AND
    u2.user_id = t.user_id AND
    r.admin_only = false
")

(def tag-counter (ref 0))

(defn stream-tags [fs]
  (with-connection *db*
    (with-query-results rs [tag-query]
      (doseq [r rs]
        (if (:admin_only r)
          (println r))
        (dosync
         (ref-set tag-counter (inc @tag-counter)))
        (doseq [f fs]
          (f r))))))

(def hall-map (ref {}))
(def popular-map (ref {}))
(def score-map (ref {}))

(defn update-popular [r]
  (if (and (:is_image r) (not (:admin_only r)))
    (dosync
     (let [author    (:author r)
           msg-id    (:message_id r)
           user-map  (get @popular-map author {})
           msg-cnt   (get user-map msg-id 0)
           hall-cnt  (get @hall-map msg-id 0)
           usr-cnt   (get @score-map author 0)]
       (alter hall-map assoc msg-id (inc hall-cnt))
       (alter score-map assoc author (inc usr-cnt))
       (alter popular-map assoc author
              (assoc user-map msg-id (inc msg-cnt)))))))

(defn transmit-popular []
  (doseq [[nick msgs] @popular-map]
    (let [sorted-msgs (sort #(>= (second %1) (second %2)) msgs)
          userkey     (str "popular:" nick)]
      (redis/atomically
       (redis/del key)
       (doseq [[msg-id score] (take (* num-popular-dumps 2)
                                    sorted-msgs)]
         (redis/zadd userkey score msg-id)))))
  (println "cached popular data for" (count @popular-map) "users"))

(defn transmit-favscores []
  (redis/atomically
   (redis/del "favscores")
   (doseq [[nick score] @score-map]
     (redis/zadd "favscores" score (lower-case nick))))
  (println "cached favscores for " (count @score-map) "users"))

(defn transmit-hall []
  (let [scores (take (* 2 num-hall-dumps)
                     (sort #(>= (second %1) (second %2)) @hall-map))]
    (redis/atomically
     (redis/del "hall")
     (doseq [[msg-id score] scores]
       (redis/zadd "hall" score msg-id)))))
     

(println "streaming tags")
(stream-tags [update-popular])
(println (format "processed %s tags" @tag-counter))

(redis/with-server redis-server
  (transmit-favscores)
  (transmit-popular)
  (transmit-hall))