使用 deepstream.io 进行实时投票
Using deepstream.io for real-time voting
我使用 deepstream.io
和 rethinkdb
作为持久性存储,制作了一个实时投票系统的原型。到目前为止,它有效,并且多个浏览器可以保持同步以获取最新的投票计数(见下面的屏幕截图),但是,我不喜欢它的一件事是 vote count
在浏览器中递增,它被发送到 deepstream.io
远程服务器。
客户端浏览器内嵌的JS代码:
/**
* Login to deepstream as Frank
*/
var ds = deepstream( 'localhost:6020' ).login({ username: 'Frank'});
var name = 'upvote';
var upVotes;
var voteText = $('.streaming-prices .vote');
var record = ds.record.getRecord(name);
$('#upvote_btn').click(function() {
// on button click, increment the vote counts
// set the record stored in the rethinkdb storage
record.set({
count: ++upVotes
});
});
record.subscribe('count', function(newVal) {
console.info('count updated, newVal: ', newVal);
upVotes = newVal;
voteText.text(newVal);
});
server.js代码:
var PermissionHandler = require( './permission-handler' );
var DeepstreamServer = require( 'deepstream.io' ),
RdbC = require( 'deepstream.io-storage-rethinkdb' ),
server = new DeepstreamServer();
server.set('host', '0.0.0.0');
server.set('port', 6020);
server.set( 'tcpHost', '0.0.0.0' );
server.set( 'tcpPort', '6022' );
server.set( 'permissionHandler', new PermissionHandler() );
server.set( 'storage', new RdbC({
port: 28015,
host: '127.0.0.1',
splitChar: '/',
database: 'votings',
defaultTable: 'question'
}));
server.start();
所以可以看到客户端的js代码是直接递增票数,更新记录,发送给deepstream.io服务器更新数据库。 我不喜欢这部分,因为我不希望用户搞乱总票数。 相反,我希望客户端只向服务器发送类似 +1
的内容,并让服务器更新持久性的总计数。 我不确定这是否可行,有人可以阐明一下吗?我很感激
说得好,允许客户操纵选票可能不太管用!
我会使用 rpc,这样在浏览器中您可以让受信任的提供商代表用户增加记录。
您需要做的三件事是:
- 通过浏览器请求rpc
- 从 rpc 提供程序(可以响应 rpc 的可信客户端)响应它
- 添加权限以拒绝任何更改非提供者记录的尝试
代码如下所示:
浏览器中的JS代码
/**
* Login to deepstream as Frank
*/
var ds = deepstream( 'localhost:6020' ).login( { username: 'Frank'} );
var voteText = $('.streaming-prices .vote');
var name = 'vote';
var record = ds.record.getRecord( name );
$('#upvote_btn').click(function() {
// on button click, increment the vote counts
// set the record stored in the rethinkdb storage
ds.rpc.make( 'upvote', {}, function( error, response ){
//notify user when upvote succesfull
});
});
record.subscribe('count', function( newVal ) {
console.info( 'count updated, newVal: ', newVal);
voteText.text(newVal);
});
处理投票的 rpc 提供程序
/**
* Login to deepstream as Frank
*/
var ds = deepstream( 'localhost:6021' ).login( { username: 'upvote-provider' } );
var name = 'vote';
var record = ds.record.getRecord( name );
ds.rpc.provide( 'upvote', function( data, response ){
record.set( 'count', record.get( 'count' ) + 1 );
response.send();
});
服务器也应该有权限只允许upvote-provider改变投票。
canPerformAction: function( username, message, callback ) {
/**
* If the user is a provider, it has all permissions
*/
if( username === 'upvote-provider' ) {
callback( null, true );
}
/**
* Otherwise the client request is valid unless it's trying to change the score
*/
else {
var messageObj = Deepstream.readMessage( message );
var isAllowed = messageObj.name !== 'vote' || messageObj.isRead;
var errorMessage = isAllowed ? null : 'Can\'t change votes via client, use \'upvote\' rpc instead';
callback( errorMessage, isAllowed );
}
}
我使用 deepstream.io
和 rethinkdb
作为持久性存储,制作了一个实时投票系统的原型。到目前为止,它有效,并且多个浏览器可以保持同步以获取最新的投票计数(见下面的屏幕截图),但是,我不喜欢它的一件事是 vote count
在浏览器中递增,它被发送到 deepstream.io
远程服务器。
客户端浏览器内嵌的JS代码:
/**
* Login to deepstream as Frank
*/
var ds = deepstream( 'localhost:6020' ).login({ username: 'Frank'});
var name = 'upvote';
var upVotes;
var voteText = $('.streaming-prices .vote');
var record = ds.record.getRecord(name);
$('#upvote_btn').click(function() {
// on button click, increment the vote counts
// set the record stored in the rethinkdb storage
record.set({
count: ++upVotes
});
});
record.subscribe('count', function(newVal) {
console.info('count updated, newVal: ', newVal);
upVotes = newVal;
voteText.text(newVal);
});
server.js代码:
var PermissionHandler = require( './permission-handler' );
var DeepstreamServer = require( 'deepstream.io' ),
RdbC = require( 'deepstream.io-storage-rethinkdb' ),
server = new DeepstreamServer();
server.set('host', '0.0.0.0');
server.set('port', 6020);
server.set( 'tcpHost', '0.0.0.0' );
server.set( 'tcpPort', '6022' );
server.set( 'permissionHandler', new PermissionHandler() );
server.set( 'storage', new RdbC({
port: 28015,
host: '127.0.0.1',
splitChar: '/',
database: 'votings',
defaultTable: 'question'
}));
server.start();
所以可以看到客户端的js代码是直接递增票数,更新记录,发送给deepstream.io服务器更新数据库。 我不喜欢这部分,因为我不希望用户搞乱总票数。 相反,我希望客户端只向服务器发送类似 +1
的内容,并让服务器更新持久性的总计数。 我不确定这是否可行,有人可以阐明一下吗?我很感激
说得好,允许客户操纵选票可能不太管用!
我会使用 rpc,这样在浏览器中您可以让受信任的提供商代表用户增加记录。
您需要做的三件事是:
- 通过浏览器请求rpc
- 从 rpc 提供程序(可以响应 rpc 的可信客户端)响应它
- 添加权限以拒绝任何更改非提供者记录的尝试
代码如下所示:
浏览器中的JS代码
/**
* Login to deepstream as Frank
*/
var ds = deepstream( 'localhost:6020' ).login( { username: 'Frank'} );
var voteText = $('.streaming-prices .vote');
var name = 'vote';
var record = ds.record.getRecord( name );
$('#upvote_btn').click(function() {
// on button click, increment the vote counts
// set the record stored in the rethinkdb storage
ds.rpc.make( 'upvote', {}, function( error, response ){
//notify user when upvote succesfull
});
});
record.subscribe('count', function( newVal ) {
console.info( 'count updated, newVal: ', newVal);
voteText.text(newVal);
});
处理投票的 rpc 提供程序
/**
* Login to deepstream as Frank
*/
var ds = deepstream( 'localhost:6021' ).login( { username: 'upvote-provider' } );
var name = 'vote';
var record = ds.record.getRecord( name );
ds.rpc.provide( 'upvote', function( data, response ){
record.set( 'count', record.get( 'count' ) + 1 );
response.send();
});
服务器也应该有权限只允许upvote-provider改变投票。
canPerformAction: function( username, message, callback ) {
/**
* If the user is a provider, it has all permissions
*/
if( username === 'upvote-provider' ) {
callback( null, true );
}
/**
* Otherwise the client request is valid unless it's trying to change the score
*/
else {
var messageObj = Deepstream.readMessage( message );
var isAllowed = messageObj.name !== 'vote' || messageObj.isRead;
var errorMessage = isAllowed ? null : 'Can\'t change votes via client, use \'upvote\' rpc instead';
callback( errorMessage, isAllowed );
}
}