octocore-mongo 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGES.md +12 -0
- data/CONTRIBUTING +0 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +150 -0
- data/LICENSE +202 -0
- data/MAINTAINERS +0 -0
- data/NOTICE +8 -0
- data/README.md +69 -0
- data/Rakefile +51 -0
- data/bin/fakestream-mongo +258 -0
- data/bin/octocore-admin-mongo +54 -0
- data/lib/octocore-mongo.rb +157 -0
- data/lib/octocore-mongo/baseline.rb +131 -0
- data/lib/octocore-mongo/callbacks.rb +117 -0
- data/lib/octocore-mongo/config.rb +39 -0
- data/lib/octocore-mongo/config/config.yml +1 -0
- data/lib/octocore-mongo/config/search/index/user.yml +42 -0
- data/lib/octocore-mongo/counter.rb +265 -0
- data/lib/octocore-mongo/counter/helpers.rb +168 -0
- data/lib/octocore-mongo/email.rb +63 -0
- data/lib/octocore-mongo/featureflag.rb +79 -0
- data/lib/octocore-mongo/helpers.rb +6 -0
- data/lib/octocore-mongo/helpers/api_consumer_helper.rb +51 -0
- data/lib/octocore-mongo/helpers/api_helper.rb +65 -0
- data/lib/octocore-mongo/helpers/api_logger.rb +14 -0
- data/lib/octocore-mongo/helpers/client_helper.rb +104 -0
- data/lib/octocore-mongo/helpers/kong_helper.rb +164 -0
- data/lib/octocore-mongo/helpers/sinatra_helper.rb +22 -0
- data/lib/octocore-mongo/kafka_bridge.rb +60 -0
- data/lib/octocore-mongo/kldivergence.rb +14 -0
- data/lib/octocore-mongo/mailer.rb +1 -0
- data/lib/octocore-mongo/mailer/subscriber_mailer.rb +32 -0
- data/lib/octocore-mongo/message_parser.rb +114 -0
- data/lib/octocore-mongo/models.rb +275 -0
- data/lib/octocore-mongo/models/contactus.rb +42 -0
- data/lib/octocore-mongo/models/enterprise.rb +75 -0
- data/lib/octocore-mongo/models/enterprise/adapter_details.rb +18 -0
- data/lib/octocore-mongo/models/enterprise/api_event.rb +14 -0
- data/lib/octocore-mongo/models/enterprise/api_hit.rb +20 -0
- data/lib/octocore-mongo/models/enterprise/api_key.rb +11 -0
- data/lib/octocore-mongo/models/enterprise/api_track.rb +13 -0
- data/lib/octocore-mongo/models/enterprise/app_init.rb +13 -0
- data/lib/octocore-mongo/models/enterprise/app_login.rb +12 -0
- data/lib/octocore-mongo/models/enterprise/app_logout.rb +12 -0
- data/lib/octocore-mongo/models/enterprise/authorization.rb +67 -0
- data/lib/octocore-mongo/models/enterprise/category.rb +14 -0
- data/lib/octocore-mongo/models/enterprise/category_baseline.rb +19 -0
- data/lib/octocore-mongo/models/enterprise/category_hit.rb +26 -0
- data/lib/octocore-mongo/models/enterprise/category_trend.rb +19 -0
- data/lib/octocore-mongo/models/enterprise/conversions.rb +69 -0
- data/lib/octocore-mongo/models/enterprise/ctr.rb +54 -0
- data/lib/octocore-mongo/models/enterprise/dimension_choice.rb +21 -0
- data/lib/octocore-mongo/models/enterprise/engagement_time.rb +43 -0
- data/lib/octocore-mongo/models/enterprise/funnel_data.rb +20 -0
- data/lib/octocore-mongo/models/enterprise/funnel_tracker.rb +19 -0
- data/lib/octocore-mongo/models/enterprise/funnels.rb +129 -0
- data/lib/octocore-mongo/models/enterprise/gcm.rb +21 -0
- data/lib/octocore-mongo/models/enterprise/newsfeed_hit.rb +52 -0
- data/lib/octocore-mongo/models/enterprise/notification_hit.rb +42 -0
- data/lib/octocore-mongo/models/enterprise/page.rb +15 -0
- data/lib/octocore-mongo/models/enterprise/page_view.rb +14 -0
- data/lib/octocore-mongo/models/enterprise/pageload_time.rb +43 -0
- data/lib/octocore-mongo/models/enterprise/product.rb +22 -0
- data/lib/octocore-mongo/models/enterprise/product_baseline.rb +20 -0
- data/lib/octocore-mongo/models/enterprise/product_hit.rb +26 -0
- data/lib/octocore-mongo/models/enterprise/product_page_view.rb +13 -0
- data/lib/octocore-mongo/models/enterprise/product_trend.rb +18 -0
- data/lib/octocore-mongo/models/enterprise/push_key.rb +15 -0
- data/lib/octocore-mongo/models/enterprise/rules.rb +45 -0
- data/lib/octocore-mongo/models/enterprise/segment.rb +65 -0
- data/lib/octocore-mongo/models/enterprise/segment_data.rb +22 -0
- data/lib/octocore-mongo/models/enterprise/tag.rb +14 -0
- data/lib/octocore-mongo/models/enterprise/tag_baseline.rb +19 -0
- data/lib/octocore-mongo/models/enterprise/tag_hit.rb +26 -0
- data/lib/octocore-mongo/models/enterprise/tag_trend.rb +19 -0
- data/lib/octocore-mongo/models/enterprise/template.rb +18 -0
- data/lib/octocore-mongo/models/plans.rb +17 -0
- data/lib/octocore-mongo/models/subscribe.rb +13 -0
- data/lib/octocore-mongo/models/user.rb +13 -0
- data/lib/octocore-mongo/models/user/push_token.rb +15 -0
- data/lib/octocore-mongo/models/user/user_browser_details.rb +16 -0
- data/lib/octocore-mongo/models/user/user_location_history.rb +15 -0
- data/lib/octocore-mongo/models/user/user_persona.rb +101 -0
- data/lib/octocore-mongo/models/user/user_phone_details.rb +17 -0
- data/lib/octocore-mongo/models/user/user_profile.rb +20 -0
- data/lib/octocore-mongo/models/user/user_timeline.rb +111 -0
- data/lib/octocore-mongo/record.rb +20 -0
- data/lib/octocore-mongo/schedeuleable.rb +20 -0
- data/lib/octocore-mongo/scheduler.rb +72 -0
- data/lib/octocore-mongo/search.rb +5 -0
- data/lib/octocore-mongo/search/client.rb +33 -0
- data/lib/octocore-mongo/search/indexer.rb +0 -0
- data/lib/octocore-mongo/search/searchable.rb +18 -0
- data/lib/octocore-mongo/search/setup.rb +71 -0
- data/lib/octocore-mongo/segment.rb +287 -0
- data/lib/octocore-mongo/stats.rb +33 -0
- data/lib/octocore-mongo/trendable.rb +88 -0
- data/lib/octocore-mongo/trends.rb +158 -0
- data/lib/octocore-mongo/utils.rb +90 -0
- data/lib/octocore-mongo/version.rb +4 -0
- data/octocore-mongo.gemspec +50 -0
- data/spec/lib/stats_spec.rb +20 -0
- data/spec/spec_helper.rb +103 -0
- metadata +545 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'statsd-ruby'
|
2
|
+
|
3
|
+
module Octo
|
4
|
+
|
5
|
+
# Instrumentation and Statistical module
|
6
|
+
module Stats
|
7
|
+
|
8
|
+
# Instrument a block identified by its name
|
9
|
+
# @param [Symbol] name The name by which this would be identified
|
10
|
+
def instrument(name)
|
11
|
+
if stats
|
12
|
+
stats.time(name.to_s, &Proc.new)
|
13
|
+
else
|
14
|
+
yield
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get stats instance
|
19
|
+
def stats
|
20
|
+
if statd_config
|
21
|
+
@statsd = Statsd.new(*statd_config.values) unless @statsd
|
22
|
+
@statsd
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Get stats config from Octo
|
29
|
+
def statd_config
|
30
|
+
Octo.get_config :statsd
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'octocore-mongo/kldivergence'
|
2
|
+
require 'octocore-mongo/counter'
|
3
|
+
|
4
|
+
module Octo
|
5
|
+
|
6
|
+
module Trendable
|
7
|
+
|
8
|
+
include Octo::KLDivergence
|
9
|
+
|
10
|
+
# Define the columns necessary for a trendable model
|
11
|
+
def trendables
|
12
|
+
key :divergence, Float
|
13
|
+
key :obp, Float
|
14
|
+
end
|
15
|
+
|
16
|
+
# Define the baseline class for this trend
|
17
|
+
def baseline(klass)
|
18
|
+
@baseline_klass = klass
|
19
|
+
end
|
20
|
+
|
21
|
+
# Define the class for trends
|
22
|
+
def trends_class(klass)
|
23
|
+
@trends_klass = klass
|
24
|
+
end
|
25
|
+
|
26
|
+
# Aggregates and attempts to store it into the database. This would only
|
27
|
+
# work if the class that extends Octo::Counter includes from
|
28
|
+
# Cequel::Record
|
29
|
+
def aggregate!(ts = Time.now.floor)
|
30
|
+
unless self.ancestors.include?MongoMapper::Document
|
31
|
+
raise NoMethodError, 'aggregate! not defined for this counter'
|
32
|
+
end
|
33
|
+
|
34
|
+
aggr = aggregate(ts)
|
35
|
+
sum = aggregate_sum(aggr)
|
36
|
+
aggr.each do |_ts, counterVals|
|
37
|
+
counterVals.each do |obj, count|
|
38
|
+
counter = self.new
|
39
|
+
counter.enterprise_id = obj.enterprise.id
|
40
|
+
counter.uid = obj.unique_id
|
41
|
+
counter.count = count
|
42
|
+
counter.type = Octo::Counter::TYPE_MINUTE
|
43
|
+
counter.ts = _ts
|
44
|
+
totalCount = sum[_ts][obj.enterprise_id.to_s].to_f
|
45
|
+
counter.obp = (count * 1.0)/totalCount
|
46
|
+
|
47
|
+
baseline_value = get_baseline_value(:TYPE_MINUTE, obj)
|
48
|
+
counter.divergence = kl_divergence(counter.obp,
|
49
|
+
baseline_value)
|
50
|
+
counter.save!
|
51
|
+
end
|
52
|
+
end
|
53
|
+
call_completion_hook(Octo::Counter::TYPE_MINUTE, ts)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# Aggregates to find the sum of all counters for an enterprise
|
59
|
+
# at a time
|
60
|
+
# @param [Hash] aggr The aggregated hash
|
61
|
+
# @return [Hash] The summed up hash
|
62
|
+
def aggregate_sum(aggr)
|
63
|
+
sum = {}
|
64
|
+
aggr.each do |ts, counterVals|
|
65
|
+
sum[ts] = {} unless sum.has_key?ts
|
66
|
+
counterVals.each do |obj, count|
|
67
|
+
if obj.respond_to?(:enterprise_id)
|
68
|
+
eid = obj.public_send(:enterprise_id).to_s
|
69
|
+
sum[ts][eid] = sum[ts].fetch(eid, 0) + count
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
sum
|
74
|
+
end
|
75
|
+
|
76
|
+
# Get the baseline value for an object.
|
77
|
+
# @param [Fixnum] baseline_type The type of baseline to fetch
|
78
|
+
# @param [Object] object The object for which baseline is to
|
79
|
+
# be fetched
|
80
|
+
def get_baseline_value(baseline_type, object)
|
81
|
+
clazz = @baseline_klass.constantize
|
82
|
+
clazz.public_send(:get_baseline_value, baseline_type, object)
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'octocore-mongo/baseline'
|
2
|
+
require 'octocore-mongo/counter'
|
3
|
+
|
4
|
+
module Octo
|
5
|
+
|
6
|
+
module Trends
|
7
|
+
|
8
|
+
include Octo::Counter::Helper
|
9
|
+
|
10
|
+
DEFAULT_COUNT = 10
|
11
|
+
|
12
|
+
# Define the columns needed for Trends
|
13
|
+
def trendable
|
14
|
+
key :type, Integer
|
15
|
+
key :ts, Time
|
16
|
+
key :rank, Integer
|
17
|
+
|
18
|
+
key :score, Float
|
19
|
+
key :uid, String
|
20
|
+
|
21
|
+
generate_aggregators { |ts, method|
|
22
|
+
trendtype = method_names_type_counter(method)
|
23
|
+
aggregate_and_create trendtype, ts
|
24
|
+
}
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
# Aggregates and creates trends for all the enterprises for a specific
|
29
|
+
# trend type at a specific timestamp
|
30
|
+
# @param [Fixnum] oftype The type of trend to be calculated
|
31
|
+
# @param [Time] ts The time at which trend needs to be calculated
|
32
|
+
def aggregate_and_create(oftype, ts = Time.now.floor)
|
33
|
+
Octo::Enterprise.each do |enterprise|
|
34
|
+
calculate(enterprise.id, oftype, ts)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Override the aggregate! defined in counter class as the calculations
|
39
|
+
# for trending are a little different
|
40
|
+
def aggregate!(ts = Time.now.floor)
|
41
|
+
aggregate_and_create(Octo::Counter::TYPE_MINUTE, ts)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Performs the actual trend calculation
|
45
|
+
# @param [String] enterprise_id The enterprise ID for whom trend needs to be found
|
46
|
+
# @param [Fixnum] trend_type The trend type to be calculates
|
47
|
+
# @param [Time] ts The Timestamp at which trend needs to be calculated.
|
48
|
+
def calculate(enterprise_id, trend_type, ts = Time.now.floor)
|
49
|
+
args = {
|
50
|
+
enterprise_id: enterprise_id,
|
51
|
+
ts: ts,
|
52
|
+
type: trend_type
|
53
|
+
}
|
54
|
+
|
55
|
+
klass = @trend_for.constantize
|
56
|
+
hitsResult = klass.public_send(:where, args)
|
57
|
+
trends = hitsResult.map { |h| counter2trend(h) }
|
58
|
+
|
59
|
+
# group trends as per the time of their happening and rank them on their
|
60
|
+
# score
|
61
|
+
grouped_trends = trends.group_by { |x| x.ts }
|
62
|
+
grouped_trends.each do |_ts, trendlist|
|
63
|
+
sorted_trendlist = trendlist.sort_by { |x| x.score }
|
64
|
+
sorted_trendlist.each_with_index do |trend, index|
|
65
|
+
trend.rank = index
|
66
|
+
trend.type = trend_type
|
67
|
+
trend.save!
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Define the class for which trends shall be found
|
73
|
+
def trend_for(klass)
|
74
|
+
unless klass.constantize.ancestors.include?MongoMapper::Document
|
75
|
+
raise ArgumentError, "Class #{ klass } does not represent a DB Model"
|
76
|
+
else
|
77
|
+
@trend_for = klass
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Define the class which would be returned while fetching trending objects
|
82
|
+
def trend_class(klass)
|
83
|
+
@trend_class = klass
|
84
|
+
end
|
85
|
+
|
86
|
+
# Gets the trend of a type at a time
|
87
|
+
# @param [String] enterprise_id The ID of enterprise for whom trend to fetch
|
88
|
+
# @param [Fixnum] type The type of trend to fetch
|
89
|
+
# @param [Hash] opts The options to be provided for finding trends
|
90
|
+
def get_trending(enterprise_id, type, opts={})
|
91
|
+
ts = opts.fetch(:ts, Time.now.floor)
|
92
|
+
args = {
|
93
|
+
enterprise_id: enterprise_id,
|
94
|
+
ts: opts.fetch(:ts, Time.now.floor),
|
95
|
+
type: type
|
96
|
+
}
|
97
|
+
res = where(args).limit(opts.fetch(:limit, DEFAULT_COUNT))
|
98
|
+
enterprise = Octo::Enterprise.find_by_id(enterprise_id)
|
99
|
+
if res.count == 0 and enterprise.fakedata?
|
100
|
+
Octo.logger.info 'Beginning to fake data'
|
101
|
+
res = []
|
102
|
+
if ts.class == Range
|
103
|
+
ts_begin = ts.begin
|
104
|
+
ts_end = ts.end
|
105
|
+
ts_begin.to(ts_end, 1.day).each do |_ts|
|
106
|
+
3.times do |rank|
|
107
|
+
items = @trend_class.constantize.send(:where, {enterprise_id: enterprise_id}).first(10)
|
108
|
+
if items.count > 0
|
109
|
+
uid = items.shuffle.pop.unique_id
|
110
|
+
_args = args.merge( ts: _ts, rank: rank, score: rank+1, uid: uid )
|
111
|
+
res << self.new(_args).save!
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
elsif ts.class == Time
|
116
|
+
3.times do |rank|
|
117
|
+
uid = 0
|
118
|
+
items = @trend_class.constantize.send(:where, {enterprise_id: enterprise_id}).first(10)
|
119
|
+
if items.count > 0
|
120
|
+
uid = items.shuffle.pop.unique_id
|
121
|
+
_args = args.merge( rank: rank, score: rank+1, uid: uid )
|
122
|
+
res << self.new(_args).save!
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
res.map do |r|
|
128
|
+
clazz = @trend_class.constantize
|
129
|
+
clazz.public_send(:recreate_from, r)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
# Converts a couunter into a trend
|
136
|
+
# @param [Object] counter A counter object. This object must belong
|
137
|
+
# to one of the counter types defined in models.
|
138
|
+
# @return [Object] Returns a trend instance corresponding to the counter
|
139
|
+
# instance
|
140
|
+
def counter2trend(counter)
|
141
|
+
self.new({
|
142
|
+
enterprise: counter.enterprise,
|
143
|
+
score: score(counter.divergence),
|
144
|
+
uid: counter.uid,
|
145
|
+
ts: counter.ts
|
146
|
+
})
|
147
|
+
end
|
148
|
+
|
149
|
+
# For now, just make sure divergence is absolute. This is responsible to
|
150
|
+
# score a counter on the basis of its divergence
|
151
|
+
# @param [Float] divergence The divergence value
|
152
|
+
# @return [Float] The score
|
153
|
+
def score(divergence)
|
154
|
+
return 0 if divergence.nil?
|
155
|
+
divergence.abs
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Octo
|
4
|
+
|
5
|
+
module Utils
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
# Serialize one record before adding it to the cache. Creates a ruby byte
|
10
|
+
# stream
|
11
|
+
# @param [Object] record Any object to be serialized
|
12
|
+
def serialize(record)
|
13
|
+
Marshal::dump(record).to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
# Deserialize a data.
|
17
|
+
# @param [String] data A string containing Marshal dump of the object
|
18
|
+
def deserialize(data)
|
19
|
+
Marshal::load(data)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class ::Time
|
26
|
+
|
27
|
+
# Find floor time
|
28
|
+
# @param [Fixnum] height The minutes of height for floor. Defaults to 1
|
29
|
+
def floor(height = 1)
|
30
|
+
if height < 1
|
31
|
+
height = 1
|
32
|
+
end
|
33
|
+
sec = height.to_i * 60
|
34
|
+
Time.at((self.to_i / sec).round * sec)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Find ceil time
|
38
|
+
# @param [Fixnum] height The minutes of height for ceil. Defaults to 1
|
39
|
+
def ceil(height = 1)
|
40
|
+
if height < 1
|
41
|
+
height = 1
|
42
|
+
end
|
43
|
+
sec = height.to_i * 60
|
44
|
+
Time.at((1 + (self.to_i / sec)).round * sec)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Finds the steps between two time.
|
48
|
+
# @param [Time] to The end time
|
49
|
+
# @param [Time] step The step time. Defaults to 15.minute
|
50
|
+
# @return [Array<Time>] An array containint times
|
51
|
+
def to(to, step = 15.minutes)
|
52
|
+
[self].tap { |array| array << array.last + step while array.last < to }
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
class ::String
|
58
|
+
|
59
|
+
# Create a custom method to convert strings to Slugs
|
60
|
+
def to_slug
|
61
|
+
#strip the string
|
62
|
+
ret = self.strip
|
63
|
+
|
64
|
+
#blow away apostrophes
|
65
|
+
ret.gsub!(/['`]/,'')
|
66
|
+
|
67
|
+
# @ --> at, and & --> and
|
68
|
+
ret.gsub!(/\s*@\s*/, ' at ')
|
69
|
+
ret.gsub!(/\s*&\s*/, ' and ')
|
70
|
+
|
71
|
+
#replace all non alphanumeric, underscore or periods with underscore
|
72
|
+
ret.gsub!(/\s*[^A-Za-z0-9\.\-]\s*/, '_')
|
73
|
+
|
74
|
+
#convert double underscores to single
|
75
|
+
ret.gsub!(/_+/,'_')
|
76
|
+
|
77
|
+
#strip off leading/trailing underscore
|
78
|
+
ret.gsub!(/\A[_\.]+|[_\.]+\z/,'')
|
79
|
+
|
80
|
+
ret
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
class ::Hash
|
86
|
+
def deep_merge(second)
|
87
|
+
merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : Array === v1 && Array === v2 ? v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
|
88
|
+
self.merge(second.to_h, &merger)
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.expand_path('../lib/octocore-mongo/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'octocore-mongo'
|
5
|
+
s.version = Octo::VERSION
|
6
|
+
|
7
|
+
s.summary = 'Octo Enterprise Core Modules for MongoDB'
|
8
|
+
s.description = <<DESC
|
9
|
+
Octocore is the core framework of Octomatic Enterprise. It
|
10
|
+
contains all the core models, tasks, actions etc for MongoDB
|
11
|
+
DESC
|
12
|
+
|
13
|
+
s.authors = ['Dipankar Sarkar']
|
14
|
+
s.email = 'dipankar@octo.ai'
|
15
|
+
s.files = Dir['lib/**/*.rb', 'spec/**/*.rb', '[A-Z]*', 'lib/**/*.yml']
|
16
|
+
|
17
|
+
s.executables << 'fakestream-mongo'
|
18
|
+
s.executables << 'octocore-admin-mongo'
|
19
|
+
|
20
|
+
s.homepage =
|
21
|
+
'https://github.com/octoai/gem-octocore-mongo'
|
22
|
+
s.license = 'MIT'
|
23
|
+
|
24
|
+
s.has_rdoc = true
|
25
|
+
s.extra_rdoc_files = 'README.md'
|
26
|
+
|
27
|
+
s.required_ruby_version = '>= 2.1.5'
|
28
|
+
|
29
|
+
s.add_runtime_dependency 'activemodel-serializers-xml', '~> 1.0.1', '>= 1.0.1'
|
30
|
+
s.add_runtime_dependency 'active_model_serializers', '~> 0.9.5', '>= 0.9.5'
|
31
|
+
s.add_runtime_dependency 'redis', '~> 3.2.2', '>= 3.2.0'
|
32
|
+
s.add_runtime_dependency 'redis-queue', '~> 0.0.4', '>= 0.0.4'
|
33
|
+
s.add_runtime_dependency 'hiredis', '~> 0.6.1', '>= 0.6.0'
|
34
|
+
s.add_runtime_dependency 'rake', '~> 11.1.0', '>= 11.1.0'
|
35
|
+
s.add_runtime_dependency 'resque', '~> 1.26.0', '>= 1.26.0'
|
36
|
+
s.add_runtime_dependency 'resque-scheduler', '~> 4.1.0', '>= 4.1.0'
|
37
|
+
s.add_runtime_dependency 'descriptive_statistics', '~> 2.5.1', '>= 2.5.0'
|
38
|
+
s.add_runtime_dependency 'statsd-ruby', '~> 1.3.0', '>= 1.3.0'
|
39
|
+
s.add_runtime_dependency 'hooks', '~> 0.4.1', '>= 0.4.1'
|
40
|
+
s.add_runtime_dependency 'json', '~> 1.8.1', '>= 1.8.1'
|
41
|
+
s.add_runtime_dependency 'ruby-kafka', '~> 0.3.2', '>= 0.3.2'
|
42
|
+
s.add_runtime_dependency 'mandrill-api', '~> 1.0', '>= 1.0.53'
|
43
|
+
s.add_runtime_dependency 'elasticsearch', '~> 1.0.17', '>= 1.0.17'
|
44
|
+
s.add_runtime_dependency 'faraday', '~> 0.9.2', '>= 0.9.2'
|
45
|
+
s.add_runtime_dependency 'mongo_mapper', '~> 0.13.1'
|
46
|
+
s.add_runtime_dependency 'bson_ext', '~> 1.12', '>= 1.12.5'
|
47
|
+
|
48
|
+
s.add_development_dependency 'rspec', '~> 3.4.0', '>= 3.4.0'
|
49
|
+
s.add_development_dependency 'parallel_tests', '~> 2.5.0', '>= 2.5.0'
|
50
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe Octo::Stats do
|
4
|
+
|
5
|
+
describe '#instrument' do
|
6
|
+
let(:dummy_class) { Class.new { extend Octo::Stats } }
|
7
|
+
|
8
|
+
it 'yields the given block' do
|
9
|
+
block = Proc.new { puts 'hello world' }
|
10
|
+
name = :hello_world
|
11
|
+
|
12
|
+
expect(dummy_class).to receive(:instrument).
|
13
|
+
with(name, &block).
|
14
|
+
and_yield(&block)
|
15
|
+
|
16
|
+
dummy_class.instrument(name, &block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|