さて、あなた自身のストレージを実装することはあなたのためのオプションかもしれません。このドキュメントは、あなたがする必要があるのは、、、および(最後の段落を参照)の3つのメソッドを実装することだけであることを示して.get
い.set
ます.destroy
。これは次のようになります(node-redisライブラリを使用し、元のconnect-redisストアを少し変更します):
var redis = require("redis"),
redis_client = redis.createClient(),
session_prefix = 'session::',
lock_suffix = '::lock',
threshold = 5000,
wait_time = 250,
oneDay = 86400;
/* If timeout is greater then threshold, then we assume that
one of the Redis Clients is dead and he cannot realese
the lock. */
function CustomSessionStore(opts) {
opts = opts || {};
var self = this;
self.ttl = opts.ttl; // <---- used for setting timeout on session
self.lock = function(sid, callback) {
callback = callback || function(){};
var key = session_prefix + sid + lock_suffix;
// try setting the lock with current Date
redis_client.setnx(key, Date.now( ), function(err, res) {
// some error handling?
if (res) {
// Everything's fine, call callback.
callback();
return;
}
// setnx failed, look at timeout
redis_client.get(key, function(err, res) {
// some error handling?
if (parseInt(res) + threshold > Date.now( )) {
// timeout, release the old lock and lock it
redis_client.getset(key, Date.now( ), function(err, date) {
if (parseInt(date) + threshold > Date.now()) {
// ups, some one else was faster in acquiring lock
setTimeout(function() {
self.lock(sid, callback);
}, wait_time);
return;
}
callback();
});
return;
}
// it is not time yet, wait and try again later
setTimeout(function() {
self.lock(sid, callback);
}, wait_time);
});
});
};
self.unlock = function(sid, callback) {
callback = callback || function(){};
var key = session_prefix + sid + lock_suffix;
redis_client.del(key, function(err) {
// some error handling?
callback();
});
};
self.get = function(sid, callback) {
callback = callback || function(){};
var key = session_prefix + sid;
// lock the session
self.lock(sid, function() {
redis_client.get(key, function(err, data) {
if (err) {
callback(err);
return;
}
try {
callback(null, JSON.parse(data));
} catch(e) {
callback(e);
}
});
});
};
self.set = function(sid, data, callback) {
callback = callback || function(){};
try {
// ttl used for expiration of session
var maxAge = sess.cookie.maxAge
, ttl = self.ttl
, sess = JSON.stringify(sess);
ttl = ttl || ('number' == typeof maxAge
? maxAge / 1000 | 0
: oneDay);
} catch(e) {
callback(e);
return;
}
var key = session_prefix + sid;
redis_client.setex(key, ttl, data, function(err) {
// unlock the session
self.unlock(sid, function(_err) {
callback(err || _err);
});
});
};
self.destroy = function(sid, callback) {
var key = session_prefix + sid;
redis_client.del(key, function(err) {
redis_client.unlock(sid, function(_err) {
callback(err || _err);
});
});
};
}
補足.lock
:とのエラー処理は実装していません.unlock
。これはあなたにお任せします!:)いくつかの小さな間違いがあるかもしれませんが(私は現在NodeJSを持っておらず、これを私の記憶から書いています:D)、あなたはその考えを理解する必要があります。これは、 Redisのロック/ロック解除の使用方法に関する説明を含むリンクです。setnx
もう1つの注意:ルートが例外をスローした場合、Redisセッションのロックが解除されないため、ルートに対してカスタムエラー処理を行うことをお勧めします。この.set
メソッドは常にルートの最後のものとして呼び出され.get
ます。これは、Expressがルートの最初で呼び出すメソッドとは逆です(そのため、でロック.get
およびロック解除し.set
ます)。それでも5秒間だけロックされるので、問題になる必要はありません。ニーズ(特に変数)threshold
に合わせて調整することを忘れないでください。wait_time
最後の注意:このメカニズムでは、リクエストハンドラーはユーザーごとに次々にのみ起動します。これは、ユーザーごとに同時ハンドラーを実行できないことを意味します。これは問題になる可能性があるため、別のアイデアは、セッションの外部でデータを保持し、手動でロック/ロック解除を処理することです。結局のところ、手動で処理しなければならないことがいくつかあります。
お役に立てば幸いです。幸運を!