// Copyright 2015 The MemDB Authors. // // 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. See the AUTHORS file // for names of contributors. 'use strict'; // run with node >= 0.12 with --harmony option // If logLevel >= INFO, change log4js.json - set appender type to fileSync (otherwise log buffer may eat out memory) var minimist = require('minimist'); var crypto = require('crypto'); var P = require('bluebird'); var _ = require('lodash'); var uuid = require('node-uuid'); var env = require('./env'); var memdb = require('../lib'); var mongodb = P.promisifyAll(require('mongodb')); var logger = memdb.logger.getLogger('test', __filename); var isMaster = true; var concurrency = 1000; var areaCount = 200; var maxAreaPlayers = 10; var randomRoute = false; // turn on this can slow down performance var newPlayerIntervalValue = 10; var currentConcurrency = 0; var route = function(id){ var shardIds = Object.keys(env.config.shards); if(id === null || id === undefined){ return _.sample(shardIds); } var md5 = crypto.createHash('md5').update(String(id)).digest('hex'); var hash = parseInt(md5.substr(0, 8), 16); var index = randomRoute ? _.random(shardIds.length - 1) : (hash % shardIds.length); return shardIds[index]; }; var playerThread = P.coroutine(function*(db, playerId){ var Player = db.collection('player'); var Area = db.collection('area'); var playInArea = P.coroutine(function*(playerId, areaId){ // join area var success = yield db.transaction(P.coroutine(function*(){ var area = yield Area.find(areaId); if(!area){ area = {_id : areaId, playerCount : 0}; yield Area.insert(area); } if(area.playerCount >= maxAreaPlayers){ return false; } yield Area.update(areaId, {$inc : {playerCount : 1}}); yield Player.update(playerId, {$set : {areaId : areaId}}); return true; }), route(areaId)); if(!success){ return; } for(var i=0; i<_.random(10); i++){ yield P.delay(_.random(1000)); // earn scores from other players in the area yield db.transaction(P.coroutine(function*(){ var players = yield Player.find({areaId : areaId}); if(players.length <= 1){ return; } for(var i=0; i= concurrency){ return; } currentConcurrency++; var playerId = uuid.v4(); try{ logger.warn('player %s start', playerId); logger.warn('current concurrency: %s', currentConcurrency); yield playerThread(autoconn, playerId); } catch(e){ logger.error('player %s error: %s', playerId, e.stack); } finally{ logger.warn('player %s finish', playerId); currentConcurrency--; } }), newPlayerIntervalValue); process.on('SIGTERM', shutdown); process.on('SIGINT', shutdown); }); if (require.main === module) { var opts = minimist(process.argv.slice(2)); main(opts); }