Class: Vanity::Adapters::RedisAdapter

Inherits:
AbstractAdapter show all
Defined in:
lib/vanity/adapters/redis_adapter.rb

Overview

Redis adapter.

Since:

  • 1.4.0

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ RedisAdapter

rubocop:todo Lint/MissingSuper

Since:

  • 1.4.0


32
33
34
35
36
37
# File 'lib/vanity/adapters/redis_adapter.rb', line 32

def initialize(options) # rubocop:todo Lint/MissingSuper
  @options = options.clone
  @options[:db] ||= @options[:database] || (@options[:path] && @options.delete(:path).split("/")[1].to_i)
  @options[:thread_safe] = true
  connect!
end

Instance Attribute Details

#redisObject (readonly)

Since:

  • 1.4.0


30
31
32
# File 'lib/vanity/adapters/redis_adapter.rb', line 30

def redis
  @redis
end

Instance Method Details

#ab_add_conversion(experiment, alternative, identity, count = 1, implicit = false) ⇒ Object

Since:

  • 1.4.0


196
197
198
199
200
201
202
203
204
205
206
# File 'lib/vanity/adapters/redis_adapter.rb', line 196

def ab_add_conversion(experiment, alternative, identity, count = 1, implicit = false)
  call_redis_with_failover(experiment, alternative, identity, count, implicit) do
    if implicit
      @experiments.sadd "#{experiment}:alts:#{alternative}:participants", identity
    else
      participating = @experiments.sismember("#{experiment}:alts:#{alternative}:participants", identity)
    end
    @experiments.sadd "#{experiment}:alts:#{alternative}:converted", identity if implicit || participating
    @experiments.incrby "#{experiment}:alts:#{alternative}:conversions", count
  end
end

#ab_add_participant(experiment, alternative, identity) ⇒ Object

Since:

  • 1.4.0


172
173
174
175
176
# File 'lib/vanity/adapters/redis_adapter.rb', line 172

def ab_add_participant(experiment, alternative, identity)
  call_redis_with_failover(experiment, alternative, identity) do
    @experiments.sadd "#{experiment}:alts:#{alternative}:participants", identity
  end
end

#ab_assigned(experiment, identity) ⇒ Object

Returns the participant's seen alternative in this experiment, if it exists

Since:

  • 1.4.0


187
188
189
190
191
192
193
194
# File 'lib/vanity/adapters/redis_adapter.rb', line 187

def ab_assigned(experiment, identity)
  call_redis_with_failover do
    Vanity.playground.experiments[experiment].alternatives.each do |alternative|
      return alternative.id if @experiments.sismember "#{experiment}:alts:#{alternative.id}:participants", identity
    end
    nil
  end
end

#ab_counts(experiment, alternative) ⇒ Object

Since:

  • 1.4.0


145
146
147
148
149
150
151
# File 'lib/vanity/adapters/redis_adapter.rb', line 145

def ab_counts(experiment, alternative)
  {
    participants: @experiments.scard("#{experiment}:alts:#{alternative}:participants").to_i,
    converted: @experiments.scard("#{experiment}:alts:#{alternative}:converted").to_i,
    conversions: @experiments.get("#{experiment}:alts:#{alternative}:conversions").to_i,
  }
end

#ab_get_outcome(experiment) ⇒ Object

Since:

  • 1.4.0


208
209
210
211
# File 'lib/vanity/adapters/redis_adapter.rb', line 208

def ab_get_outcome(experiment)
  alternative = @experiments.get("#{experiment}:outcome")
  alternative && alternative.to_i
end

#ab_not_showing(experiment, identity) ⇒ Object

Since:

  • 1.4.0


166
167
168
169
170
# File 'lib/vanity/adapters/redis_adapter.rb', line 166

def ab_not_showing(experiment, identity)
  call_redis_with_failover do
    @experiments.del "#{experiment}:participant:#{identity}:show"
  end
end

#ab_seen(experiment, identity, alternative_or_id) ⇒ Object

Since:

  • 1.4.0


178
179
180
181
182
183
184
# File 'lib/vanity/adapters/redis_adapter.rb', line 178

def ab_seen(experiment, identity, alternative_or_id)
  with_ab_seen_deprecation(experiment, identity, alternative_or_id) do |expt, ident, alt_id|
    call_redis_with_failover(expt, ident, alt_id) do
      alt_id if @experiments.sismember "#{expt}:alts:#{alt_id}:participants", ident
    end
  end
end

#ab_set_outcome(experiment, alternative = 0) ⇒ Object

Since:

  • 1.4.0


213
214
215
# File 'lib/vanity/adapters/redis_adapter.rb', line 213

def ab_set_outcome(experiment, alternative = 0)
  @experiments.setnx "#{experiment}:outcome", alternative
end

#ab_show(experiment, identity, alternative) ⇒ Object

Since:

  • 1.4.0


153
154
155
156
157
# File 'lib/vanity/adapters/redis_adapter.rb', line 153

def ab_show(experiment, identity, alternative)
  call_redis_with_failover do
    @experiments.set("#{experiment}:participant:#{identity}:show", alternative)
  end
end

#ab_showing(experiment, identity) ⇒ Object

Since:

  • 1.4.0


159
160
161
162
163
164
# File 'lib/vanity/adapters/redis_adapter.rb', line 159

def ab_showing(experiment, identity)
  call_redis_with_failover do
    alternative = @experiments.get("#{experiment}:participant:#{identity}:show")
    alternative && alternative.to_i
  end
end

#active?Boolean

Returns:

  • (Boolean)

Since:

  • 1.4.0


39
40
41
# File 'lib/vanity/adapters/redis_adapter.rb', line 39

def active?
  !!@redis
end

#connect!Object

Since:

  • 1.4.0


53
54
55
56
57
# File 'lib/vanity/adapters/redis_adapter.rb', line 53

def connect!
  @redis = @options[:redis] || Redis.new(@options)
  @metrics = Redis::Namespace.new("vanity:metrics", redis: redis)
  @experiments = Redis::Namespace.new("vanity:experiments", redis: redis)
end

#destroy_experiment(experiment) ⇒ Object

Since:

  • 1.4.0


217
218
219
220
221
222
223
224
225
# File 'lib/vanity/adapters/redis_adapter.rb', line 217

def destroy_experiment(experiment)
  cursor = nil

  while cursor != "0"
    cursor, keys = @experiments.scan(cursor || "0", match: "#{experiment}:*")

    @experiments.del(*keys) unless keys.empty?
  end
end

#destroy_metric(metric) ⇒ Object

Since:

  • 1.4.0


88
89
90
# File 'lib/vanity/adapters/redis_adapter.rb', line 88

def destroy_metric(metric)
  @metrics.del(*@metrics.keys("#{metric}:*"))
end

#disconnect!Object

Since:

  • 1.4.0


43
44
45
46
# File 'lib/vanity/adapters/redis_adapter.rb', line 43

def disconnect!
  redis.disconnect! if redis
  @redis = nil
end

#experiment_persisted?(experiment) ⇒ Boolean

– Experiments –

Returns:

  • (Boolean)

Since:

  • 1.4.0


94
95
96
# File 'lib/vanity/adapters/redis_adapter.rb', line 94

def experiment_persisted?(experiment)
  !!@experiments.get("#{experiment}:created_at")
end

#flushdbObject

Since:

  • 1.4.0


63
64
65
# File 'lib/vanity/adapters/redis_adapter.rb', line 63

def flushdb
  @redis.flushdb
end

#get_experiment_completed_at(experiment) ⇒ Object

Since:

  • 1.4.0


113
114
115
116
# File 'lib/vanity/adapters/redis_adapter.rb', line 113

def get_experiment_completed_at(experiment)
  completed_at = @experiments.get("#{experiment}:completed_at")
  completed_at && Time.at(completed_at.to_i)
end

#get_experiment_created_at(experiment) ⇒ Object

Since:

  • 1.4.0


104
105
106
107
# File 'lib/vanity/adapters/redis_adapter.rb', line 104

def get_experiment_created_at(experiment)
  created_at = @experiments.get("#{experiment}:created_at")
  created_at && Time.at(created_at.to_i)
end

#get_metric_last_update_at(metric) ⇒ Object

– Metrics –

Since:

  • 1.4.0


69
70
71
72
# File 'lib/vanity/adapters/redis_adapter.rb', line 69

def get_metric_last_update_at(metric)
  last_update_at = @metrics.get("#{metric}:last_update_at")
  last_update_at && Time.at(last_update_at.to_i)
end

#is_experiment_completed?(experiment) ⇒ Boolean

rubocop:todo Naming/PredicateName

Returns:

  • (Boolean)

Since:

  • 1.4.0


118
119
120
121
122
123
124
125
126
127
128
# File 'lib/vanity/adapters/redis_adapter.rb', line 118

def is_experiment_completed?(experiment) # rubocop:todo Naming/PredicateName
  call_redis_with_failover do
    if @experiments.respond_to?(:exists?)
      @experiments.exists?("#{experiment}:completed_at")
    else
      exists = @experiments.exists("#{experiment}:completed_at")

      exists.is_a?(Numeric) ? exists > 0 : exists
    end
  end
end

#is_experiment_enabled?(experiment) ⇒ Boolean

rubocop:todo Naming/PredicateName

Returns:

  • (Boolean)

Since:

  • 1.4.0


136
137
138
139
140
141
142
143
# File 'lib/vanity/adapters/redis_adapter.rb', line 136

def is_experiment_enabled?(experiment) # rubocop:todo Naming/PredicateName
  value = @experiments.get("#{experiment}:enabled")
  if Vanity.configuration.experiments_start_enabled
    value != 'false'
  else
    value == 'true'
  end
end

#metric_track(metric, timestamp, identity, values) ⇒ Object

Since:

  • 1.4.0


74
75
76
77
78
79
80
81
# File 'lib/vanity/adapters/redis_adapter.rb', line 74

def metric_track(metric, timestamp, identity, values)
  call_redis_with_failover(metric, timestamp, identity, values) do
    values.each_with_index do |v, i|
      @metrics.incrby "#{metric}:#{timestamp.to_date}:value:#{i}", v
    end
    @metrics.set("#{metric}:last_update_at", Time.now.to_i)
  end
end

#metric_values(metric, from, to) ⇒ Object

Since:

  • 1.4.0


83
84
85
86
# File 'lib/vanity/adapters/redis_adapter.rb', line 83

def metric_values(metric, from, to)
  single = @metrics.mget(*(from.to_date..to.to_date).map { |date| "#{metric}:#{date}:value:0" }) || []
  single.map { |v| [v.to_i] }
end

#reconnect!Object

Since:

  • 1.4.0


48
49
50
51
# File 'lib/vanity/adapters/redis_adapter.rb', line 48

def reconnect!
  disconnect!
  connect!
end

#set_experiment_completed_at(experiment, time) ⇒ Object

Since:

  • 1.4.0


109
110
111
# File 'lib/vanity/adapters/redis_adapter.rb', line 109

def set_experiment_completed_at(experiment, time)
  @experiments.setnx "#{experiment}:completed_at", time.to_i
end

#set_experiment_created_at(experiment, time) ⇒ Object

Since:

  • 1.4.0


98
99
100
101
102
# File 'lib/vanity/adapters/redis_adapter.rb', line 98

def set_experiment_created_at(experiment, time)
  call_redis_with_failover do
    @experiments.setnx "#{experiment}:created_at", time.to_i
  end
end

#set_experiment_enabled(experiment, enabled) ⇒ Object

Since:

  • 1.4.0


130
131
132
133
134
# File 'lib/vanity/adapters/redis_adapter.rb', line 130

def set_experiment_enabled(experiment, enabled)
  call_redis_with_failover do
    @experiments.set "#{experiment}:enabled", enabled
  end
end

#to_sObject

Since:

  • 1.4.0


59
60
61
# File 'lib/vanity/adapters/redis_adapter.rb', line 59

def to_s
  redis.id
end