Created
July 18, 2017 09:00
-
-
Save shaunakpp/eb23cb20a2153898084f39ad14b53920 to your computer and use it in GitHub Desktop.
lazy staggered iteration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Lookup | |
attr_reader :person, :service | |
def initialize(person) | |
@person = person | |
@service = ThirdPartyService.new | |
end | |
def find_match | |
lookups = [ | |
expensive_phone_lookup(@person.email), | |
expensive_location_lookup(@person.email), | |
expensive_property_lookup(@person.email), | |
] | |
lookups.each do |lookup| | |
result = @service.match_person(stage) | |
break result if result.success? | |
end | |
end | |
def find_match | |
while stage = stages(@person.email).next | |
result = @service.match_person(stage) | |
break result if result.success? | |
end | |
rescue StopIteration => _ | |
# error handling here | |
end | |
def stages(email) | |
@stages ||= Enumerator.new do |enumerator| | |
# Step 1: Only Phone | |
phone = expensive_phone_lookup(email) | |
enumerator.yield(:email_only, :phone => phone) | |
# Step 2: Only Phone Number | |
location = expensive_location_lookup(email) | |
enumerator.yield(:location_only, :location => location) | |
# Step 3: Only Property | |
property = expensive_property_lookup(email) | |
enumerator.yield(:property, :property => property) | |
# Step 4: All Info | |
enumerator.yield(:all_info, all_info) | |
end | |
end | |
end | |
We are fetching person data from an third party service like Clearbit or FullContact using his/her email. | |
Each type of data like phones, location, properties, are expensive computationally and monetarily. | |
If we use a traditional collection like Array for this, the array will be eager loaded and all the expensive lookups will happen at the same time | |
But we dont want that do we ? | |
So lets use an enumerator. | |
# Stop on Success | |
def find_match(previous_step = nil) | |
current_step, lookup_data = steps.next | |
result = @service.match_person(lookup_data) | |
if result.failure? | |
return find_match(current_step) | |
end | |
Result.new(current_step, :found, result) | |
rescue StopIteration => _ | |
return Result.new(previous_step, :not_found, document = nil) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment