We are going to use this app for our migrations demos.
It is a reference sample application that we built and released open source last year at GLSEC.
Available on Github: https://github.com/OSTUSA/ost-todos
A baseline for domain driven .NET applications using an Onion Architecture.
Available on Github: https://github.com/OSTUSA/ndriven
At OST, we leverage NDriven as the base of our projects constantly. We also used it on our recent upgrade of PayItSquare.com.
Node.js is a software platform for scalable server-side and networking applications. Node.js applications are written in JavaScript, and can be run within the Node.js runtime on Windows, Mac OS X and Linux with no changes.
" We are moving every product & every site within PayPal to Node. We started the journey by using it as prototyping framework... by end of 2014 we hope to have all major experiences redesigned, and rewritten on Node.
We are seeing big scale gains, performance boosts and big developer productivity."
Bill Scott - http://www.quora.com/Node-js/What-companies-are-using-Node-js-in-production
"The simple truth is Node has reinvented the way we create websites. Developers build critical functionality in days, not weeks."
Michael Yormark
WSJD Product Operations
More examples here: http://nodejs.org/industry/
Take it over Nic and Jason
BossFoo wants you to add the following features to the Todos application:
However, you are constrained by the following criteria:
You carefully consider what you will need to prototype the new features:
Since you have no hardware budget, you choose to use Amazon S3, a cloud-based file system that scales seamlessly.
There are at least two stacks you could use to build the API:
Goal: Create a Node.js API server that interacts with Amazon S3, and update the AngularJS UI to associate documents with tasks
> express node-server
> npm install aws-sdk
We want to create the following REST API routes:
GET /api/todo/:id/files
GET /api/todo/:id/file/:name
DELETE /api/todo/:id/file/:name
POST /api/todo/:id/files
// imports
var http = require('http'), fs = require('fs'),
express = require('express'), AWS = require('aws-sdk');
// configure AWS
AWS.config.loadFromPath('./aws.json');
var s3 = new AWS.S3();
// startup the HTTP server
app = express();
var httpServer = http.createServer(app);
httpServer.listen(80);
// one of the routes
app.get('/api/todo/:id/files/:name', function(req, res) {
s3.getObject({
Bucket: 'glsec-2014',
Key: 'todos/' + req.params.id + '/' + req.params.name + '.txt'
}, function(err, data) {
if (err || !data) { return res.send(500, err); }
var buff = new Buffer(data.Body, "binary");
res.send(buff);
});
});
This is a simplified (but runnable) version of the code.
Goal: Create an Admin interface so the system can be monitored in real-time.
Server
// ... continued from Phase 1 server code ...
var socketIo = require('socket.io');
var sockets = [];
io = socketIo.listen(httpServer);
io.sockets.on('connection', function(socket) {
sockets.push(socket);
socket.emit('log', { msg: 'Hello' });
});
Client
<script src="socket.io.js"></script>
<script>
// ... AngularJS client code ...
var socket = io.connect('http://api.foofactory.net');
socket.on('log', function (data) {
// log message
});
</script>
This is a simplified (but runnable) version of the code.
Goal: Allow the system to be easily scaled by Admins.
For this phase, we created mock instances that pretend to see user activity.
Load-Balanced Instances
// workerInstance.js: Server instances also connect
// to master API server via Socket.IO
var socketIoClient = require('socket.io-client');
var io = socketIoClient.connect('http://api.foofactory.net');
client.on('connect', function() {
client.emit('log', { msg: 'I connected' });
});
Master Server
// ... continued from Phase 2 server code ...
// collect log events from other server instances
socket.on('log', function(data) {
// repeat log to all Admin clients
for (var i = 0; i < sockets.length; i++) {
sockets[i].emit('log', data);
}
});
This is a simplified version of the code.
Goal: For comparison, migrate all of the existing ASP.net MVC API to Node.js.
Leave the client alone. Migrate the following REST APIs to Node.js:
GET /api/todolist/:id/todos
: Get todos for a listPOST /api/todolist/:id/todos
: Post a todo to a listGET /api/todolists
: Get all of the todos for the userGET /api/todolist/:id
: Get a specific todolistDELETE /api/todolist/:id
: Deletes a specific todolistPOST /api/todolist
: Creates a todolist
// todolist.js
var mongoose = require('mongoose');
var todoSchema = mongoose.Schema({
Title: String,
Completed: Boolean
});
var todoListSchema = mongoose.Schema({
Name: String,
OwnerId: String,
Todos: [todoSchema]
});
// CommonJS exports
exports.Todo = mongoose.model('Todo', todoSchema);
exports.TodoList = mongoose.model('TodoList', todoListSchema);
This is a simplified version of the code.
var TodoList = require('./todolist').TodoList;
app.get('/api/todolists', function(req, res) {
var userId = req.get('userId');
// MongoDB / Mongoose ORM
TodoList.find({ OwnerId: userId }, function(err, lists) {
if (err) { return res.send(500, err); }
if (!lists) { return res.send(404); }
return res.send(lists);
});
});
angular.module("todos.services", ['ngResource']).
factory("TodoList", ['$resource', function ($resource) {
return $resource('/api/todolists/:id', { id: '@Id' });
}]).
}]).
After
angular.module("todos.services", ['ngResource']).
factory("TodoList", ['$resource', function ($resource) {
return $resource('http://api.foofactory.net/api/todolists/:id', { id: '@Id' });
}]).
}]).
This should look the same as Phase 2, now powered by Node.js!
Links: