Reliably implement presence status with ActionCable - ruby-on-rails

I have implemented a chat feature using ActionCable. I am now trying to implement a presence status based on the implementation of user appearances in the README.
This documentation mention the following statement:
The #subscribed callback is invoked when, as we'll show below, a
client-side subscription is initiated. In this case, we take that
opportunity to say "the current user has indeed appeared". That
appear/disappear API could be backed by Redis or a database or
whatever else.
I can implement an online attribute in my database and update it when the application receives appear/disappear notifications. But I have no guarantee about the reliability of this attribute. It could become out of sync in case of a server failure for example.
How could I implement this in a reliable way?

Place it in a Redis structure that expires in a certain amount of time (use TTL). If you store it somewhere for an infinite amount of time (like the DB) it can go out of sync. You might argue that you can set all user presence to false on application startup, but that will only work until you run multiple servers or workers. While a user is connected: insert a presence value for this user into Redis every few minutes. Also handle the connection close event to delete the user presence from Redis for higher accuracy than a few minutes.

Related

Accounting for users that have left website without using onunload

I have a webservice with very limited resources (I will be able to handle about 3 simultaneous users).
When users interact with my website they start a complex process server-side. (This process is the limiting factor, as my server machine will not be able to handle many in parallel, and clients cannot run this on their side.)
My question is how to make sure to end the process for users that leave, for example by closing the window.
I have considered onunload and onbeforeunload, but they are also triggered by links within the website (which I need for users to be able to interact with the process) so that does not seem like an option.
This approach seems problematic according to other questions (see this, for example), but it could work if there were a way to check if the user is still an active user when performing the action triggered by onunload (even if in a different page of the website), but I don't know how to do this.
I have also considered periodically checking the list of active users and cancelling the process for users that have left, but I don't know if this is even possible.
I have zero experience with cookies, but could this be a place to use them? Can the server access the (still living) cookies of disconnected users?
Which sounds like a reasonable approach for this problem?
Cases such as these are generally handled by heartbeats. Have your client send periodic heartbeats (which are essentially pings) to the server notifying that it is still alive and interested in the process's results. And the server automatically kills those processes for which it hasn't received client heartbeat for a configured amount of time.
I have considered onunload and onbeforeunload
You are right- you can't rely on them.
I have zero experience with cookies, but could this be a place to use them?
No. Cookies maintain client-side state that is sent to a server on HTTP calls. So, servers don't manage cookies. Instead, they only look at them to identify state.

signalr notifications based on nonweb originating events

Our system has two servers (S1) one is running processesing and data storage (basically DB) and the other one is a webserver (WS).
There are two types of even that can happen in the system:
User A pings User B. In this case we check if user B is logged in and we push a notification to User B client throw SignalR. It works.
Services constantly running on S1 and generating new data that concenrs multiple users. My goal is as soon as a new data important for user A is generated I immediately want to dispatch a signalR notification to user A client provided he/she is logged in.
This part 2 is not quite clear for me how to design. My thought right now is to start an indefinite process on webserves that monitors our DataBase and checks if new records are generated fpr this user and then push a SignalR message.
That would be fine, but now we have 10k users logged in and I don't think the right decision would be run 10k threads monitoring activities.
Basically, my question is what would a proper way do design signalR based notification mechanism that is based on events that are not originated on our webserver.
I would use a service bus or mq, for example this Free MQ https://www.rabbitmq.com/
You can proxy the messages direcly to the Clients using this proxy library (I'm the author).
Doc's here https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/wiki
Demo https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/tree/master/SignalR.EventAggregatorProxy.Demo.MVC4
You can also set up a sql dependency that triggers a message to your signalr clients,
http://techbrij.com/database-change-notifications-asp-net-signalr-sqldependency
This link is the one that I based my code on.
couple of things to watch for, the setup of the table. You cannot use 3 part table names
"SELECT [CMRID],
[SolutionID],
[CreateDT],
[ModifyDT]
**FROM [dbo].[Case]**
WHERE [ModifyDT] > " + LastExecutionDateTime;
Also, and this is very important, you MUST reset the event handler every time the dependency triggers, if not it will work the first time and then stop working.
I hope this helps you.

How to check if user has bought consumable item?

First, thanks everyone.
Prerequisite:I am providing consumable items in my application.
product:
List item
User purchase the item by iap.
before my application received the updatedTrancactions(Transaction),Network is disconnected.
So my server don't have data to verify the receipt. the user also can not get the "Virtual currency".
Would anyone tell me how to solve this problem,or give me some tip. Thanks very much.
its the standard client-server problem. In case the connection between client and server is severed (due to timeout or other reasons), common way to do it is to retry the request. But if your API calls are not Idempotent and calling an API multiple times can affect the state of your system that many times then we have to resort to do something more clever. Some options you have -
Have a local database. When a purchase happens, then first update the state in you local DB. Late lazily sync the DB from client to server, I hear coredata or sqlite is excellent. User is not aware of this and since DB is local the UI will be extra snappy for the user.
Second approach is - in case of a failed HTTP call. You keep retrying till the call succeeds.
Incase the API is non-idempotent, then you need to have a concept of a token. i.e. a API call with the same token called multiple times is first checked on the server-side if the initial call was a success only if it was a failure execute again. ex. this is very important in banking solutions. Imagine multiple debits from your bank account due to timeouts and someone programmed to keep retrying!
This is all I am able to think of right now. Give it a spin and tell us what worked for you...

HTTP requests in transactions?

I have a model which sends a HTTP request to an external web service on creation in order to find out some information to add before it is saved.
Currently I'm doing this in a before_create callback. I recently learned that before/after callbacks happen within database transactions.
Am I opening myself up to any issues such as limiting DB throughput by doing this? Would it be better to commit the record before sending the http request and then update the record when it returns?
As long a s you keep a transaction open, all the locks it acquired are active. If you have a call to an external source that may stall you for a long period of time, be sure not to to have any unrelated locks in the same transaction.
In other words: don't put anything else into the same transaction.
If you don't mind the new row being visible before you look up the additional information, you might just commit and later update the row.
Or you fetch the information from the external web service before you even start the transaction. That would be cleanest / fastest solution for the database.
PostgreSQL lock types.
How to view locks.

Suggestions for how to write a service in Rails 3

I am building an application which will send status requests to users (via email & sms) on a regular basis. I want to execute the service each hour which will:
Query the database for all requests that need to be sent (based on some logic)
Send the requests through Amazon's Simple Email Service (this is already working)
Write a record of the status request notification back to the data store
I am considering wrapping up this series of operations into a single controller with an end point that can be called remotely to kick off the process within the rails app.
Longer term, I will break this process out into an app that can be run independently of my rails app, but for now I'm just trying to keep it simple.
My first inclination is to build the following:
Controller with the following elements:
A method which will orchestrate the steps outlined above (and can be called externally)
A call to the status_request model which will bring back a collection of request needing to be sent
A loop to iterate through the pending requests, which will:
Make a call to my AWS Simple Email Service module to actually send the email, and
Make a call to the status_request model to log the request back to the database
Model:
A method on my status_request model which will bring back a collection of requests that need to be sent
A method in my status_request model which will log that a notification was sent
Since this will behave as a service that gets called periodically from an outside scheduler I don't think I'll need a view for this operation. (Will, of course, need views to show users and admins what requests have been sent, but that's later...).
As someone new to Rails, I'm asking for review of this approach and any suggestions you may have.
Thanks!
Instead of a controller which Jeff pointed out exposes a security risk, you may just want to expose a rake task and use cron to invoke it on an hourly basis.
If you are still interested in building a controller, look at devise gem and its single access token, token_authenticatable, for securing the methods you are exposing.
You may also want to look at delayed_job or resque to offload the call to status_request and the loop to AWS simple service to a background worker process.
You may want a seperate controller and view for the log file so you can review progress on demand.
And if you want to get real fancy use Amazon SNS to send you alerts when the service reaches some unacceptable level of failures, backlog, etc.
Since you are trying to invoke this from an outside process, your approach should work. You could also have a worker process that processes task when they are there.
You will need routes to expose your service, and you may want to also make security decisions. How will the service that invokes your application authenticate so all others can't hit it at will?
Another consideration should be how many emails are you sending. If there are enough, we may want to look into the fact that writing this sort of loop is going to be extremely top heavy; and may affect users on the current system if it's a web application.
In the end, there are many ways to do this. I would focus on the performance/usage you expect as well as security. There's never one perfect way to solve a problem like this, and your way should just be aware of the variables it will need to be operating within.
Resque and Redis might be helpful to you in scheduling and performing operatio n .They are simple and superfast, [here](http://railscasts.com/episodes/271-resque] is a simple tut on same.

Resources