Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Copyright (c) 2017 Ably

Copyright 2016 Ably Real-time Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: node server.js
39 changes: 33 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,38 @@
[![Ably](https://s3.amazonaws.com/files.ably.io/logo-with-type.png)](https://www.ably.io)
# [Ably](https://www.ably.io) Ably Reactor Queue and Wolfram Alpha demo

---
Ably is a hugely scalable, superfast and secure hosted real-time messaging service for web-enabled devices. [Find out more about Ably](https://www.ably.io).

# Tutorials repository
This demo uses realtime pub/sub to publish questions and subscribe to answers, and uses the [Ably Reactor Queues](https://www.ably.io/reactor) to subscribe to realtime data from a worker server over AMQP. When the worker receives a question, it sends the request to Wolfram Alpha to get the answer, and publishes the answer on a channel so that the browser receives it.

This repository contains the working code for many of the [Ably tutorials](https://www.ably.io/tutorials).
Want to try this demo now? Deploy to Heroku for free:

See [https://www.ably.io/tutorials](https://www.ably.io/tutorials) for a complete list of Ably tutorials. The source code for each tutorial exists as a branch in this repo, see [a complete list of branches in this repo](https://github.com/ably/tutorials/branches).
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/ably/tutorials/tree/queue-wolfram-alpha-nodejs)

To find out more Ably and our realtime data delivery platform, visit [https://www.ably.io](https://www.ably.io)
# Setting up the demo on Heroku

Once the app has been deployed to Heroku using the button above, there a few quick steps needed to get this demo running:

* [Sign up for a free Developer AppId with Wolfram Alpha](http://developer.wolframalpha.com/)
* Configure an environment variable with the Wolfram AppId (replace `[your wolfram app id]` with the AppId from the previous step): `heroku config:set WOLFRAM_APP_ID=[your wolfram app id] --app [heroku app name you assigned for this demo]`
* Log in to your Ably dashboard `heroku addons:open ably --app [heroku app name you assigned for this demo]`
* Set up a queue (in the Queues tab) with the name `wolfram` in the `US East (Virgina)` area.
* Set up a queue rule (button to add rules is further down the page within the Queues tab) with the following:
* Queue - choose the `wolfram` queue you just set up
* Source - choose "Message"
* Channel Filter - enter `"^wolfram:questions"` to ensure that all questions published to the `wolfram:questions` channel are republished into the `wolfram` queue

You are now ready to run the demo: `heroku open --app [heroku app name you assigned for this demo]`

# Ably Reactor

The Ably Reactor provides Queues to consume realtime data, Events to trigger server-side code or functions in respons to realtime data, and Firehose to stream events to other queue or streaming services.

[Find out more about the Ably Reactor](https://www.ably.io/reactor)

# Questions

Please visit http://support.ably.io/ for access to our knowledgebase and to ask for any assistance.

# License

Copyright (c) 2017 Ably Real-time Ltd, Licensed under the Apache License, Version 2.0. Refer to [LICENSE](./LICENSE) for the license terms.
13 changes: 13 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "Ably Wolfram Queue demo",
"description": "A simple demo to demonstrate using Ably Reactor Queues with Wolfram Alpha",
"repository": "https://github.com/ably/tutorials/tree/queue-wolfram-alpha-nodejs",
"logo": "https://files.ably.io/logo-70x70.png",
"keywords": ["Ably", "AMQP", "Wolfram Alpha", "realtime"],
"success_url": "/post-install.html",
"addons": [
{
"plan": "ably:test"
}
]
}
19 changes: 19 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "ably-tutorials",
"author": "Ably <hello@ably.io>",
"description": "Node.js Reactor Queue and Wolfram Alpha tutorial",
"repository": "https://github.com/ably/tutorials",
"license": "Apache-2.0",
"engines": {
"node": ">=0.10"
},
"scripts": {
"start": "node ./server.js"
},
"dependencies": {
"ably": ">=0.9.0-beta",
"amqplib": "^0.4",
"express": ">=4.14.0",
"request": ">=2.79.0"
}
}
49 changes: 49 additions & 0 deletions public/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
$(function() {
/* Set up realtime library and authenticate using token issued from server */
var ably = new Ably.Realtime({ authUrl: '/auth' });
var answersChannel = ably.channels.get('wolfram:answers');
var questionsChannel = ably.channels.get('wolfram:questions');

var $answers = $('#answers'),
$status = $('#status'),
$askButton = $('#ask-btn'),
$question = $('#question');

/* Subscribe to answers published on this channel */
answersChannel.subscribe(function(message) {
var $question = $('<div class="question">').text(message.data.question);
var $answer = $('<div class="answer">').text(message.data.answer);
var $stat = $('<div class="stat">').text("Wolfram took " + message.data.wolframTime + "ms");
$answers.prepend($('<div>').append($stat).append($question).append($answer));
});

$askButton.on('click', function() {
var question = $question.val();
if (question.replace(' ') != '') {
/* Publish question to the Ably channel so that the queue worker receives it via queues */
questionsChannel.publish('question', question, function(err) {
if (err) {
showStatus('Failed to publish question!');
$question.val(question);
return;
}
clearStatus();
});
showStatus('Sending question...');
$question.val('');
}
});

ably.connection.on('connecting', function() { showStatus('Connecting to Ably...'); });
ably.connection.on('connected', function() { clearStatus(); });
ably.connection.on('disconnected', function() { showStatus('Disconnected from Ably...'); });
ably.connection.on('suspended', function() { showStatus('Disconnected from Ably for a while...'); });

function showStatus(text) {
$status.text(text).show();
}

function clearStatus() {
$status.fadeOut(750);
}
});
24 changes: 24 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<html>
<head>
<title>Ably Reactor Queue and Wolfram Alpha demo</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="//code.jquery.com/jquery-3.1.1.min.js" crossorigin="anonymous"></script>
<script src="//cdn.ably.io/lib/ably.min-0.9.js" crossorigin="anonymous"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body>
<h1>Wolfram Alpha</h1>
<div class="col">
<h2>Questions</h2>
<textarea id="question" placeholder="Type a question such as 'How far is Venus from Earth'"></textarea>
<button id="ask-btn">Ask Wolfram</button><span id="status"></span>
<p>
Pressing this button will publish a message to a channel, which will in turn using an <a href="https://www.ably.io/reactor">Ably Reactor Queue</a> rule to republish the message into a queue. The node.js worker server will then consume this message in real time, send the question to Wolfram Alpha using its REST API, and publish the answer back to the client using an Ably channel.
</p>
</div>
<div class="col">
<h2>Answers</h2>
<div id="answers"></div>
</div>
</body>
</html>
40 changes: 40 additions & 0 deletions public/post-install.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<html>
<head>
<title>Ably Reactor Queue and Wolfram Alpha demo</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="//code.jquery.com/jquery-3.1.1.min.js" crossorigin="anonymous"></script>
</head>
<body>
<h1>Finalizing the setup of this demo</h1>

<p>Great, the app is now installed! However we need to you to follow few quick steps to get this demo running:</p>

<ul>
<li><a href="http://developer.wolframalpha.com/">Sign up for a free Developer AppId with Wolfram Alpha</a></li>
<li>Configure an environment variable with the Wolfram AppId (replace <code>[your wolfram app id]</code> with the AppId from the previous step): <code>heroku config:set WOLFRAM_APP_ID=[your wolfram app id] --app <span class="appid">[heroku app name you assigned for this demo]</span></code></li>
<li>Log in to your <a href="https://support.ably.io/support/solutions/articles/3000052373-how-do-i-access-my-app-dashboard-if-i-am-a-heroku-add-on-user-">Ably dashboard</a>: <code>heroku addons:open ably --app <span class="appid">[heroku app name you assigned for this demo]</span></code></li>
<li>Set up a queue (in the Queues tab) with the name <code>wolfram</code> in the <code>US East (Virgina)</code> area.</li>
<li>Set up a queue rule (button to add rules is further down the page within the Queues tab) with the following:

<ul>
<li>Queue - choose the <code>wolfram</code> queue you just set up</li>
<li>Source - choose "Message"</li>
<li>Channel Filter - enter <code>"^wolfram:questions"</code> to ensure that all questions published to the <code>wolfram:questions</code> channel are published into the <code>wolfram</code> queue</li>
</ul>
</li>
</ul>

<p>All done!</p>

<p>
<b><a href="/">View the Reactor Queue and Wolfram Alpha Demo &raquo;</a></b>
</p>
</body>

<script type="text/javascript">
var domain = window.location.host.split(':')[0];
if (domain.match(/\.herokuapp\.com$/)) {
$('.appid').text(domain.replace(/\.herokuapp\.com$/, ''));
}
</script>
</html>
94 changes: 94 additions & 0 deletions public/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 0.85em;
}

h2 {
font-size: 1.2em;
}

.col {
width: 50%;
float: left;
box-sizing: border-box;
padding: 0 1em;
}

textarea#question {
width: 100%;
height: 4em;
margin-bottom: 1em;
}

#answers > div {
box-shadow: 0 0 0.5em #bbb;
margin-bottom: 1.5em;
}

#answers > div .question {
color: orange;
font-style: italic;
padding: 5px;
float: left;
}

#answers > div .stat {
color: #999;
font-size: 0.8em;
float: right;
padding: 5px;
}

#answers > div .answer {
font-weight: bold;
padding: 5px;
clear: both;
}

#status {
color: orange;
padding-left: 1em;
}

button {
-moz-box-shadow: 0px 1px 0px 0px #fff6af;
-webkit-box-shadow: 0px 1px 0px 0px #fff6af;
box-shadow: 0px 1px 0px 0px #fff6af;
background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #ffec64), color-stop(1, #ffab23));
background:-moz-linear-gradient(top, #ffec64 5%, #ffab23 100%);
background:-webkit-linear-gradient(top, #ffec64 5%, #ffab23 100%);
background:-o-linear-gradient(top, #ffec64 5%, #ffab23 100%);
background:-ms-linear-gradient(top, #ffec64 5%, #ffab23 100%);
background:linear-gradient(to bottom, #ffec64 5%, #ffab23 100%);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffec64', endColorstr='#ffab23',GradientType=0);
background-color:#ffec64;
-moz-border-radius:6px;
-webkit-border-radius:6px;
border-radius:6px;
border:1px solid #ffaa22;
display:inline-block;
cursor:pointer;
color:#333333;
font-family:Arial;
font-size:15px;
font-weight:bold;
padding:6px 24px;
text-decoration:none;
text-shadow:0px 1px 0px #ffee66;
}

button:hover {
background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #ffab23), color-stop(1, #ffec64));
background:-moz-linear-gradient(top, #ffab23 5%, #ffec64 100%);
background:-webkit-linear-gradient(top, #ffab23 5%, #ffec64 100%);
background:-o-linear-gradient(top, #ffab23 5%, #ffec64 100%);
background:-ms-linear-gradient(top, #ffab23 5%, #ffec64 100%);
background:linear-gradient(to bottom, #ffab23 5%, #ffec64 100%);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffab23', endColorstr='#ffec64',GradientType=0);
background-color:#ffab23;
}

button:active {
position:relative;
top:1px;
}
42 changes: 42 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const Ably = require('ably');
const Express = require('express');
const ServerPort = process.env.PORT || 3000;
const worker = require('./worker');

const ApiKey = process.env.ABLY_API_KEY || 'INSERT-YOUR-API-KEY-HERE'; /* Add your API key here */
if (ApiKey.indexOf('INSERT') === 0) { throw('Cannot run without an Ably API key. Add your key to server.js'); }

const WolframAppId = process.env.WOLFRAM_APP_ID || 'INSERT-YOUR-WOLFRAM-APP-ID-HERE'; /* Add your Wolfram AppID here */
if (WolframAppId.indexOf('INSERT') === 0) { console.warn('Cannot run without a Wolfram AppID. Add your AppID to server.js'); }

/* Instance the Ably library */
const rest = new Ably.Rest({ key: ApiKey });

/* Start a web server */
const app = Express();

/* Issue token requests to browser clients sending a request to the /auth endpoint */
app.get('/auth', function (req, res) {
rest.auth.createTokenRequest(function(err, tokenRequest) {
if (err) {
res.status(500).send('Error requesting token: ' + JSON.stringify(err));
} else {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(tokenRequest));
}
});
});

if (WolframAppId.indexOf('INSERT') === 0) {
app.get('/', function (req, res) {
res.status(500).send('WolframAppId is not set. You need to configure an environment variable WOLFRAM_APP_ID');
});
}

/* Server static HTML files from /public folder */
app.use(Express.static('public'));
app.listen(ServerPort);

worker.start(ApiKey, WolframAppId, 'wolfram:answers', 'wolfram', 'us-east-1-a-queue.ably.io:5671/shared');

console.log('Open the Wolfram demo in your browser: https://localhost:' + ServerPort + '/');
Loading