Reputation: 8318
I have to use an external API to generate a screenshot. In the first step I trigger the generation of the screenshot and receive a job_id
. Than I have to wait and can download the screenshot with the given job_id
. Unfortunately I don't know how long I have to wait. Sometimes the result is ready after 10 seconds and sometimes not. If it is not ready the function image_url/1
returns nil
. If it is ready it returns the image URL.
Currently I use a sleep for 45 seconds which is suboptimal.
I don't understand how I can use the concept of recursion to achieve that the function generate_screenshot/1
, first runs new_job_id(url)
and than tries image_url/1
10 times with a 10 second sleep between or until it is not nil
.
How can I solve this with a recursion?
def generate_screenshot(url) do
job_id = new_job_id(url)
:timer.sleep(45000)
image_url(job_id)
end
defp new_job_id(url) do
# This function triggers a process on
# an external web server an returns
# the job_id of it.
12345
end
defp image_url(job_id) do
# This function fetches something from
# a webserver. The result is nil or
# a URL of an image.
[...]
end
Upvotes: 0
Views: 188
Reputation: 310
You should be able to do it using pattern matching and by breaking up your logic a bit. Something like this should work :
def generate_screenshot(url) do
job_id = new_job_id(url)
image_url(job_id))
end
defp new_job_id(url) do
# This function triggers a process on
# an external web server an returns
# the job_id of it.
12345
end
defp image_url(job_id) do
# Call the version of this function with arity /2
# and check the result. The 0 will act as a counting variable
image_url(job_id), 0)
end
# When the counter reaches 10 return the value regardless
defp image_url(_, 10) do fetch_something()
# Add a case statement that checks the value returned
# if its nil call image_url/2 again after 10 seconds
# and increment the counter by 1
# Otherwise its not nil so we return the value
defp image_url(job_id, count) do
case fetch_something() do
nil ->
:timer.sleep(10000)
image_url(job_id, count + 1)
url -> url
end
end
defp fetch_something() do
# This function fetches something from
# a webserver. The result is nil or
# a URL of an image.
[...]
end
The important part here is we broke the actual fetching of the content away from the image_url/2
function and can now call it from within the case statement. This lets us use pattern matching to call image_url/2
and match on the 10th response with the count variable.
Hope this is helpful I wanted to comment and ask for more info but I can't leave comments quite yet.
Upvotes: 2
Reputation: 21
First I don't understand why you want/have to use a recursion.
IMHO, an elegant way would be to make a loop that check for image_url, sleep a fixed number of seconds (2, 5, 10, ...?) if the image is not ready then continue the loop (to check again in n seconds) and stop the loop when image is ready.
Does this solution meet your needs ?
Upvotes: 0