minuteman 1.0.3 → 2.0.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gems +3 -0
- data/.travis.yml +4 -3
- data/ORIGIN.md +21 -0
- data/README.md +115 -122
- data/Rakefile +3 -3
- data/SPEC.md +21 -0
- data/lib/minuteman.rb +88 -122
- data/lib/minuteman/analyzable.rb +96 -0
- data/lib/minuteman/analyzer.rb +21 -0
- data/lib/minuteman/configuration.rb +25 -0
- data/lib/minuteman/counter.rb +21 -0
- data/lib/minuteman/event.rb +12 -0
- data/lib/minuteman/lua/operations.lua +37 -0
- data/lib/minuteman/model.rb +36 -0
- data/lib/minuteman/result.rb +12 -0
- data/lib/minuteman/trigger.rb +4 -0
- data/lib/minuteman/user.rb +38 -0
- data/minuteman.gemspec +4 -5
- data/test/helper.rb +2 -0
- data/test/minuteman_bench.rb +72 -0
- data/test/minuteman_test.rb +204 -0
- metadata +44 -73
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -30
- data/lib/minuteman/bit_operations.rb +0 -97
- data/lib/minuteman/bit_operations/data.rb +0 -33
- data/lib/minuteman/bit_operations/operation.rb +0 -115
- data/lib/minuteman/bit_operations/plain.rb +0 -34
- data/lib/minuteman/bit_operations/result.rb +0 -15
- data/lib/minuteman/bit_operations/with_data.rb +0 -56
- data/lib/minuteman/keys_methods.rb +0 -23
- data/lib/minuteman/time_events.rb +0 -18
- data/lib/minuteman/time_span.rb +0 -36
- data/lib/minuteman/time_spans.rb +0 -7
- data/lib/minuteman/time_spans/day.rb +0 -17
- data/lib/minuteman/time_spans/hour.rb +0 -19
- data/lib/minuteman/time_spans/minute.rb +0 -19
- data/lib/minuteman/time_spans/month.rb +0 -17
- data/lib/minuteman/time_spans/week.rb +0 -18
- data/lib/minuteman/time_spans/year.rb +0 -17
- data/test/bench/minuteman_bench.rb +0 -37
- data/test/test_helper.rb +0 -9
- data/test/unit/minuteman_test.rb +0 -225
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 33273982b184b97986adee038d64bc71a5ebf868
|
4
|
+
data.tar.gz: 1787e29f6314d78e1967140a1194692b58fc678c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8e3d61fa6e931eceb2935d14ca8d734494e945e04d7a8676565e8c1c5e47454cfffdc336d71724e9c05ccfa2ac17e4f79fe69c4d4054bb1223988653a63c9d2a
|
7
|
+
data.tar.gz: 4925693e4ed12b00efe943693c0940296eb6c7d762e5a8697be551381ce0711b1feee081e778867f7a3c1d24db99c914c3a13da7cd0b9f69acb77ea9f3af9119
|
data/.gems
ADDED
data/.travis.yml
CHANGED
data/ORIGIN.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Origin
|
2
|
+
|
3
|
+
_Freenode - #cuba.rb - 2012/10/30 15:20 UYT_
|
4
|
+
|
5
|
+
> **conanbatt:** anyone here knows some good web app metrics tool ?
|
6
|
+
|
7
|
+
> **conanbatt:** i use google analytics for the page itself, and its good, but for the webapp its really not useful
|
8
|
+
|
9
|
+
> **tizoc: conanbatt:** http://amix.dk/blog/post/19714 you can port this (if an equivalent doesn't exist already)
|
10
|
+
|
11
|
+
> **conanbatt:** the metrics link is excellent but its python and released 5 days ago lol
|
12
|
+
|
13
|
+
> **elcuervo: tizoc:** the idea it's awesome
|
14
|
+
|
15
|
+
> **elcuervo:** interesting...
|
16
|
+
|
17
|
+
## Inspiration
|
18
|
+
|
19
|
+
* http://blog.getspool.com/2011/11/29/fast-easy-realtime-metrics-using-redis-bitmaps/
|
20
|
+
* http://amix.dk/blog/post/19714
|
21
|
+
* http://en.wikipedia.org/wiki/Bit_array
|
data/README.md
CHANGED
@@ -2,172 +2,165 @@
|
|
2
2
|
|
3
3
|
# Minuteman
|
4
4
|
[](https://codeclimate.com/github/elcuervo/minuteman)
|
5
|
-
[](https://travis-ci.org/elcuervo/minuteman)
|
6
5
|
|
7
|
-
|
6
|
+
[](https://travis-ci.org/elcuervo/minuteman)
|
7
|
+
|
8
|
+
> Minutemen were members of teams from Massachusetts that were well-prepared
|
8
9
|
militia companies of select men from the American colonial partisan militia
|
9
10
|
during the American Revolutionary War. _They provided a highly mobile, rapidly
|
10
11
|
deployed force that allowed the colonies to respond immediately to war threats,
|
11
12
|
hence the name._
|
12
13
|
|
13
|
-
## Origin
|
14
|
-
Freenode - #cuba.rb - 2012/10/30 15:20 UYT
|
15
|
-
|
16
|
-
**conanbatt:** anyone here knows some good web app metrics tool ?
|
17
|
-
|
18
|
-
**conanbatt:** i use google analytics for the page itself, and its good, but for the webapp its really not useful
|
19
|
-
|
20
|
-
**tizoc: conanbatt:** http://amix.dk/blog/post/19714 you can port this (if an equivalent doesn't exist already)
|
21
|
-
|
22
|
-
**conanbatt:** the metrics link is excellent but its python and released 5 days ago lol
|
23
|
-
|
24
|
-
**elcuervo: tizoc:** the idea it's awesome
|
25
|
-
|
26
|
-
**elcuervo:** interesting...
|
27
|
-
|
28
|
-
|
29
|
-
## Inspiration
|
30
|
-
|
31
|
-
* http://blog.getspool.com/2011/11/29/fast-easy-realtime-metrics-using-redis-bitmaps/
|
32
|
-
* http://amix.dk/blog/post/19714
|
33
|
-
* http://en.wikipedia.org/wiki/Bit_array
|
34
|
-
|
35
14
|
## Installation
|
36
15
|
|
37
|
-
### Important!
|
38
|
-
|
39
|
-
Depends on Redis 2.6 for the `bitop` operation. You can install it using:
|
40
|
-
|
41
|
-
```bash
|
42
|
-
brew install redis
|
43
|
-
```
|
44
|
-
|
45
|
-
or upgrading your current version:
|
46
|
-
|
47
|
-
```bash
|
48
|
-
brew upgrade redis
|
49
|
-
```
|
50
|
-
|
51
|
-
And then install the gem
|
52
|
-
|
53
16
|
```bash
|
54
17
|
gem install minuteman
|
55
18
|
```
|
56
19
|
|
57
|
-
|
58
|
-
|
59
|
-
Currently Minutemen supports two options `:silent (default: false)` and `:redis
|
60
|
-
(default: {})`
|
20
|
+
### Configuration
|
61
21
|
|
62
|
-
|
22
|
+
Configuration exists within the `config` block:
|
63
23
|
|
64
|
-
|
24
|
+
```ruby
|
25
|
+
Minuteman.configure do |config|
|
26
|
+
# You need to use Redic to define a new Redis connection
|
27
|
+
config.redis = Redic.new("redis://127.0.0.1:6379/1")
|
28
|
+
|
29
|
+
# The prefix affects operations
|
30
|
+
config.prefix = "Tomato"
|
31
|
+
|
32
|
+
# The patterns is what Minuteman uses for the tracking/counting and the
|
33
|
+
# different analyzers
|
34
|
+
config.patterns = {
|
35
|
+
dia: -> (time) { time.strftime("%Y-%m-%d") }
|
36
|
+
}
|
37
|
+
end
|
38
|
+
```
|
65
39
|
|
66
|
-
|
67
|
-
day]` will only track events on that timespans. Ignoring the rest
|
40
|
+
## Tracking
|
68
41
|
|
69
|
-
|
70
|
-
connection already established (`Redis::Namespace` works as well).
|
42
|
+
Tracking is the most basic scenario for Minuteman:
|
71
43
|
|
72
44
|
```ruby
|
73
|
-
|
45
|
+
# This will create the "landing:new" event in all the defined patterns and since
|
46
|
+
# there is no user here it will create an annonymous one.
|
47
|
+
# This user only exists in the Minuteman context.
|
48
|
+
user = Minuteman.track("landing:new")
|
74
49
|
|
75
|
-
#
|
76
|
-
|
50
|
+
# The id it's an internal representation, not useful for you
|
51
|
+
user.id # => "1"
|
77
52
|
|
78
|
-
#
|
79
|
-
|
53
|
+
# This is the unique id. With this you can have an identifier for the user
|
54
|
+
user.uid # => "787c8770-0ac2-4654-9fa4-e57d152fa341"
|
80
55
|
|
81
|
-
#
|
82
|
-
|
83
|
-
analytics.track("login:successful", other_user.id)
|
56
|
+
# You can use the `user` to keep tracking things:
|
57
|
+
user.track("register:page")
|
84
58
|
|
85
|
-
#
|
86
|
-
|
59
|
+
# Or use it as an argument
|
60
|
+
Minuteman.track("help:page", user)
|
87
61
|
|
88
|
-
#
|
89
|
-
|
62
|
+
# Or track several users at once
|
63
|
+
Minuteman.track("help:page", [user1, user2, user3])
|
90
64
|
|
91
|
-
#
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
analytics.day("login:successful")
|
96
|
-
analytics.hour("login:successful")
|
97
|
-
analytics.minute("login:successful")
|
98
|
-
|
99
|
-
# Lists all the tracked events
|
100
|
-
analytics.events
|
101
|
-
#=> ["login:successful", "programming:login:ruby"]
|
65
|
+
# By default all the tracking and counting events are triggered with `Time.now.utc`
|
66
|
+
# but you can change that as well:
|
67
|
+
Minuteman.track("setup:account", user, Time.new(2010, 2, 10))
|
68
|
+
```
|
102
69
|
|
103
|
-
|
104
|
-
today_events.length
|
105
|
-
#=> 2
|
70
|
+
## Analysis
|
106
71
|
|
107
|
-
|
108
|
-
today_events.include?(user.id)
|
109
|
-
#=> true
|
110
|
-
today_events.include?(admin.id)
|
111
|
-
#=> false
|
72
|
+
There is a powerful engine behind all the operations which is Redis + Lua <3
|
112
73
|
|
113
|
-
|
114
|
-
|
115
|
-
|
74
|
+
```ruby
|
75
|
+
# The analysis of information relies on `Minuteman.patterns` and if you don't
|
76
|
+
# change it you'll get acess to `year`, `month`, `day`, `hour`, `minute`.
|
77
|
+
# To get information about `register:page` for today:
|
78
|
+
Minuteman.analyze("register:page").day
|
79
|
+
|
80
|
+
# You can always pass a `Time` instance to set the time you need information.
|
81
|
+
Minuteman.analyze("register:page").day(Time.new(2004, 2, 12))
|
82
|
+
|
83
|
+
# You also have a shorthand for analysis:
|
84
|
+
register_page_month = Minuteman("register:page").month
|
85
|
+
|
86
|
+
# And the power of Minuteman relies on the operations you can do with that.
|
87
|
+
# Counting the amount:
|
88
|
+
register_page_month.count # => 10
|
89
|
+
|
90
|
+
# Or knowing if a user is included in that set:
|
91
|
+
register_page_month.include?(User[42]) # => true
|
92
|
+
|
93
|
+
# But the most important part is the ability to do bit operations on that:
|
94
|
+
# You can intersect sets using bitwise AND(`&`), OR(`|`), NOT(`~`, `-`) and XOR(`^`).
|
95
|
+
# Also you can use plus(`+`) and minus(`-`) operations.
|
96
|
+
# In this example we'll get all the users that accessed our site via a promo
|
97
|
+
# invite but didn't buy anything
|
98
|
+
(
|
99
|
+
Minuteman("promo:email").day & Minuteman("promo:google").day
|
100
|
+
) - Minuteman("buy:success").day
|
116
101
|
```
|
117
102
|
|
118
|
-
##
|
103
|
+
## Counting
|
119
104
|
|
120
|
-
|
121
|
-
Also you can use plus(`+`) and minus(`-`) operations.
|
105
|
+
Since Minuteman 2.0 there's the possibility to have counters.
|
122
106
|
|
123
107
|
```ruby
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
~set1 \
|
131
|
-
|==> This are the same
|
132
|
-
-set1 /
|
133
|
-
```
|
108
|
+
# Counting works in a very similar way to tracking but with some important
|
109
|
+
# differences. Trackings are idempotent unlike countings and they do not provide
|
110
|
+
# operations between sets... you can use plain ruby for that.
|
111
|
+
# This will add 1 to the `hits:page` counter:
|
112
|
+
Minuteman.add("hits:page")
|
134
113
|
|
135
|
-
|
114
|
+
# You can also pass a `Time` instance to define when this tracking ocurred:
|
115
|
+
Minuteman.add("hits:page", Time.new(2012, 20, 01))
|
136
116
|
|
137
|
-
|
117
|
+
# And you can also send users to also count the times that given user did that
|
118
|
+
# event
|
119
|
+
Minuteman.add("hits:page", Time.new(2012, 20, 01), user)
|
138
120
|
|
139
|
-
You
|
140
|
-
|
121
|
+
# You can access counting information similar to tracking:
|
122
|
+
Minuteman.count("hits:page").day.count # => 201
|
141
123
|
|
142
|
-
|
143
|
-
|
144
|
-
payed_from_miami = paid & User.find_all_by_state("MIA").map(&:id)
|
145
|
-
payed_from_miami.size
|
146
|
-
#=> 43
|
147
|
-
payed_users_from_miami = payed_from_miami.map { |id| User.find(id) }
|
124
|
+
# Or with a shorthand:
|
125
|
+
Counterman("hits:page").day.count # => 201
|
148
126
|
```
|
149
127
|
|
150
|
-
|
128
|
+
## Users
|
151
129
|
|
152
|
-
|
130
|
+
Minuteman 2.0 adds the concept of users which can be annonymous or have a
|
131
|
+
relation with your own database.
|
153
132
|
|
154
133
|
```ruby
|
155
|
-
|
156
|
-
|
134
|
+
# This will create an annonymous user
|
135
|
+
user = Minuteman::User.create
|
157
136
|
|
158
|
-
|
159
|
-
|
137
|
+
# Users are just a part of Minuteman and do not interfere with your own.
|
138
|
+
# They do have some properties like a unique identifier you can use to find it
|
139
|
+
# in the future
|
140
|
+
user.uid # => "787c8770-0ac2-4654-9fa4-e57d152fa341"
|
160
141
|
|
161
|
-
#
|
162
|
-
|
163
|
-
|
142
|
+
# User lookup works like this:
|
143
|
+
# And you can use that unique identifier as a key in a cookie to see what your
|
144
|
+
# uses do when no one is looking
|
145
|
+
Minuteman::User['787c8770-0ac2-4654-9fa4-e57d152fa341']
|
164
146
|
|
165
|
-
|
147
|
+
# But since the point is to be able to get tied to your data you can promote a
|
148
|
+
# user, from anonymous to "real"
|
149
|
+
user.promote(123)
|
166
150
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
151
|
+
# Lookups also work with promoted ids
|
152
|
+
Minuteman::User["123"]
|
153
|
+
|
154
|
+
# Having a user you can do all the same operations minus the hussle.
|
155
|
+
# Like tracking:
|
156
|
+
user.track("user:login")
|
157
|
+
|
158
|
+
# or adding:
|
159
|
+
user.add("failed:login")
|
160
|
+
|
161
|
+
# or counting
|
162
|
+
user.count("failed:login").month.count # => 23
|
171
163
|
|
172
|
-
|
164
|
+
# But also the counted events go to the big picture
|
165
|
+
Counterman("failed:login").month.count # => 512
|
173
166
|
```
|
data/Rakefile
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
require "rake/testtask"
|
2
2
|
|
3
|
-
Rake::TestTask.new("
|
3
|
+
Rake::TestTask.new("test") do |t|
|
4
|
+
t.libs << "test"
|
4
5
|
t.pattern = "test/**/*_test.rb"
|
5
6
|
end
|
6
7
|
|
7
8
|
Rake::TestTask.new("bench") do |t|
|
8
|
-
t.pattern = "test
|
9
|
+
t.pattern = "test/**/*_bench.rb"
|
9
10
|
end
|
10
11
|
|
11
12
|
task :default => [:test]
|
12
13
|
task :all => [:test, :bench]
|
13
|
-
task :test => [:spec]
|
data/SPEC.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
```ruby
|
2
|
+
# Track an event
|
3
|
+
minuteman_user = Minuteman.track("login:successfull")
|
4
|
+
minuteman_user.promote(user.id)
|
5
|
+
|
6
|
+
# Trigger an event in the pipeline
|
7
|
+
Minuteman.trigger("event:name")
|
8
|
+
|
9
|
+
# Gets an event analyzer
|
10
|
+
analyzer = Minuteman.analyze("event:name")
|
11
|
+
# Counts unique users in that given time
|
12
|
+
analyze.day(Time.now.utc)
|
13
|
+
|
14
|
+
Minuteman("event:name").day | Minuteman("event2:name).day
|
15
|
+
```
|
16
|
+
|
17
|
+
Caching:
|
18
|
+
Cache ids in events:
|
19
|
+
|
20
|
+
Minuteman::Operation:50:AND:20, Minuteman::Operation:50:OR:20
|
21
|
+
Minuteman::Operation:(50:AND:20):AND:14
|
data/lib/minuteman.rb
CHANGED
@@ -1,151 +1,117 @@
|
|
1
|
-
require
|
2
|
-
require "time"
|
3
|
-
require "forwardable"
|
4
|
-
require "minuteman/time_events"
|
1
|
+
require 'redic'
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
extend Forwardable
|
3
|
+
module Minuteman
|
4
|
+
LUA_CACHE = Hash.new { |h, k| h[k] = Hash.new }
|
5
|
+
LUA_OPERATIONS = File.expand_path("../minuteman/lua/operations.lua", __FILE__)
|
10
6
|
|
11
7
|
class << self
|
12
|
-
|
13
|
-
|
14
|
-
# Public: Prevents a fatal error if the options are set to silent
|
15
|
-
#
|
16
|
-
def safe(&block)
|
17
|
-
yield if block
|
18
|
-
rescue Redis::BaseError => e
|
19
|
-
raise e unless options[:silent]
|
8
|
+
def config
|
9
|
+
@_configuration ||= Configuration.new
|
20
10
|
end
|
21
|
-
end
|
22
|
-
|
23
|
-
PREFIX = "minuteman"
|
24
11
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
#
|
29
|
-
# options - An options hash to change how Minuteman behaves
|
30
|
-
#
|
31
|
-
def initialize(options = {})
|
32
|
-
redis_options = options.delete(:redis) || {}
|
12
|
+
def configure
|
13
|
+
yield(config)
|
14
|
+
end
|
33
15
|
|
34
|
-
|
35
|
-
|
16
|
+
def prefix
|
17
|
+
config.prefix
|
18
|
+
end
|
36
19
|
|
37
|
-
|
38
|
-
|
39
|
-
|
20
|
+
def patterns
|
21
|
+
config.patterns
|
22
|
+
end
|
40
23
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
# ids - The ids to be tracked
|
45
|
-
#
|
46
|
-
# Examples
|
47
|
-
#
|
48
|
-
# analytics = Minuteman.new
|
49
|
-
# analytics.track("login", 1)
|
50
|
-
# analytics.track("login", [2, 3, 4])
|
51
|
-
#
|
52
|
-
def track(event_name, ids, time = Time.now.utc)
|
53
|
-
event_time = time.kind_of?(Time) ? time : Time.parse(time.to_s)
|
54
|
-
time_events = TimeEvents.start(@time_spans, event_name, event_time)
|
55
|
-
|
56
|
-
track_events(time_events, Array(ids))
|
57
|
-
end
|
24
|
+
def time_spans
|
25
|
+
@_time_spans = patterns.keys
|
26
|
+
end
|
58
27
|
|
59
|
-
|
60
|
-
|
61
|
-
def events
|
62
|
-
keys = safe { redis.keys([PREFIX, "*", "????"].join("_")) }
|
63
|
-
keys.map { |key| key.split("_")[1] }
|
64
|
-
end
|
28
|
+
def track(action, users = nil, time = Time.now.utc)
|
29
|
+
users = Minuteman::User.create if users.nil?
|
65
30
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
31
|
+
Array(users).each do |user|
|
32
|
+
process do
|
33
|
+
time_spans.each do |time_span|
|
34
|
+
event = Minuteman::Event.find_or_create(
|
35
|
+
type: action,
|
36
|
+
time: patterns[time_span].call(time)
|
37
|
+
)
|
71
38
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
safe { redis.del(keys) } if keys.any?
|
77
|
-
end
|
39
|
+
event.setbit(user.id)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
78
43
|
|
79
|
-
|
80
|
-
|
81
|
-
def reset_all
|
82
|
-
keys = safe { redis.keys([PREFIX, "*"].join("_")) }
|
83
|
-
safe { redis.del(keys) } if keys.any?
|
84
|
-
end
|
44
|
+
users
|
45
|
+
end
|
85
46
|
|
86
|
-
|
47
|
+
def add(action, time = Time.now.utc, users = [])
|
48
|
+
time_spans.each do |time_span|
|
49
|
+
process do
|
50
|
+
counter = Minuteman::Counter.create({
|
51
|
+
type: action,
|
52
|
+
time: patterns[time_span].call(time)
|
53
|
+
})
|
87
54
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
#
|
92
|
-
def generate_spans(spans)
|
93
|
-
spans.map do |method_name|
|
94
|
-
constructor = self.class.const_get(method_name.capitalize)
|
55
|
+
counter.incr
|
56
|
+
end
|
57
|
+
end
|
95
58
|
|
96
|
-
|
97
|
-
|
98
|
-
|
59
|
+
Array(users).each do |user|
|
60
|
+
time_spans.each do |time_span|
|
61
|
+
counter = Minuteman::Counter::User.create({
|
62
|
+
user_id: user.id,
|
63
|
+
type: action,
|
64
|
+
time: patterns[time_span].call(time)
|
65
|
+
})
|
99
66
|
|
100
|
-
|
67
|
+
counter.incr
|
68
|
+
end
|
101
69
|
end
|
70
|
+
end
|
102
71
|
|
103
|
-
|
72
|
+
def analyze(action)
|
73
|
+
analyzers_cache[action]
|
104
74
|
end
|
105
|
-
end
|
106
75
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
{ cache: true, silent: false }
|
111
|
-
end
|
76
|
+
def count(action)
|
77
|
+
counters_cache[action]
|
78
|
+
end
|
112
79
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
object
|
122
|
-
else
|
123
|
-
Redis.new(object)
|
80
|
+
private
|
81
|
+
|
82
|
+
def process(&block)
|
83
|
+
if !!config.parallel
|
84
|
+
Thread.current(&block)
|
85
|
+
else
|
86
|
+
block.call
|
87
|
+
end
|
124
88
|
end
|
125
|
-
end
|
126
89
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
# ids: The ids to be tracked
|
131
|
-
#
|
132
|
-
def track_events(time_events, ids)
|
133
|
-
safe_multi do
|
134
|
-
time_events.each do |event|
|
135
|
-
ids.each { |id| safe { redis.setbit(event.key, id, 1) } }
|
90
|
+
def analyzers_cache
|
91
|
+
@_analyzers_cache ||= Hash.new do |h,k|
|
92
|
+
h[k] = Minuteman::Analyzer.new(k)
|
136
93
|
end
|
137
94
|
end
|
138
|
-
end
|
139
95
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
96
|
+
def counters_cache
|
97
|
+
@_counters_cache ||= Hash.new do |h,k|
|
98
|
+
h[k] = Minuteman::Analyzer.new(k, Minuteman::Counter)
|
99
|
+
end
|
100
|
+
end
|
144
101
|
end
|
102
|
+
end
|
145
103
|
|
146
|
-
|
147
|
-
|
148
|
-
def operations_cache_key_prefix
|
149
|
-
[ PREFIX, Minuteman::KeysMethods::BIT_OPERATION_PREFIX ].join("_")
|
150
|
-
end
|
104
|
+
def Minuteman(action)
|
105
|
+
Minuteman.analyze(action)
|
151
106
|
end
|
107
|
+
|
108
|
+
def Counterman(action)
|
109
|
+
Minuteman.count(action)
|
110
|
+
end
|
111
|
+
|
112
|
+
require 'minuteman/user'
|
113
|
+
require 'minuteman/event'
|
114
|
+
require 'minuteman/counter'
|
115
|
+
require 'minuteman/result'
|
116
|
+
require 'minuteman/analyzer'
|
117
|
+
require 'minuteman/configuration'
|