mixpanel_client 3.0.0 → 3.1.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/README.md CHANGED
@@ -21,26 +21,46 @@ or if you use a Gemfile
21
21
  client = Mixpanel::Client.new(config)
22
22
 
23
23
  data = client.request('events/properties', {
24
- # Available options
25
- event: '["test-event"]',
26
- name: 'hello',
24
+ event: 'splash features',
25
+ name: 'feature',
27
26
  values: '["uno", "dos"]',
28
- timezone: '-8',
29
- type: 'general',
30
- unit: 'hour',
31
- interval: 24,
27
+ type: 'unique',
28
+ unit: 'day',
29
+ interval: 7,
32
30
  limit: 5,
33
- bucket: 'contents',
34
- from_date: '2011-08-11',
35
- to_date: '2011-08-12',
36
- on: 'properties["product_id"]',
37
- where: '1 in properties["product_id"]',
38
- buckets: '5',
39
- # etc.
40
31
  })
41
32
 
42
33
  puts data.inspect
43
34
 
35
+ ## Parallel
36
+
37
+ require 'rubygems'
38
+ require 'mixpanel_client'
39
+
40
+ config = {api_key: 'changeme', api_secret: 'changeme', parallel: true}
41
+ client = Mixpanel::Client.new(config)
42
+
43
+ first_request = client.request('events/properties', {
44
+ ...
45
+ })
46
+
47
+ second_request = client.request('events/properties', {
48
+ ...
49
+ })
50
+
51
+ third_request = client.request('events/properties', {
52
+ ...
53
+ })
54
+
55
+ ...
56
+
57
+ client.run_parallel_requests
58
+
59
+ puts first_request.response.handled_response
60
+ puts second_request.response.handled_response
61
+ puts third_request.response.handled_response
62
+
63
+
44
64
  ## Development
45
65
  List of rake tasks.
46
66
 
@@ -74,6 +94,10 @@ Create tag v2.0.2 and build and push mixpanel_client-2.0.2.gem to Rubygems
74
94
 
75
95
  ## Changelog
76
96
 
97
+
98
+ ### v3.1.0
99
+ * Parallel requests option.
100
+
77
101
  ### v.3.0.0
78
102
  * NOTE: This version breaks backwards compatibility.
79
103
  * Use a regular ruby hash instead of metaprogramming for mixpanel options.
@@ -13,7 +13,7 @@ module Mixpanel
13
13
  DATA_URI = 'https://data.mixpanel.com/api/2.0'
14
14
 
15
15
  attr_reader :uri
16
- attr_accessor :api_key, :api_secret
16
+ attr_accessor :api_key, :api_secret, :parallel
17
17
 
18
18
  # Configure the client
19
19
  #
@@ -25,6 +25,7 @@ module Mixpanel
25
25
  def initialize(config)
26
26
  @api_key = config[:api_key]
27
27
  @api_secret = config[:api_secret]
28
+ @parallel = config[:parallel] || false
28
29
  end
29
30
 
30
31
  # Return mixpanel data as a JSON object or CSV string
@@ -47,9 +48,41 @@ module Mixpanel
47
48
  def request(resource, options)
48
49
  @format = options[:format] || :json
49
50
  @uri = URI.mixpanel(resource, normalize_options(options))
50
- response = URI.get(@uri)
51
- response = %Q|[#{response.split("\n").join(',')}]| if resource == 'export'
52
- Utils.to_hash(response, @format)
51
+ if @parallel
52
+ parallel_request = prepare_parallel_request
53
+ hydra.queue parallel_request
54
+ parallel_request
55
+ else
56
+ response = URI.get(@uri)
57
+ response = %Q|[#{response.split("\n").join(',')}]| if resource == 'export'
58
+ Utils.to_hash(response, @format)
59
+ end
60
+ end
61
+
62
+ def prepare_parallel_request
63
+ request = ::Typhoeus::Request.new(@uri)
64
+ request.on_complete do |response|
65
+ if response.success?
66
+ Utils.to_hash(response.body, @format)
67
+ elsif response.timed_out?
68
+ raise TimeoutError
69
+ elsif response.code == 0
70
+ # Could not get an http response, something's wrong.
71
+ raise HTTPError, response.curl_error_message
72
+ else
73
+ # Received a non-successful http response.
74
+ raise HTTPError, response.body.present? ? JSON.parse(response.body)['error'] : response.code.to_s
75
+ end
76
+ end
77
+ request
78
+ end
79
+
80
+ def run_parallel_requests
81
+ hydra.run
82
+ end
83
+
84
+ def hydra
85
+ @hydra ||= ::Typhoeus::Hydra.new
53
86
  end
54
87
 
55
88
  private
@@ -10,5 +10,6 @@ module Mixpanel
10
10
  # URI related exceptions
11
11
  class Error < StandardError; end
12
12
  class HTTPError < Error; end
13
+ class TimeoutError < Error; end
13
14
  class ParseError < Error; end
14
15
  end
@@ -10,6 +10,6 @@ module Mixpanel
10
10
  # Return metrics from Mixpanel Data API
11
11
  class Client
12
12
  # Mixpanel::Client library version
13
- VERSION = '3.0.0'
13
+ VERSION = '3.1.0'
14
14
  end
15
15
  end
data/manual_test/basic.rb CHANGED
@@ -6,14 +6,13 @@ require 'yaml'
6
6
 
7
7
  config = YAML.load_file(File.dirname(__FILE__) + '/../config/mixpanel.yml')['mixpanel']
8
8
 
9
- client = Mixpanel::Client.new(config)
9
+ client = Mixpanel::Client.new({api_key: config['api_key'], api_secret: config['api_secret']})
10
10
 
11
- data = client.request do
12
- resource 'events/properties'
13
- event '["test-event"]'
14
- type 'general'
15
- unit 'hour'
16
- name 'test'
17
- end
11
+ data = client.request('events/properties', {
12
+ event: '["test-event"]',
13
+ type: 'general',
14
+ unit: 'hour',
15
+ name: 'test'
16
+ })
18
17
 
19
18
  puts data.inspect
@@ -0,0 +1,25 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'rubygems'
4
+ require 'mixpanel_client'
5
+ require 'yaml'
6
+ require 'typhoeus'
7
+
8
+ config = YAML.load_file(File.dirname(__FILE__) + '/../config/mixpanel.yml')['mixpanel']
9
+
10
+ client = Mixpanel::Client.new({:api_key => config['api_key'], :api_secret => config['api_secret'], :parallel => true})
11
+
12
+ f = client.request('events/top', {
13
+ :type => 'general'
14
+ })
15
+
16
+
17
+ s = client.request('events/names', {
18
+ :type => 'general'
19
+ })
20
+
21
+ client.run_parallel_requests
22
+
23
+ puts f.response.handled_response.inspect
24
+ puts s.response.handled_response.inspect
25
+
@@ -18,11 +18,11 @@ Gem::Specification.new do |s|
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ['lib']
21
-
22
21
  s.add_runtime_dependency('json', '~> 1.6') if RUBY_VERSION < '1.9'
22
+ s.add_runtime_dependency('typhoeus', '~> 0.5.4')
23
23
  s.add_development_dependency('bundler', '>=1.2')
24
24
  s.add_development_dependency('rake', '>=0.9.2.2')
25
25
  s.add_development_dependency('rdoc', '>=3.11')
26
26
  s.add_development_dependency('rspec', '>=2.5.0')
27
- s.add_development_dependency('webmock', '>=1.6.2')
27
+ s.add_development_dependency('webmock', '>=1.9.0')
28
28
  end
@@ -10,6 +10,14 @@ describe Mixpanel::Client do
10
10
  it 'should not raise an exception if a hash is given' do
11
11
  Mixpanel::Client.new('api_key' => 'test_key', 'api_secret' => 'test_secret').should_not raise_error(ArgumentError)
12
12
  end
13
+
14
+ it 'should set a parallel option as false by default' do
15
+ Mixpanel::Client.new(:api_key => 'test_key', :api_secret => 'test_secret').parallel.should == false
16
+ end
17
+
18
+ it 'should be able to set a parallel option when passed' do
19
+ Mixpanel::Client.new(:api_key => 'test_key', :api_secret => 'test_secret', :parallel => true).parallel.should == true
20
+ end
13
21
  end
14
22
 
15
23
  context 'when making an invalid request' do
@@ -50,6 +58,76 @@ describe Mixpanel::Client do
50
58
  })
51
59
  data.should == {"events"=>[], "type"=>"general"}
52
60
  end
61
+
62
+ context "with parallel option enabled" do
63
+ before :all do
64
+ @parallel_client = Mixpanel::Client.new(:api_key => 'test_key', :api_secret => 'test_secret', :parallel => true)
65
+ end
66
+
67
+ it "should return Typhoeus::Request" do
68
+ # Stub Mixpanel request
69
+ stub_request(:get, /^#{@uri}.*/).to_return(:body => '{"legend_size": 0, "data": {"series": [], "values": {}}}')
70
+
71
+ # No endpoint
72
+ data = @parallel_client.request('events', {
73
+ :event => '["test-event"]',
74
+ :unit => 'hour',
75
+ :interval => 24
76
+ })
77
+ data.should be_a Typhoeus::Request
78
+ end
79
+
80
+ describe '#hydra' do
81
+ it 'should return a Typhoeus::Hydra object' do
82
+ @parallel_client.hydra.should be_a Typhoeus::Hydra
83
+ end
84
+ end
85
+
86
+ describe '#run_parallel_requests' do
87
+ it 'should run queued requests' do
88
+ # Stub Mixpanel request
89
+ stub_request(:any, /^#{@uri}.*/).to_return(:body => '{"legend_size": 1, "data": {"series": ["2010-05-29","2010-05-30","2010-05-31"],
90
+ "values": {
91
+ "account-page": {"2010-05-30": 1},
92
+ "splash features": {"2010-05-29": 6,
93
+ "2010-05-30": 4,
94
+ "2010-05-31": 5
95
+ }
96
+ }
97
+ }
98
+ }')
99
+
100
+
101
+ stub_request(:any, /^#{@uri}.*secondevent.*/).to_return(:body => '{"legend_size": 2, "data": {"series": ["2010-05-29","2010-05-30","2010-05-31"],
102
+ "values": {
103
+ "account-page": {"2010-05-30": 2},
104
+ "splash features": {"2010-05-29": 8,
105
+ "2010-05-30": 6,
106
+ "2010-05-31": 7
107
+ }
108
+ }
109
+ }
110
+ }')
111
+
112
+ first_request = @parallel_client.request('events', {
113
+ :event => '["firstevent"]',
114
+ :unit => 'day'
115
+ })
116
+
117
+
118
+ second_request = @parallel_client.request('events', {
119
+ :event => '["secondevent"]',
120
+ :unit => 'day'
121
+ })
122
+
123
+ @parallel_client.run_parallel_requests
124
+
125
+ first_request.response.handled_response.should == {"data"=>{"series"=>["2010-05-29", "2010-05-30", "2010-05-31"], "values"=>{"splash features"=>{"2010-05-29"=>6, "2010-05-30"=>4, "2010-05-31"=>5}, "account-page"=>{"2010-05-30"=>1}}}, "legend_size"=>1}
126
+
127
+ second_request.response.handled_response.should == {"data"=>{"series"=>["2010-05-29", "2010-05-30", "2010-05-31"], "values"=>{"splash features"=>{"2010-05-29"=>8, "2010-05-30"=>6, "2010-05-31"=>7}, "account-page"=>{"2010-05-30"=>2}}}, "legend_size"=>2}
128
+ end
129
+ end
130
+ end
53
131
  end
54
132
 
55
133
  describe '#hash_args' do
@@ -65,4 +143,5 @@ describe Mixpanel::Client do
65
143
  Mixpanel::Client::Utils.to_hash('{"a" : "ey", "b" : "bee"}', :json).should == {'a' => 'ey', 'b' => 'bee'}
66
144
  end
67
145
  end
146
+
68
147
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mixpanel_client
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 3
5
5
  prerelease:
6
6
  segments:
7
7
  - 3
8
+ - 1
8
9
  - 0
9
- - 0
10
- version: 3.0.0
10
+ version: 3.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Keolo Keagy
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-09-22 00:00:00 Z
18
+ date: 2013-02-05 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: json
@@ -33,9 +33,25 @@ dependencies:
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency
36
- name: bundler
36
+ name: typhoeus
37
37
  prerelease: false
38
38
  requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ - 5
47
+ - 4
48
+ version: 0.5.4
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: bundler
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
39
55
  none: false
40
56
  requirements:
41
57
  - - ">="
@@ -46,11 +62,11 @@ dependencies:
46
62
  - 2
47
63
  version: "1.2"
48
64
  type: :development
49
- version_requirements: *id002
65
+ version_requirements: *id003
50
66
  - !ruby/object:Gem::Dependency
51
67
  name: rake
52
68
  prerelease: false
53
- requirement: &id003 !ruby/object:Gem::Requirement
69
+ requirement: &id004 !ruby/object:Gem::Requirement
54
70
  none: false
55
71
  requirements:
56
72
  - - ">="
@@ -63,11 +79,11 @@ dependencies:
63
79
  - 2
64
80
  version: 0.9.2.2
65
81
  type: :development
66
- version_requirements: *id003
82
+ version_requirements: *id004
67
83
  - !ruby/object:Gem::Dependency
68
84
  name: rdoc
69
85
  prerelease: false
70
- requirement: &id004 !ruby/object:Gem::Requirement
86
+ requirement: &id005 !ruby/object:Gem::Requirement
71
87
  none: false
72
88
  requirements:
73
89
  - - ">="
@@ -78,11 +94,11 @@ dependencies:
78
94
  - 11
79
95
  version: "3.11"
80
96
  type: :development
81
- version_requirements: *id004
97
+ version_requirements: *id005
82
98
  - !ruby/object:Gem::Dependency
83
99
  name: rspec
84
100
  prerelease: false
85
- requirement: &id005 !ruby/object:Gem::Requirement
101
+ requirement: &id006 !ruby/object:Gem::Requirement
86
102
  none: false
87
103
  requirements:
88
104
  - - ">="
@@ -94,23 +110,23 @@ dependencies:
94
110
  - 0
95
111
  version: 2.5.0
96
112
  type: :development
97
- version_requirements: *id005
113
+ version_requirements: *id006
98
114
  - !ruby/object:Gem::Dependency
99
115
  name: webmock
100
116
  prerelease: false
101
- requirement: &id006 !ruby/object:Gem::Requirement
117
+ requirement: &id007 !ruby/object:Gem::Requirement
102
118
  none: false
103
119
  requirements:
104
120
  - - ">="
105
121
  - !ruby/object:Gem::Version
106
- hash: 11
122
+ hash: 51
107
123
  segments:
108
124
  - 1
109
- - 6
110
- - 2
111
- version: 1.6.2
125
+ - 9
126
+ - 0
127
+ version: 1.9.0
112
128
  type: :development
113
- version_requirements: *id006
129
+ version_requirements: *id007
114
130
  description: Simple ruby client interface to the Mixpanel API.
115
131
  email:
116
132
  - keolo@dreampointmedia.com
@@ -136,6 +152,7 @@ files:
136
152
  - lib/mixpanel/version.rb
137
153
  - lib/mixpanel_client.rb
138
154
  - manual_test/basic.rb
155
+ - manual_test/parallel.rb
139
156
  - mixpanel_client.gemspec
140
157
  - spec/mixpanel_client/events_externalspec.rb
141
158
  - spec/mixpanel_client/mixpanel_client_spec.rb