Skip to content
Yu Xia edited this page Jun 30, 2015 · 10 revisions

Prerequisites

Pomelo

Quick-pomelo is based on pomelo, you should first understand the pomelo framework.

MemDB

Quick-pomelo use memdb to manage data model and data access, so understanding memdb is required.

Architecture

architecture

IMPORTENT

Components by folder

app

> models

Define all your data models here.

Model is just mdbgoose schema, you should write models as below.

// app/models/player.js
// app is pomelo instance passed by framework
module.exports = function(app){
    // get mdbgoose instance
    var mdbgoose = app.memdb.goose;
    // define mdbgoose model
    var PlayerSchema = new mdbgoose.Schema({
        _id : {type : String},
        areaId : {type : String},
        teamId : {type : String},
        connectorId : {type : String},
        name : {type : String},
    }, {collection : 'players'});

    mdbgoose.model('Player', PlayerSchema);
};

You can access models by

var Player = app.models.Player;

Note that database index should be defined inside .memdb.js

> controllers

Put all controllers here.

Write all your business logic in controller as below

// app/controllers/player.js
// app is passed from framework
var Controller = function(app){
    this.app = app;
};
// define controller methods
Controller.prototype.createPlayerAsync = function(opts){
    var player = new this.app.models.Player(opts);
    yield player.saveAsync();
};
// export controller
module.exports = function(app){
    return new Controller(app);
};

You can access controllers by

var playerController = app.controllers.player;

> routes

For each type of server, write a route in app/routes directory.

A route function accepts a request info (as session, method, msgs), and output a routing key. Routing key is string, requests with the same routing key will be always forwarded to the same backend server.

Writing route properly is crucial for performance, please read performance optimize.

Please write routes as below

// app/routes/player.js
// router for serverType 'player'
module.exports = {
    // Route for handler
    handler : function(session, method, msg){
        // Return a string routing key
        return session.uid || msg.playerId;
    },
    // Route for remote
    remote : function(routeParam, method, args){
        // Return a string routing key
        return routeParam;
    }
};

If no routes provided, the backend server forwarded is undetermined.

config

> [env]/memdb.json

Memdb client config

Every pomelo server is a memdb client, which use pomelo server id (by app.getServerId()) as the routing shardId for memdb transaction. Although not required, there is 1-1 relationship between a pomelo server and a memdb shard.

{
    "shards" : {
        // pomelo serverId : memdb shard host and port
        "area-server-1" : {
            "host" : "127.0.0.1",
            "port" : 31017
        },
        "area-server-2" : {
            "host" : "127.0.0.1",
            "port" : 31018
        },
        // ......
    }
}

> .memdb.js

Memdb server config, please refer to .memdb.js wiki. Specify the config file by --conf=[path to .memdb.js] when you operate memdb

> .memdb.index.js

Database index definition, this is included by .memdb.js

app.js

Main script, some extra code should be added to load quick-pomelo components.

This is the minimum setup, you can start with the template/app.js

var quick = require('quick-pomelo');
//...

app.configure('all', function(){
    //...

    // Configure memdb client
    app.loadConfigBaseApp('memdbConfig', 'memdb.json');

    // Load components
    app.load(quick.components.memdb);
    app.load(quick.components.controllers);
    app.load(quick.components.routes);

    // Configure filter
    app.filter(quick.filters.transaction(app));

    //...
});

Built-in Controllers

We have implemented some useful built-in controllers, you can leverage them

Integrate built-in controllers

Here is how to make built-in controllers available in your code, we assume you want to use build-in 'push' controller

  • create push.js in app/models, add following code
module.exports = require('quick-pomelo').models.push;
  • create push.js in app/controllers, add following code
module.exports = require('quick-pomelo').controllers.push;
  • Get controller instance
var pushController = app.controllers.push;

Push

A powerful push service, you can use push controller to implement chat, notification in your game, features:

  • Channel subscribe control
  • Message history persistent
  • Offline message

Push API reference

Miscellaneous

timer component

Some time we need to delay execute or repeat in an interval. Timer component is useful which put every callback inside one transaction. Do not access memdb in native setTimeout/setInterval callback.

Usage

// Load the timer component
app.load(quick.components.timer);

var timeout = app.timer.setTimeout(function(){
    // this is executed inside a single transaction
}, 1000);
clearTimeout(timeout);

var interval = app.timer.setInterval(fn, 1000);
clearInterval(interval);

// You can also specify an id for the timer as below
app.timer.setInterval(fn, 1000, id);
app.timer.clear(id);

app transaction events

There are app events fired when transaction finish. You can use these event to commit/rollback changes to external resources (not in memdb).

app.on('transactionSuccess', function(){
    // commit changes    
});

app.on('transactionFail', function(){
    // rollback changes
});

use raw memdb API

Although mongoose is powerful, it has performance penalty. You can directly use raw memdb API if performance is an issue.

// Get the autoConnection object for mdbgoose
var autoconn = app.memdb.goose.autoconn;

var player = yield autoconn.collection('player').find({_id : 1});

Clone this wiki locally