prisma 0.1.2 → 0.2.0

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.
data/bin/prisma-web CHANGED
@@ -9,7 +9,6 @@ rescue LoadError
9
9
  end
10
10
  require 'prisma/server'
11
11
 
12
-
13
12
  Vegas::Runner.new(Prisma::Server, 'prisma-web') do |runner, opts, app|
14
13
  opts.on('-N NAMESPACE', "--namespace NAMESPACE", "set the Redis namespace") {|namespace|
15
14
  runner.logger.info "Using Redis namespace '#{namespace}'"
data/lib/prisma.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'rails/all'
2
2
  require 'redis-namespace'
3
+ require 'bitset'
3
4
 
4
5
  require 'prisma/group'
5
6
  require 'prisma/railtie'
@@ -36,7 +37,7 @@ module Prisma
36
37
  # Configure prisma. Example usage:
37
38
  # Prisma.setup do |config|
38
39
  # config.group :active_api_clients { |controller| controller.current_client.id }
39
- # config.redis = Redis.new(:db => 1)
40
+ # config.redis = Redis.new(db: 1)
40
41
  # config.redis_namespace = 'stats'
41
42
  # config.redis_expiration_duration = 2.days
42
43
  # end
@@ -47,15 +48,15 @@ module Prisma
47
48
 
48
49
  # Configures a group. The instance of the current {http://api.rubyonrails.org/classes/ActionController/Base.html ActionController} is being passed as an argument into the block.
49
50
  # As an example, tracking daily active users could be as simple as:
50
- # Prisma.setup |config|
51
+ # Prisma.setup do |config|
51
52
  # config.group :logged_in { |controller| controller.current_user.id }
52
53
  # end
53
54
  #
54
55
  # @param [Symbol/String] name for identifying the group, it is used as part of the redis key.
55
- # @param [String] description for describing the gorup, it is used in the admin interface.
56
+ # @param [Hash] options where +:type+ is either +:counter+ (default) or +:bitmap+, and where +:description+ is an optional description (used in the admin UI)
56
57
  # @param [Block] block returning a String (or a meaningful +.to_s output+) which is used for identifying a counter inside a group, Prisma doesn't count a request if block returns +nil+ or +false+
57
- def self.group(name, description=nil, &block)
58
- @@groups[name] = Group.new(:name => name, :description => description, :block => block)
58
+ def self.group(name, options={}, &block)
59
+ @@groups[name] = Group.new(options.merge(name: name, block: block))
59
60
  end
60
61
 
61
62
  # Returns a default or configured +Redis+ instance wrapped in a +Redis::Namespace+
@@ -65,14 +66,14 @@ module Prisma
65
66
  case @@redis
66
67
  when String
67
68
  if @@redis =~ /redis\:\/\//
68
- redis = Redis.connect(:url => @@redis, :thread_safe => true)
69
+ redis = Redis.connect(url: @@redis, thread_safe: true)
69
70
  else
70
71
  host, port, db = @@redis.split(':')
71
- redis = Redis.new(:host => host, :port => port, :thread_safe => true, :db => db)
72
+ redis = Redis.new(host: host, port: port, thread_safe: true, db: db)
72
73
  end
73
- Redis::Namespace.new(redis_namespace, :redis => redis)
74
+ Redis::Namespace.new(redis_namespace, redis: redis)
74
75
  else
75
- Redis::Namespace.new(redis_namespace, :redis => @@redis)
76
+ Redis::Namespace.new(redis_namespace, redis: @@redis)
76
77
  end
77
78
  end.call
78
79
  end
@@ -101,7 +102,9 @@ module Prisma
101
102
  def self.store_configuration
102
103
  redis.del 'configuration'
103
104
  groups.values.each do |group|
104
- redis.hset 'configuration', group.name, group.description
105
+ redis.rpush 'configuration', group.name
106
+ redis.set "configuration:description:#{group.name}", group.description if group.description
107
+ redis.set "configuration:type:#{group.name}", group.type
105
108
  end
106
109
  end
107
110
  end
data/lib/prisma/filter.rb CHANGED
@@ -13,8 +13,16 @@ module Prisma
13
13
  Prisma.groups.each do |name, group|
14
14
  redis_key = Prisma.redis_key(name)
15
15
  value = group.block.call(self)
16
- Prisma.redis.hincrby redis_key, value, 1 if value
17
16
 
17
+ case group.type
18
+ when :bitmap
19
+ next if value.to_i == 0
20
+ setbit_key = Redis::Namespace::COMMANDS.include?('setbit') ? redis_key : "#{Prisma.redis_namespace}:#{redis_key}"
21
+ Prisma.redis.setbit setbit_key, value.to_i, 1
22
+ when :counter
23
+ next unless value
24
+ Prisma.redis.incr redis_key
25
+ end
18
26
  Prisma.redis.expire redis_key, Prisma.redis_expire if Prisma.redis_expiration_duration
19
27
  end
20
28
  end
data/lib/prisma/group.rb CHANGED
@@ -4,15 +4,24 @@ module Prisma
4
4
  # The name of the group, typically a +Symbol+
5
5
  attr_accessor :name
6
6
 
7
+ # The type of the group, +:counter+ or +:bitmap+
8
+ attr_accessor :type
9
+
7
10
  # The description of the group, typcially a +String+
8
11
  attr_accessor :description
9
12
 
10
- # The block which evaluates to a +String+ or meaningful +Object.to_s+
13
+ # Block which gets called to evaluate if request should be counted and depending on the type how the request should be counted.
14
+ # When +type+ is +:counter+ the request is getting counted as long as the return value is not nil or false.
15
+ # When +type+ is +:bitmap+ the request is getting counted as long as the return value is an integer.
11
16
  attr_accessor :block
12
17
 
13
18
  # Initialize +Group+ from a hash
14
19
  def initialize(options={})
20
+ options.reverse_merge!(type: :counter)
21
+ raise ArgumentError.new("Type #{options[:type].inspect} not allowed") unless [:counter, :bitmap].include? options[:type]
22
+
15
23
  self.name = options[:name]
24
+ self.type = options[:type]
16
25
  self.description = options[:description]
17
26
  self.block = options[:block]
18
27
  end
@@ -26,7 +35,15 @@ module Prisma
26
35
  range = range..range if range.is_a? Date
27
36
  data = {}
28
37
  range.each do |date|
29
- data[date] = Prisma.redis.hlen Prisma.redis_key(name, date)
38
+ case type
39
+ when :counter
40
+ data[date] = Prisma.redis.get(Prisma.redis_key(name, date)).to_i
41
+ when :bitmap
42
+ bitstring = Prisma.redis.get(Prisma.redis_key(name, date)) || ''
43
+ string = bitstring.unpack('b*').first
44
+ bitmap = Bitset.from_s(string)
45
+ data[date] = bitmap.cardinality
46
+ end
30
47
  end
31
48
  data
32
49
  end
data/lib/prisma/server.rb CHANGED
@@ -45,8 +45,10 @@ module Prisma
45
45
  private
46
46
 
47
47
  def groups
48
- Prisma.redis.hgetall('configuration').map do |name, description|
49
- Prisma::Group.new(:name => name, :description => description)
48
+ Prisma.redis.lrange('configuration', 0, -1).map do |name|
49
+ type = Prisma.redis.get("configuration:type:#{name}").to_sym
50
+ description = Prisma.redis.get("configuration:description:#{name}")
51
+ Prisma::Group.new(name: name, type: type, description: description)
50
52
  end
51
53
  end
52
54
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prisma
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-05 00:00:00.000000000 Z
12
+ date: 2012-07-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: 1.0.2
46
+ - !ruby/object:Gem::Dependency
47
+ name: redis
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 2.2.0
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.2.0
46
62
  - !ruby/object:Gem::Dependency
47
63
  name: sinatra
48
64
  requirement: !ruby/object:Gem::Requirement
@@ -75,6 +91,22 @@ dependencies:
75
91
  - - ~>
76
92
  - !ruby/object:Gem::Version
77
93
  version: 0.1.2
94
+ - !ruby/object:Gem::Dependency
95
+ name: bitset
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: 0.1.0
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: 0.1.0
78
110
  - !ruby/object:Gem::Dependency
79
111
  name: rspec-rails
80
112
  requirement: !ruby/object:Gem::Requirement
@@ -320,7 +352,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
320
352
  version: '0'
321
353
  segments:
322
354
  - 0
323
- hash: 4578263424559141618
355
+ hash: 2186605231112697474
324
356
  required_rubygems_version: !ruby/object:Gem::Requirement
325
357
  none: false
326
358
  requirements: