cocaine

Node.js framework for Cocaine platform

Cocaine NodeJS Framework

Let's start with simple NodeJS http application.

var http = require('http')
 
var server = new http.Server(function(reqres){
    var body = []
    req.on('data', function(data){
        body.push(data)
    })
    req.on('end', function(){
        res.writeHead(200, {
          'x-any-header': 'x-any-value',
          'content-type': 'text/plain'
        })
        res.end('hello, Cocaine!')
    })
})
 
server.listen(8080)

To get our app working in Cocaine cloud, let's add just a couple of things.

#!/path/to/node
var cocaine = require('cocaine')
var http = cocaine.http // monkey-patches node's original http server 
 
var argv = require('optimist').argv //which is actually a hash 
// looking like { opt: 'value'} 
 
var worker = new cocaine.Worker(argv)
 
var handle = worker.getListenHandle("http") // the handle implements a 
// low-level nodejs' listening tcp socket, and it makes nodejs 
// understand cocaine streams. 
 
var server = new http.Server(...) // the same thing as above 
 
server.listen(handle) // as per [1], start listening on cocaine handle 

To let the cocaine-runtime know what to run in our app, we put manifest.json:

{ "slave":"app.js" }

Since the app.js has to be an executable, we put shebang on first line and don't forget about setting an executable bit.

See the complete app here [2].

git clone url/the_app
cd the_app
npm install
tar -czf ../the_app.tgz
cocaine-tool app upload -n the_app --package ../the_app.tgz --manifest manifest.json
>app the_app has been successfully uploaded

then,

cocaine-tool app start -n the_app -r default
>app the_app started
curl -v http://<cloud.front>/the_app/http/
>...
 
var cocaine = require("cocaine")
 
var cli = new cocaine.Client(["localhost", 10053])
 
var log = new cli.Logger("myprefix") // logs lines like "myprefix/..." 
 
cli.on('error', function(err){
    console.log('client error', err)
})
 
log.on('error', function(err){
    console.log('logger error', err)
})
 
 
log.connect()
 
log.on("connect", function() {
 
    cli.getServices(['geobase'], function(errgeoua){
        var names
        
        log.info("looking up regionId for ip 1.2.3.4")
        
        geo.region_id("1.2.3.4", function(errregionId) {
            if(err) return _handleError(err)
 
            log.debug("found region %d for %s", regionId, "1.2.3.4")
 
            geo.names(regionId, function(errnames){
                if(err) return _handleError(err)
 
                log.debug("names for region %d are %s", regionId, names.join())
 
                geo.coordinates(regionId, function(coords){
                    if(err) return _handleError(err)
 
                    log.debug('coordinates for region %d are %s', regionId, coords.join())
 
                })
            })
        })
    })
})
 
function _handleError(err){
    console.log('service error', err)
}

See client-simple for complete source of the simplest cocaine client app.

To fully control a client to services, you can use Client. It resolves services for you, keeps services cache, and resets resolved services cache on locator disconnect.

var cli = new require('cocaine').Client()
 
var storage = cli.Service('storage')
 
storage.on('error', function(err){
    // reconnect on network error 
})
 
storage.connect()
 
storage.on('connect', function(){
    storage0.write('collection','key','value', function(err){
        if(err){
            console.log('error writing to storage', err)
            return
        }
        
        console.log(done 'writing to storage')
    })
})

See client-reconnect for example of handling various socket-level failures when connecting and communicating to locator and target services.

var cli = new require('cocaine').Client()
var app = cli.Service('the_app')
 
app.connect()
 
app.on('connect', function(){
    app.enqueue('handle','anydata', function(errresult){
        if(err) {
           console.log('app error', err)
        } else {
          console.log('app response is', result)
        }
    })
})
 

[1] http://nodejs.org/api/net.html#net_server_listen_handle_callback