thunk(function *() { var consumers = [] var messages = [] while (messages.length < messageCount) { messages.push(messages.length) } while (consumers.length < consumerCount) { consumers.push(new Consumer(host, { path: '/websocket', token: producer.signAuth({userId: Consumer.genUserId()}) })) } yield io.clearRoom('benchmark') // 注册 consumers 消息处理器 var thunkQueue = ThunkQueue() consumers.forEach(function (consumer, index) { var received = 0 thunkQueue.push(thunk(function (done) { consumer.message = function (message) { received++ if (message === null) this.close() else if (!index && (received % 10000) === 0) process.stdout.write('.') } consumer.onerror = function (err) { console.error(err) done(err) } consumer.onclose = done })) }) // 等待 consumers 连接并加入 chaos room yield consumers.map(function (consumer) { return thunk(function (done) { consumer.onopen = function () { producer.joinRoom('benchmark', consumer.consumerId, done) } consumer.connect() }) }) // 开始发送消息 var time = Date.now() while (messages.length) { producer.sendMessage('benchmark', JSON.stringify(messages.shift())) if ((messages.length % 10000) === 0) process.stdout.write('.') } producer.sendMessage('benchmark', JSON.stringify(null)) // 等待 consumers 所有消息处理完毕 yield thunkQueue.end() time = (Date.now() - time) / 1000 var ops = Math.floor(messageCount * consumerCount / time) yield io.clearRoom('benchmark') console.log(`\n${consumerCount} consumers, ${messageCount * consumerCount} messages, ${time.toFixed(2)} sec, ${ops} messages/sec`) })(tools.logErr)
L.calculateList = function *(list_id) { console.log('caculate list', list_id) let list = yield db.list.load({id: list_id}) if (!list) throw new Error('no list') let defaultList = { total_interest: 0, total_paid: 0, total_sum: 0, bill_type: db.list.BILL_TYPE.UNKNOWN, three_days_free: 0, total_bill_num: 0 } let defaultExtra = { bankInfo: {} } _.assign(list, defaultList) _.assign(list.extra, defaultExtra) let isFuture = false if (list.transaction_type === db.list.TRANSACTION_TYPE.BUY_RETURN || list.transaction_type === db.list.TRANSACTION_TYPE.SELL_RETURN) { isFuture = true } let listbills = yield db.listbill.findWithBill({list_id: list_id}) let queue = Queue() for (let i in listbills) { let bill = listbills[i].bill let listbill = listbills[i].listbill list.total_bill_num++ list.total_sum += bill.sum list.bill_type = list.bill_type !== db.list.BILL_TYPE.UNKNOWN && list.bill_type !== bill.bill_type ? db.list.BILL_TYPE.MIXED : bill.bill_type let bankInfo = list.extra.bankInfo[bill.accept_bank_type] = list.extra.bankInfo[bill.accept_bank_type] || { num: 0, sum: 0 } bankInfo.num ++ bankInfo.sum += bill.sum let interestDays = 0 if (!bill.is_calculated_holiday) { bill.holiday = yield calculateHolidays(bill.end_date) yield db.bill.update(bill.id, {holiday: bill.holiday, is_calculated_holiday: 1}) } if (isFuture) { interestDays = moment(list.future_date).diff(moment(list.transaction_date), 'days', true) } else { interestDays = moment(bill.end_date).diff(moment(list.transaction_date), 'days', true) if (list.is_delay) interestDays += bill.holiday if (!list.is_local) interestDays += 3 } interestDays = Math.max(0, interestDays) interestDays = Math.ceil(interestDays) let interest = bill.sum * list.interest_rate / 100 * interestDays / ONE_YEAR interest = Math.round(interest * 100) / 100 let listbillInfo = { interest_rate: list.interest_rate, interest_calculated_days: interestDays, interest: interest, paid: bill.sum - interest } queue.push(db.listbill.update(listbill.id, listbillInfo)) list.total_interest += interest list.total_paid += bill.sum - interest queue.push(L.calculateBillForUser(bill.id, list.User_id)) } queue.push(db.list.update(list.id, list)) if (list.status === db.list.STATUS_TYPE.CONFIRMED || list.status === db.list.STATUS_TYPE.DELETED) { yield L.calculateUserStatics(list.user_id) } yield queue.end return list }
tman.it('2000 messages, 200 rooms, 50 consumers', function * () { var consumers = [] var messages = [] var rooms = [] while (messages.length < 2000) messages.push(messages.length) while (rooms.length < 200) rooms.push('room' + rooms.length) while (consumers.length < 50) { consumers.push(new Consumer(host, { path: '/websocket', transports: ['websocket'], // easy to trigger "xhr poll error" token: producer.signAuth({userId: Consumer.genUserId()}) })) } // 注册 consumers 消息处理器 var thunkQueue = ThunkQueue() consumers.forEach(function (consumer, index) { var received = [] thunkQueue.push(thunk(function (done) { consumer.message = function (message) { if (message === null) { // 不同的 room 不能保证时序 received.sort(function (a, b) { return a - b }) if (JSON.stringify(received) !== JSON.stringify(messages)) console.log(JSON.stringify(received)) assert.deepEqual(received, messages) done() } else { received.push(message) } } consumer.onerror = done })) }) // 等待 consumers 连接并加入 chaos room yield consumers.map(function (consumer) { return thunk(function (done) { consumer.onopen = function () { thunk.all(rooms.map(function (room) { return producer.joinRoom(room, consumer.consumerId) }))(done) } consumer.connect() }) }) // 开始发送消息 var _messages = messages.slice() var room = rooms[0] while (_messages.length) { let random = Math.ceil(Math.random() * 200) // 等待 random 毫秒 yield thunk.delay(random) // 并发发送 random 条消息 let todo = _messages.splice(0, random) room = rooms[random] || rooms[0] while (todo.length) producer.sendMessage(room, JSON.stringify(todo.shift())) process.stdout.write('.') } yield thunk.delay(1000) producer.sendMessage(room, JSON.stringify(null)) // 等待 consumers 所有消息处理完毕 yield thunkQueue.end() })