I am trying to implement several queries against Cassandra DB, here is my attempt:
def last_locations(conn, params) do
{user_ids, _}= Code.eval_string(params["user_ids"])
locations= user_ids
|> Enum.map(&Task.async(fn -> last_location(&1, params) end))
|> Enum.map(&Task.await/1)
json(conn, locations)
end
defp last_location(user_id, params) do
client = CQEx.Client.new!
organization_id= params["organization_id"]
user_id= params["user_id"]
query= "SELECT * from myapp.locations WHERE organization_id=#{organization_id} and user_id=#{user_id} LIMIT 1;"
result= for [organization_id: _, user_id: _, date: _, unix_time: _, lat: lat, long: long] <- Q.call!(client, query)
|> Enum.to_list,
do: [lat, long]
result
end
So, basically, I get user ids, and pass them to last_location function through Task.async, but when I call last_locations I get error:
Is there something I am missing?
EDIT
I have tested the function last_locations to return user_ids via json(conn, user_ids) without calling Enum.map and I got them back, so the function last_locations is being called for sure.
Task.await/1 has a timeout of 5 seconds, so if you were not really getting anything back, you would eventually trigger a timeout. You need to investigate a bit more what is happening.
Please do not ever evaluate user input. The snippet above will allow anyone to execute any code they want in your server. If you want to convert from strings to integers, use String.to_integer or Integer.parse while traversing the list.
Just to make sure you understand the severity of the risk with eval: What if user_ids was code to send all of your application passwords to another website? Or install malware on your server? or delete specific data? You’d have just run it.