crystal_sdk 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +98 -2
- data/docs/recommendations.png +0 -0
- data/lib/crystal_sdk/profile.rb +12 -10
- data/lib/crystal_sdk/profile/request.rb +6 -0
- data/lib/crystal_sdk/version.rb +1 -1
- data/spec/crystal_sdk/profile/request_spec.rb +49 -0
- data/spec/crystal_sdk/profile_spec.rb +2 -2
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ba27b0a6417d08fd9880ceebb13a9c948687a1c
|
4
|
+
data.tar.gz: 319692fbacdf2346768bac7820da9b4f5f4eeb4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9e85319e38fcbf762b87eecee617ae03a0adf3bb2a241292e24abc90a98fa052cc759165219a64d641ef78ac1f4a0ecff67acda949c36b0d565cfe8bc487e5f
|
7
|
+
data.tar.gz: b801219d333da34f0bc7425d456d781d027295f8d49ce7e875c902809d888a96eb718d7de0547d491e9af4222201cd03daadd558fba6f84d07b16ccb53c89fba
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
This gem provides access to Crystal, the world's largest and most accurate personality database!
|
4
4
|
|
5
|
+
![Recommendations Demo](docs/recommendations.png)
|
6
|
+
|
5
7
|
Here's how to install it:
|
6
8
|
```bash
|
7
9
|
$ gem install crystal_sdk
|
@@ -9,6 +11,8 @@ $ gem install crystal_sdk
|
|
9
11
|
|
10
12
|
Here's how you use it:
|
11
13
|
|
14
|
+
## Synchronous Flow (Recommended)
|
15
|
+
|
12
16
|
```ruby
|
13
17
|
require 'crystal_sdk'
|
14
18
|
|
@@ -34,13 +38,13 @@ begin
|
|
34
38
|
|
35
39
|
print "Recommendations: #{profile.recommendations}"
|
36
40
|
|
37
|
-
rescue CrystalSDK::Profile::NotFoundError
|
41
|
+
rescue CrystalSDK::Profile::NotFoundError
|
38
42
|
print "No profile was found"
|
39
43
|
|
40
44
|
rescue CrystalSDK::Profile::NotFoundYetError => e
|
41
45
|
print "Profile search exceeded time limit: #{e.request.id}"
|
42
46
|
|
43
|
-
rescue CrystalSDK::Profile::RateLimitHitError
|
47
|
+
rescue CrystalSDK::Profile::RateLimitHitError
|
44
48
|
print "The organization's API rate limit was hit"
|
45
49
|
|
46
50
|
rescue CrystalSDK::Profile::NotAuthedError => e
|
@@ -51,3 +55,95 @@ rescue StandardError => e
|
|
51
55
|
|
52
56
|
end
|
53
57
|
```
|
58
|
+
|
59
|
+
## Asynchronous Flow (For bulk analysis)
|
60
|
+
|
61
|
+
When requesting large amounts of profiles, or when wanting to have more fine-grained control over performance, we recommend using our asynchronous flow. It allows us to process your requests in parallel and get the information back to you more quickly. There are a couple options for using this capability.
|
62
|
+
|
63
|
+
### Option 1: Polling (Small Lists + Realtime Enrichment)
|
64
|
+
The option we use internally in the SDK, is to poll for request information periodically until a set timeout has been reached:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
MAX_RETRIES = 10
|
68
|
+
PAUSE_IN_SECONDS = 3
|
69
|
+
|
70
|
+
# Start the request
|
71
|
+
query = { first_name: "Drew", ... }
|
72
|
+
request = CrystalSDK::Profile::Request.from_search(query)
|
73
|
+
|
74
|
+
# Poll server until request finishes
|
75
|
+
MAX_RETRIES.times do
|
76
|
+
|
77
|
+
# If the request hasn't finished, wait and loop again
|
78
|
+
unless request.did_finish?
|
79
|
+
sleep(PAUSE_IN_SECONDS)
|
80
|
+
next
|
81
|
+
end
|
82
|
+
|
83
|
+
# Get profile information
|
84
|
+
if request.did_find_profile?
|
85
|
+
profile = Profile.from_request(request)
|
86
|
+
end
|
87
|
+
|
88
|
+
break
|
89
|
+
end
|
90
|
+
|
91
|
+
# Use the profile if it was found
|
92
|
+
profile
|
93
|
+
```
|
94
|
+
|
95
|
+
Polling can be extended to poll for multiple profiles. It gives the efficiency of our parallel processing, while writing code that behaves synchronously.
|
96
|
+
|
97
|
+
This option is great if you want information as fast as possible while keeping open network connections and code complexity to a minimum. It is especially useful if you are requesting multiple profiles and can process the profiles one at a time, as each individual profile comes in (as opposed to waiting for all of them to come in before processing anything).
|
98
|
+
|
99
|
+
|
100
|
+
### Option 2: Background Processing (Large Lists + Passive Enrichment)
|
101
|
+
|
102
|
+
Sometimes, it isn't important to have the profile information immediately. Especially when dealing with larger jobs or passive data enrichment. In that case, we allow you to save the Request ID and pull information from the request at a later time via this ID.
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
|
106
|
+
# Send the request to Crystal
|
107
|
+
profile_request = CrystalSDK::Profile::Request.from_search(query)
|
108
|
+
|
109
|
+
# Pull out the Profile Request ID (string)
|
110
|
+
profile_request_id = profile_request.id
|
111
|
+
|
112
|
+
# Save the Request ID somewhere (to a database or background job, for example)
|
113
|
+
...
|
114
|
+
|
115
|
+
# Later, pull up the Request ID and pull information about it
|
116
|
+
backgrounded_request = CrystalSDK::Profile::Request.new(profile_request_id)
|
117
|
+
|
118
|
+
if backgrounded_request.did_finish? && backgrounded_request.did_find_profile?
|
119
|
+
profile = backgrounded_request.profile
|
120
|
+
...
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
We try and store your request for a few days after the request has been started. Your Request ID should work when you try to pull information from it for at least that period of time!
|
125
|
+
|
126
|
+
|
127
|
+
## Contributing
|
128
|
+
|
129
|
+
- Clone the repository:
|
130
|
+
|
131
|
+
`git clone git@github.com:crystal-project-inc/ruby_sdk.git`
|
132
|
+
|
133
|
+
- Run rspec tests:
|
134
|
+
|
135
|
+
`rspec`
|
136
|
+
|
137
|
+
- Open up an IRB console with the gem loaded to play around with it:
|
138
|
+
|
139
|
+
`rake console`
|
140
|
+
|
141
|
+
- Make a code change
|
142
|
+
|
143
|
+
- Check that the tests still pass
|
144
|
+
|
145
|
+
- Make a pull request!
|
146
|
+
|
147
|
+
We will review the Pull Request to make sure that it does not break the external specification of the gem and that it fits with the overall mission of the SDK!
|
148
|
+
|
149
|
+
We also encourage people to build further libraries that utilize our SDK and extend the use of the Connect API!
|
Binary file
|
data/lib/crystal_sdk/profile.rb
CHANGED
@@ -21,21 +21,23 @@ module CrystalSDK
|
|
21
21
|
|
22
22
|
def search(query, timeout: 30)
|
23
23
|
request = nil
|
24
|
+
profile = nil
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
request = Profile::Request.from_search(query)
|
26
|
+
Timeout.timeout(timeout) do
|
27
|
+
request = Profile::Request.from_search(query)
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
loop do
|
30
|
+
sleep(2) && next unless request.did_finish?
|
31
|
+
raise NotFoundError unless request.did_find_profile?
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
end
|
33
|
+
profile = Profile.from_request(request)
|
34
|
+
break
|
35
35
|
end
|
36
|
-
rescue Timeout::Error
|
37
|
-
raise NotFoundYetError.new(request)
|
38
36
|
end
|
37
|
+
|
38
|
+
profile
|
39
|
+
rescue Timeout::Error
|
40
|
+
raise NotFoundYetError.new(request)
|
39
41
|
end
|
40
42
|
end
|
41
43
|
end
|
@@ -56,6 +56,10 @@ module CrystalSDK
|
|
56
56
|
def did_finish?
|
57
57
|
status = fetch_status
|
58
58
|
status == 'complete' || status == 'error'
|
59
|
+
rescue Profile::NotFoundError
|
60
|
+
true
|
61
|
+
rescue Profile::NotAuthedError
|
62
|
+
true
|
59
63
|
end
|
60
64
|
|
61
65
|
def did_find_profile?
|
@@ -63,6 +67,8 @@ module CrystalSDK
|
|
63
67
|
|
64
68
|
info = fetch_request_info
|
65
69
|
!info[:data][:info][:error]
|
70
|
+
rescue Profile::NotFoundError
|
71
|
+
false
|
66
72
|
end
|
67
73
|
|
68
74
|
def profile_info
|
data/lib/crystal_sdk/version.rb
CHANGED
@@ -156,6 +156,35 @@ describe CrystalSDK::Profile::Request do
|
|
156
156
|
it { is_expected.to eql(true) }
|
157
157
|
end
|
158
158
|
|
159
|
+
context '#fetch_status raises NotFoundError' do
|
160
|
+
before(:each) do
|
161
|
+
allow(request).to receive(:fetch_status)
|
162
|
+
.and_raise(CrystalSDK::Profile::NotFoundError)
|
163
|
+
end
|
164
|
+
|
165
|
+
it { is_expected.to eql(true) }
|
166
|
+
end
|
167
|
+
|
168
|
+
context '#fetch_status raises NotAuthedError' do
|
169
|
+
before(:each) do
|
170
|
+
allow(request).to receive(:fetch_status)
|
171
|
+
.and_raise(CrystalSDK::Profile::NotAuthedError.new('SomeToken'))
|
172
|
+
end
|
173
|
+
|
174
|
+
it { is_expected.to eql(true) }
|
175
|
+
end
|
176
|
+
|
177
|
+
context '#fetch_status raises an unexpected error' do
|
178
|
+
before(:each) do
|
179
|
+
allow(request).to receive(:fetch_status)
|
180
|
+
.and_raise('SomeError')
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'should not suppress it' do
|
184
|
+
expect { subject }.to raise_error('SomeError')
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
159
188
|
context '#fetch_status returns something else' do
|
160
189
|
before(:each) do
|
161
190
|
allow(request).to receive(:fetch_status).and_return('something')
|
@@ -177,6 +206,26 @@ describe CrystalSDK::Profile::Request do
|
|
177
206
|
end
|
178
207
|
end
|
179
208
|
|
209
|
+
context '#fetch_request_info raises NotFoundError' do
|
210
|
+
before(:each) do
|
211
|
+
allow(request).to receive(:fetch_request_info)
|
212
|
+
.and_raise(CrystalSDK::Profile::NotFoundError)
|
213
|
+
end
|
214
|
+
|
215
|
+
it { is_expected.to eql(false) }
|
216
|
+
end
|
217
|
+
|
218
|
+
context '#fetch_request_info raises unexpected error' do
|
219
|
+
before(:each) do
|
220
|
+
allow(request).to receive(:fetch_request_info)
|
221
|
+
.and_raise(CrystalSDK::Profile::NotAuthedError.new('SomeToken'))
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'should not suppress it' do
|
225
|
+
expect { subject }.to raise_error(CrystalSDK::Profile::NotAuthedError)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
180
229
|
context '#did_finish? is true' do
|
181
230
|
before(:each) do
|
182
231
|
allow(request).to receive(:did_finish?).and_return(true)
|
@@ -43,11 +43,11 @@ describe CrystalSDK::Profile do
|
|
43
43
|
.and_return(req)
|
44
44
|
|
45
45
|
allow(req).to receive(:did_finish?)
|
46
|
-
.and_raise(
|
46
|
+
.and_raise('SomeError')
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'should raise exception' do
|
50
|
-
expect { subject }.to raise_error
|
50
|
+
expect { subject }.to raise_error('SomeError')
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crystal_sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cory Finger
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- README.md
|
83
83
|
- Rakefile
|
84
84
|
- crystal_sdk.gemspec
|
85
|
+
- docs/recommendations.png
|
85
86
|
- lib/crystal_sdk.rb
|
86
87
|
- lib/crystal_sdk/api.rb
|
87
88
|
- lib/crystal_sdk/base.rb
|