I am trying to show post to the first friend of a person first and other’s after making a delay of 1 mins,For that i am using genserver.
Problem is occurring that,the first friend as well as the other friends are getting the post after 1 min.
Here is my code of genserver:
defmodule Phoenix.SchedulePost do
use GenServer
def start_link(state) do
GenServer.start_link __MODULE__,state
end
def init(state) do
schedule_post(state)
{:ok, state}
end
#handling looby
def handle_info(:postSchedule,state) do
#sending posts to others
{:noreply,state}
end
#scheduling a task
defp schedule_post(state) do
IO.puts "scheduling the task"
Process.send_after(self(),:postSchedule,1*60*1000)
end
end
I am starting genserver process for each post request and sending it to the first friend,
Here is the code:
def handle_in("post:toFrstFrnd", %{"friendId"=>friendId,"body" => body}, socket) do
newSocket = PhoenixWeb.SocketBucket.get_socket(friendId)
if newSocket != nil do
push newSocket, "post:toFrstFrnd", %{"friendId": friendId,"body": body}
end
Phoenix.SchedulePost.start_link(postId);
{:noreply, socket}
end
to send on a specific channel… It could replace following code.
newSocket = PhoenixWeb.SocketBucket.get_socket(friendId)
if newSocket != nil do
push newSocket, "post:toFrstFrnd", %{"friendId": friendId,"body": body}
end
You could probably replace all your code by a single handle_in channel function.
Thank you @kokolegorille for your help,:timer.sleep will make handle_in to wait for the timeout of the timer or it will return after timeout,the delayed action will be performed??.
Please review it:
I was trying to push to the first friend
push newSocket, “post:tofrstFrnd”, %{postId: postId,body: body}
since i am making a push call then,it should send the post to the first friend,but the post is coming for first friend after the delay job completed. #sending it to others by making a delay
spawn(fn -> :timer.sleep(60*1000); PhoenixWeb.Endpoint.broadcast! “timer:lobby”,
“scheduledPost:toFrnd”,%{postId: postId}; end)
But the above timer is sending the posts to all friend including the first after 1 minutes,so it is delaying the task.
There is one more thing you have to consider. If you do sleep tasks like that, and then you have a traditional deployment that does stop and start the Erlang VM during the process, your sleeping tasks would be silently killed and cancelled. It might be totally okay to do what you do, but in a scenario where you do multiple deployments per day it can be a show stopper as lots of these tasks would never be executed and your user experience will suffer.
So, if it’s the second case, I would advise storing the jobs somewhere. It does look like exq library already allows you to schedule delayed execution of tasks. I haven’t used it but it does appear to have enqueue_at function that wil ldo what you need: https://hexdocs.pm/exq/Exq.Enqueuer.html#enqueue_at/5
do you think exq library will work for my requirement,The post shared by a person first sent to the friend who has introduced into the application and after 1 min shared to all other friends.
Right now i am facing a problem that after making :timer.sleep(timeout),the delay is happening for both the first friend and other friends.So both(first friend and other friends) can able to get the post after 1 min of delay.
I think that is totally separated problem resulting from that you are starting one job to do these two different things. I think you should start two jobs/processes, or even process per friend and give it a delay as a paremeter that they’d use to sleep on to. For the one you want to get notification immediately, you just pass 0.
If you are going to keep your own solution, change the :postSchedule message to be an actual tuple, consisting of {:postSchedule, user_id} and schedule a number of these messages in the queue, with different third send_after parameter to send those out at different dates. This way you are also de-coupling the behavior so if something fails for one user, others would not be affected.