rmll2015_ccnq4(1).pdf

(214 KB) Pobierz
CCNQ(4)
Stéphane Alnet
RMLL, July 2015
CCNQ was born in 2006.
That’s 9 years ago.
What happened during these 9 years?
Let’s go Historical
v0.x (2006) ssh push
(think ansible)
• System and customer configuration in a single document.
• Only OK when you’re doing a couple changes a day.
• Code was lost in the Carribeans.
v1.5 (2007) Perl (sync)
CouchDB?
• Barely better.
• Code also thankfully lost.
1
v2.0 (2009) Perl async, CouchDB
CouchDB on each call-processing server
Perl async for realtime change management
Task management via CouchDB
Everything: provisioning, rating, UI, . . .
Perl packages
Doing async in Perl is hard.
• No unified model for callbacks.
• Incompatibilities between modules sometimes create hard-to-resolve locking
situations.
• Never was able to get a CouchDB/AMQP/FileSystem synchronization to
work properly.
v3 (2010) Node.js, CouchDB, RabbitMQ
Focus on deployable call-processing
Node.js for async
Debian packages
AMQP for M2M
Host configurations in CouchDB
CouchDB-based DNS
Host configuration changes are dynamically applied (e.g. FreeSwitch XML con-
figuration files generated on the fly +
reloadxml).
Debian packages are hard.
AMQP is verbose. (Also: 1ko limit per message?)
v4 (2014) Node.js, CouchDB, Docker.io, Socket.IO
Docker.io: one app, one container.
Apps built out of tiny components.
package.json & git for (strong) dependency management.
Socket.io for M2M & UI
2
• Host configurations in git(lab)
Host configurations in git(lab) really is a workaround. Ideally should move back
to a database-centric approach to host provisioning. Lots of code to migrate
from CCNQ3, still iterating.
Let’s talk About Code
Guiding Principles
• APIs: REST/JSON and Socket.IO only
No HTML generated on servers, use templating on the client.
• Prefer
changes
over directives
• Same modules on the server and the client: PouchDB, Socket.io-client,
superagent, bluebird (Promises)
Promises
This isn’t 2011 anymore.
serialize cfg,
config
Configure using
config
middlewares.
.then ->
unless cfg.server_only is true
fs.writeFileAsync process.env.FSCONF, xml,
Write FreeSwitch XML configuration (if needed)
.then ->
supervisor.startProcessAsync
Start the call-handler service
.then ->
unless cfg.server_only is true
supervisor.startProcessAsync
Start FreeSwitch (if needed)
.then ->
debug Done
Source: thinkable-ducks/config
3
server
utf-8
freeswitch
Fluent
SuperAgent
.get "#{@cfg.auth_base ? @cfg.proxy_base}/_session"
.accept json
.auth user.name, user.pass
.then ({body}) =>
@session.couchdb_username = body.userCtx.name
@session.couchdb_roles = body.userCtx.roles
@session.couchdb_token = hex_hmac_sha1 @cfg.couchdb_secret, @session.couchdb_username
Source: spicy-action/couchdb-auth Uses package
superagent-as-promised
Also illustrates combining fluent interfaces with Promises.
Domain-Specifc LanguagesDSL
require( zappajs ) cfg.web, ->
@get / , ->
@json
ok: true
name: pkg.name
version: pkg.version
db = new PouchDB cfg.db
@get /forwarding/:number , ->
db.get @param.number
.then (doc) =>
@json forwarding: doc.forwarding
cfg = require process.env.CONFIG ?
pkg = require ./package.json
PouchDB = require pouchdb
db = new PouchDB cfg.db
./local/config.json
require( zappajs ) cfg.web, ->
@on trace: ->
if @session.admin
@broadcast_to trace-servers ,
4
trace , @data
client = require( socket.io-client ) process.env.SOCKET
client.on trace , (doc) ->
client.emit trace_started , host:hostname, in_reply_to:doc
Promise.resolve()
.then ->
trace doc
.then ->
client.emit trace_completed , host:hostname, in_reply_to:doc
.catch (error) ->
client.emit trace_error ,
host: hostname
in_reply_to: doc
error: error
Source: project
nifty-ground.
Note the trick with
Promise.resolve()
which
allows to start the Promise chain whether function
trace
returns a Promise or
not.
Domain-Specifc LanguagesVoicemail
class User
main_menu: ->
@call.get_choice "phrase:voicemail_main_menu"
.then (choice) =>
switch choice
when "1"
@retrieve_new_messages()
.then (rows) =>
@navigate_messages rows, 0
.then =>
@main_menu()
when "3"
@config_menu()
Souce: project
well-groomed-feast,
with some renaming to simplify.
5
Zgłoś jeśli naruszono regulamin