I'm wondering the way to push content in my site in real time..
I've researched some time and I realized that there are many ways to do this work.
Some considerations first:
I have a Rails 3 App with some social functionality..one of the features I want to achieve is to notify my users when a new activity is created.
My first approach was to implement SSE and a controller that searches in the DB for new registries after the last loaded activity.
This can work but this requires too many DB queries when all I need is to push the activity to all active users (related with that activity) when a new activity is created, without the need to do DB queries..
My second approach was to create a route pointing to a controller and an observer to catch when an new activity is created, later pass the current activity created to the controller and finally render the activity partial through SSE.
Here comes my problem.. how can connect the observer with the controller and pass it the current activity to be rendered?
And there, can I use another controller type such as a Metal Controller or even an Abstract one?
In this point I realized that could be another approach to do this job..
It'd be really nice if I could find a way to do this without having to develop it in another language or framework.. I think that should have a gem that could do real time apps easier..
What do you think?? I'm on the right way or what I should do to achieve this??
Many Thanks!!
Rails 3.0+ Push Content in Real-time with PubNub
In order to safely and securely push real-time updates to your users with some social functionality on your web site or web app there are, as you say, many options available and many nuances to consider with this as well. There is a gem for this! And I will help you get started by providing a simple start guide here for your Rails 3.0+ app and web site. First you'll want to run gem install pubnub which is the real-time component known as PubNub that will allow you to send notifications directly to targeted users or a group of users on your website and apps. This allows you to target only those who are online and interested in receiving the notifications from your Rails server. You can consider this as efficient server-sent events that require no DB Lookup or other resource intensive operations on your servers.
Ruby GEM Install
gem install pubnub
Require PubNub GEM
require 'pubnub'
Initialize The PubNub Class
pubnub = Pubnub.new(
:publish_key => 'demo', # publish_key only required if publishing.
:subscribe_key => 'demo', # required always
:secret_key => nil, # optional - message signing
:cipher_key => nil, # optional - AES 256 Crypto
:ssl => true # optional - SSL 2048bit
)
From Rails 3.0+ Send Messages to the Web App
Now from your Rails App with the pubnub class ready, you can send any kind of JSON data type including a String, Number, Array and Dictionary/Object:
a "String"
a Number 123
an array [ 1, 2, 3 ]
an object { :a => "apple" }
The following code will show you the process which will pass a message from your Rails App directly to the browser or web app that you users are running. Essentially sending the data to your users when you need to directly from your server. The pubnub.publish(...) function will serialize the message you send as a JSON for transport to your mobile and web apps.
## Broadcast or Unicast to Browser App User(s)
pubnub.publish(
:channel => "event_feed_channel",
:message => { :event => "update", :from => "Jay", :feed => "New Updates!" },
:callback => lambda { |info| puts info }
)
This process works great for performance and security considerations and never requires DB queries; saving you from hammering on your Database server and other resource intensive operations. You may consider this process as SSE (Server-Sent Events) while you are using the PubNub GEM in your Rails applications.
Using the PubNub GEM you are essentially sending events from your Server direct to your User's Browser/App. It removes the need for client-side periodic AJAX requests. This is because you are only sending data to your user's when new information is available. You may also consider using more PubNub Real-time Network features like Presence and Storage/Playback by visiting the home site to learn more details about the Ruby features. And also use the Developers Dev Console for debugging if needed during your integration into your Rails code.
Setup Browser to Receive Server-Sent Events
Next you need to setup your app to receive the Server-Sent Events by running init and passing in the
<script src=http://cdn.pubnub.com/pubnub-3.4.2.min.js ></script>
<script>(function(){
// Class Setup
var pubnub = PUBNUB.init({ subscribe_key : 'demo' });
// Event Hook Setup
pubnub.subscribe({
channel : "event_feed_channel",
message : function(m){ pubnub.events.fire( m.event, m ) }
});
// RECEIVE the "update" Server Broadcast Event in the Browser
pubnub.events.bind( "update", function(message) {
console.log( "update a <div> with received event: ", m );
} );
})();</script>
Note you may be interested in Advanced Subscribe Connectivity Options and Events.
Notice how the "update" event is identical to the :event => "update" message value in the ruby code. This means that the event will be triggered based on the name you supply and you need to bind the event to trigger code to execute on your Web App page. Inside this triggered event you will update the User Interface with any relevant details that the user would want to see on their screen in real-time.
Also notice the :channel => "event_feed_channel" is the publish channel, and this must be identical as the subscribe channel in the JavaScript client code.
If you want to read the source code of the Ruby GEM, it is available via GitHub PubNub Ruby-based APIs.
These are the basics for getting started with Ruby 3.0+ Apps and sending events directly from your server to your End-users. Note this also works for Mobile Apps that run on iOS Web Browsers or Android Browsers. Also old versions of IE are supported for this mechanism. In addition you could optionally consider server sent events from your Rails servers directly to Native iOS applications and Native Android Applications. If you have any questions ask them here on this Forum.
I've built a realtime rails gem and a sample realtime server (node.js) which enables easy realtime messaging without the need of a paid, third party, such as Pusher or PubNub. It works with Rails 3+.
Related
I have an API where users can create, what I call, orders.
I enqueue those orders and process them via Sidekiq gem. When the process is done, I currently send an email to the user. However, I am looking on how to notify him programatically.
So, sending the user a POST request to a particular endpoint, telling him that the order has been processed.
I am wondering which kind of security or other technical things I should take into account when doing this, or if there is any kind of gem that would help me on developing this.
you can check pub/sub pattern to do this...
when sidekiq finish processing then you publish an event... and you register the browser to listen to this event... which is better than sending the user a POST request to a particular endpoint, telling him that the order has been processed.
there are many libraries out there that can help you implementing the pub/sub pattern check the following...
PubNub
Pusher
Bunny
RabbitMQ
Redis
please note that you will have to use the rails app as the publisher and the front end as the subscriber ( you can check equivalent libs for JS )
and if you are interested in implementing the pub/sub within the same rails app... i've looked a lot and found that only those are the working solutions ( for app to publish and listen to his published events without getting locked in the process )
EventBus
Event_BG_Bus
Wisper
this is a post on how to use those gems to implement pub/sub pattern
I am working in a Rails application and below is the scenario requiring a solution.
I'm doing some time consuming processes in the background using Sidekiq and saves the related information in the database. Now when each of the process gets completed, we would like to show notifications in a separate area saying that the process has been completed.
So, the notifications area really need to pull things from the back-end (This notification area will be available in every page) and show it dynamically. So, I thought Ajax must be an option. But, I don't know how to trigger it for a particular area only. Or is there any other option by which Client can fetch dynamic content from the server efficiently without creating much traffic.
I know it would be a broad topic to say about. But any relevant info would be greatly appreciated. Thanks :)
You're looking at a perpetual connection (either using SSE's or Websockets), something Rails has started to look at with ActionController::Live
Live
You're looking for "live" connectivity:
"Live" functionality works by keeping a connection open
between your app and the server. Rails is an HTTP request-based
framework, meaning it only sends responses to requests. The way to
send live data is to keep the response open (using a perpetual connection), which allows you to send updated data to your page on its
own timescale
The way to do this is to use a front-end method to keep the connection "live", and a back-end stack to serve the updates. The front-end will need either SSE's or a websocket, which you'll connect with use of JS
The SEE's and websockets basically give you access to the server out of the scope of "normal" requests (they use text/event-stream content / mime type)
Recommendation
We use a service called pusher
This basically creates a third-party websocket service, to which you can push updates. Once the service receives the updates, it will send it to any channels which are connected to it. You can split the channels it broadcasts to using the pub/sub pattern
I'd recommend using this service directly (they have a Rails gem) (I'm not affiliated with them), as well as providing a super simple API
Other than that, you should look at the ActionController::Live functionality of Rails
The answer suggested in the comment by #h0lyalg0rithm is an option to go.
However, primitive options are.
Use setinterval in javascript to perform a task every x seconds. Say polling.
Use jQuery or native ajax to poll for information to a controller/action via route and have the controller push data as JSON.
Use document.getElementById or jQuery to update data on the page.
I'm using pusher gem to manipulate my front-end from an external API. It works fine, no problem with that.
But the thing I wonder is if there is a possibility to use push notifications at the back-end of my application? I spent a serious amount of time investigating this but couldn't find something useful.
Let me summarize:
I have an application and another API application which is tightly interacting with other. Sometimes I want to use my API to send notification to my main application and I want to be able to manipulate data at the back-end of my main application regarding the data received from API side. These are things like 'an action was completed/started/succeed' etc...
I understand that 'pusher' receives push notifications by JavaScript at the front-end. But I believe that there must be a way to use those notifications at the back-end as well.
If there is another way (maybe Faye? Websocket) to do that I'd love to learn what it is. Any clue would be appreciated.
Is it something doable?
Thank you
Pusher is a backend system too (to "push" updates to channels)
Endpoints
I think you may be interested in endpoints
From what I can gather, it seems you're looking to trigger the transfer of data to an endpoint once an action occurs in your API? For example:
User signs up on "API" app
API app sends "notification" to main app
Main app increases user count by 1
The way I can see this working is by either using ajax, or sending a curl request to your main app's endpoint (set in routes), triggering the action:
#main_app/config/routes.rb
post "endpoint", to: "application#endpoint"
#main_app/controllers/application_controller.rb
def endpoint
#count = Option.increment!(:user_count)
end
This will allow you to manipulate your data in the backend of your "main" app
API
The tricky, non-conventional part comes when you want to send the data from your API app to your Main app (this is where you got the "pusher" idea from)
I would personally look at sending a standard HTTP request to the Main app endpoint, probably with Curl (if from the backend):
Curl on Ruby on Rails
Rails curl syntax
You may want to install curb (CUrl RuBy) here: https://github.com/taf2/curb
I could write some code if you wanted?
I had asked the same question to the Pusher's support team and I got the exact answer I was looking for.
You can install a client library on your server
(http://pusher.com/docs/client_libraries) if there is one for your
server. You can then subscribe to a client channel this way.
In my case, I use Ruby gem which can be reached from https://github.com/pusher/pusher-ruby-client .
I have an analytics engine which periodically packages a bunch of stats in JSON format. I want to send these packages to a Rails server. Upon a package arriving, the Rails server should examine it, generate a model instance out of it (for historical purposes), and then display the contents to the user. I've thought of two approaches.
1) Have a little app residing on the same host as the Rails server to be listening for these packages (using ZeroMQ). Upon receiving a package, the app would invoke a Rails action through CURL, passing on the package as a parameter. My concern with this approach is that my Rails server checks that only signed-in users can access actions which affect models. By creating an action accessible to this listening app (and therefore other entities), am I exposing myself to a major security flaw?
2) The second approach is to simply have the listening app dump the package into a special database table. The Rails server will then periodically check this table for new packages. Upon detecting one or more, it will process them and remove them from the table.
This is the first time I'm doing something like this, so if you have techniques or experiences you can share for better solutions, I'd love to learn.
Thank you.
you can restrict access to a certain call by limiting the host name that is allowed for the request in routes.rb
post "/analytics" => "analytics#create", :constraints => {:ip => /127.0.0.1/}
If you want the users to see updates, you can use polling to refresh the page every minute orso.
1) Yes you are exposing a major security breach unless :
Your zeroMQ app provides the needed data to do authentification and authorization on the rails side
Your rails app is configured to listen only on the 127.0.0.1 interface and is thus not accessible from the outside
Like Benjamin suggests, you restrict specific routes to certain IP
2) This approach looks a lot like what delayed_job does. You might wanna take a look there : https://github.com/collectiveidea/delayed_job and use a rake task to add a new job.
In short, your listening app will call a rake task that will add a custom delayed_job when receiving a packet. Then let delayed_job handle the load. You benefit from delayed_job goodness (different queues, scaling, ...). The hard part is getting the result.
One idea would be to associated a unique ID with each job, and have the delayed_job task output the result in a data store wich associated the job ID with the result. This data store can be a simple relational table
+----+--------+
| ID | Result |
+----+--------+
or a memecache/redis/whatever instance. You just need to poll that data store looking for the result associated with the job ID. And delete everything when you are done displaying that to the user.
3) Why don't you directly POST the data to the rails server ?
Following Benjamin's lead, I implemented a filter for this particular action.
def verify_ip
#ips = ['127.0.0.1']
if not #ips.include? request.remote_ip
redirect_to root_url
end
end
The listening app on the localhost now invokes the action, passing the JSON package received from the analytics engine as a param. Thank you.
I am to build a web application which will accept different events from external sources and present them quickly to the user for further actions. I want to use Ruby on Rails for the web application. This project is a internal development project. I would prefer simple and easy to use solutions for rapid development over high reliable and complex systems.
What it should do
The user has the web application opened in his browser. Now an phone call comes is. The phone call is registered by a PBX monitoring daemon. In this case via the Asterisk Manager Interface. The daemon sends the available information (remote extension, local extension, call direction, channel status, start time, end time) somehow to the web application. Next the user receives a notified about the phone call event. The user now can work with this. For example by entering a summary or by matching the call to a customer profile.
The duration from the first event on the PBX (e.g. the creation of a new channel) to the popup notification in the browser should be short. Given a fast network I would like to be within two seconds. The single pieces of information about an event are created asynchronously. The local extension may be supplied separate from the remote extension. The user can enter a summary before the call has ended. The end time, new status etc. will show up on the interface as soon as one party has hung up.
The PBX monitor is just one data source. There will be more monitors like email or a request via a web form. The monitoring daemons will not necessarily run on the same host as the database or web server. I do not image the application will serve thousands of logged in users or concurrent requests soon. But from the design 200 users with maybe about the same number of events per minute should not be a scalability issue.
How should I do?
I am interested to know how you would design such an application. What technologies would you suggest? How do the daemons communicate their information? When and by whom is the data about an event stored into the main database? How does the user get notified? Should the browser receive a complete dataset on behalf of a daemon or just a short note that new data is available? Which JS library to use and how to create the necessary code on the server side?
On my research I came across a lot of possibilities: Message brokers, queue services, some rails background task solutions, HTTP Push services, XMPP and so on. Some products I am going to look into: ActiveMQ, Starling and Workling, Juggernaut and Bosh.
Maybe I am aiming too hight? If there is a simpler or easier way, like just using the XML or JSON interface of Rails, I would like to read this even more.
I hope the text is not too long :)
Thanks.
If you want to skip Java and Flash, perhaps it makes sense to use a technology in the Comet family to do the push from the server to the browser?
http://en.wikipedia.org/wiki/Comet_%28programming%29
For the sake of simplicity, for notifications from daemons to the Web browser, I'd leave Rails in the middle, create a RESTful interface to that Rails application, and have all of the daemons report to it. Then in your daemons you can do something as simple as use curl or libcurl to post the notifications. The Rails app would then be responsible for collecting the incoming notifications from the various sources and reporting them to the browser, either via JavaScript using a Comet solution or via some kind of fatter client implemented using Flash or Java.
You could approach this a number of ways but my only comment would be: Push, don't pull. For low latency it's not only quicker it's more efficient, as your server now doesn't have to handle n*clients once a second polling the db/queue. ActiveMQ is OK, but Starling will probably serve you better if you're not looking for insane levels of persistence.
You'll almost certainly end up using Flash on the client side (Juggernaut uses it last time I checked) or Java. This may be an issue for your clients (if they don't have Flash/Java installed) but for most people it's not an issue; still, a fallback mechanism onto a pull notification system might be prudent to implement.
Perhaps http://goldfishserver.com might be of some use to you. It provides a simple API to allow push notifications to your web pages. In short, when your data updates, send it (some payload data) to the Goldfish servers and your client browsers will be notified, with the same data.
Disclaimer: I am a developer working on goldfish.
The problem
There is an event - either external (or perhaps internally within your app).
Users should be notified.
One solution
I am myself facing this problem. I haven't solved it yet, but this is how I intend to do it. It may help you too:
(A) The app must learn about the event (via an exposed end point)
Expose an end point by which you app can be notified about external events.
When the end point is hit (and after authentication then users need to be notified).
(B) Notification
You can notify the user directly by changing the DOM on the current web page they are on.
You can notify users by using the Push API (but you need to make sure your browsers can target that).
All of these notification features should be able to be handled via Action Cable: (i) either by updating the DOM to notify you when a phone call comes in, or (ii) via a push notification that pops up in your browser.
Summary: use Action Cable.
(Also: why use an external service like Pusher, when you have ActionCable at your disposal? Some people say scalability, and infrastructure management. But I do not know enough to comment on these issues. )