During a lesson we don't want that neither the student nor the teacher had to refresh the page.
There is two way to do that:
Long polling (pull): IE, every 5sec I'll make a query to my backend/API to see if there's no new data.
Pro: Easy to implement
Con: So many useless queries and doesn't scale very well.
Websockets: IE, I open a new permanent connection with the API so the backend can decide when to push me some new data.
Pro: Elegant. "Instantaneous". Scale.
Con: Hard to implement correctly.
What is a websocket: It's… A bi-directonal tube between 2 machine. Both of them can push data in it so the other side will get it.
Must have
This will be fun™.
To be able to properly instanciate websocket connection we have to do it securely. BUT the websocket protocol doesn't allow headers (you see where we are going ?) so we have to secure the connection negociation ourselves.
Then we have to provide the websocket connection.
Then we have to write data in it :D.
We will heavily rely on ActionCable for handling most of the websocket complexity
We will use action-cable-testing for testing purposes. This gem will be part of rails 6.
[ ] Read the ActionCable documentation so the concepts will be clearer
[ ] Read the action-cable-testing so you can have a glimpse of what's coming.
Websocket connection negociation
We need a way to be sure that our user is authorized and we can't really use headers nor cookies. We will rely on temporary tokens to do so.
[ ] Add a field in the user to store its temporary permanent WS tokenS (Postgres Array is a good candidate here.). Don't forget to add an index.
[ ] Add a way to create a new token for a user (with SecureRandom). Here you have two choices:
Either add it to the user model (the lazy spaghetti way)
[ ] Create a new job (ActiveJob) that will try to find the token in the user and if it exists remove the token.
[ ] After token generation, always start a job that will execute 5 minute later to destroy the token. (hint: use an interactor and an organizer to do both in sequence).
[ ] Provide an URL to ask for a new token for a WS connection. It will create the token, start the job and the return it to the user. (POST on /websocket ?). You can verify that the user is logged in at that time.
[ ] Of course everything should be tested.
Now that we can negotiate for a short-lived auth token we can use it to securely create a bi-directional connection \o/
[ ] Make it fetch the user from the token and be identified_by it. (Hint: A quick way to get the token from the url: token = request.path.gsub(%r{.*/}, ''))
[ ] Remember to remove the token from the user instantly.
[ ] Test eveything
Now we can open the tube and start thinking about throwing data in it \o/
You now have a full flow of websocketing \o/ Adding new channels and infos in your app is easy because you already have the connection flow. Congrats. You have done a hard ticket and you are ready to face the challenges outside of this formation :)
Why ?
During a lesson we don't want that neither the student nor the teacher had to refresh the page.
There is two way to do that:
Long polling (pull): IE, every 5sec I'll make a query to my backend/API to see if there's no new data.
Websockets: IE, I open a new permanent connection with the API so the backend can decide when to push me some new data.
What is a websocket: It's… A bi-directonal tube between 2 machine. Both of them can push data in it so the other side will get it.
Must have
This will be fun™.
To be able to properly instanciate websocket connection we have to do it securely. BUT the websocket protocol doesn't allow headers (you see where we are going ?) so we have to secure the connection negociation ourselves.
Then we have to provide the websocket connection.
Then we have to write data in it :D.
We will heavily rely on ActionCable for handling most of the websocket complexity We will use action-cable-testing for testing purposes. This gem will be part of rails 6.
Websocket connection negociation
We need a way to be sure that our user is authorized and we can't really use headers nor cookies. We will rely on temporary tokens to do so.
SecureRandom
). Here you have two choices:/websocket
?). You can verify that the user is logged in at that time.Now that we can negotiate for a short-lived auth token we can use it to securely create a bi-directional connection \o/
Websocket connection
/cable/:token
identified_by
it. (Hint: A quick way to get the token from the url:token = request.path.gsub(%r{.*/}, '')
)Now we can open the tube and start thinking about throwing data in it \o/
Data broadcasting
stream_for
the lessonYou now have a full flow of websocketing \o/ Adding new channels and infos in your app is easy because you already have the connection flow. Congrats. You have done a hard ticket and you are ready to face the challenges outside of this formation :)
Reading list