0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

express-session connect-couchdb Error: Document update conflict

Last updated at Posted at 2014-12-21

セッション管理機能を Express にて実装するためのミドルウェアとして express-session がある。
こいつを用いると、セッションデータを保存しておくデータベースには様々なものを選ぶことができる。セッションデータを保存しておくデータベースとして、僕は CouchDB を利用している。

CouchDB を用いるためには、https://github.com/expressjs/session#session-store-implementation を参考にして、API を実装する必要があるが、connect-couchdb というパッケージを利用すると、自分で実装しなくていいから便利である。

express-session と connect-couchdb を組み合わせてセッション管理を実装していると、Error: Document update conflict というエラーに出くわした。

数時間、こいつに悩まされていたのであるが、原因が分かったのでメモしておく。

以下の Sample code は、Error: Document update conflict が必ず発生した。
(少なくとも僕の環境では)

Sample code

app.js

var express = require('express');
var path = require('path');
var morgan = require('morgan');
var http = require("http");
var session = require('express-session');
var ConnectCouchDB = new require("connect-couchdb")(session);


var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
app.use(morgan('dev'));
app.use(express.static(path.join(__dirname, 'public')));

app.use("/", session ({
  name: "test.sid",
  secret: "test",
  rolling: false,
  cookie: {
    httpOnly: true,
    secure: false,
  },
  resave: true,
  proxy: undefined,
  saveUninitialized: true,
  unset: "keep",
  store: new ConnectCouchDB ({
    name: "test_sessions",
    username: "",
    password: "",
    host: "localhost",
    port: "5984"
  })
}));

app.get ("/", function (req, res) {
  console.log(JSON.stringify(req.session));
  req.session.a = Math.random();
  req.session.save(callbackSave);
  req.session.b = Math.random();
  req.session.save(callbackSave);
  res.send("hello world");
});

function callbackSave (error) {
  if (error) {
    throw error;
  }
}

module.exports = app;

エラー原因の推測

// 1. リクエストを受け取ったら、クッキーを取得する。
// 2. クッキーに書かれている session id に該当するドキュメントを CouchDB から取得する。
   req.session 変数に取得したドキュメントの内容が書き込まれる。
app.get ("/", function (req, res) {
  console.log(JSON.stringify(req.session));
  req.session.a = Math.random();
// 3. req.session.a が更新された。これを CouchDB へ書き込む。
//    ここではエラーは発生しない。
  req.session.save(callbackSave);
  req.session.b = Math.random();
// 4. req.session.b が更新された。これを CouchDB へ書き込む。
//    ここでエラーが発生する。
  req.session.save(callbackSave);
  res.send("hello world");
});

詳細なことはソースコードを読まなければ分からないが、2 の時点での CouchDB のドキュメントのリビジョン番号を 100 とする。3 の時点で CouchDB のドキュメントのリビジョン番号が 100 から 101 に更新される。4 の時点でも CouchDB のドキュメントのリビジョン番号を 100 から 101 に更新しようとするが、3 の時点において、既にドキュメントのリビジョン番号が 101 に更新されてしまうため、Conflict となるのだろう。

詳細な調査はしないが、express-session と connect-session を併用する場合には、用法を間違えないことである。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?