DynamoDBSessionManager の期限切れセッションクリア処理が正しく動作しない

DynamoDB で Tomcat のセッション管理を行う の動作確認を行いましたが、一点不具合が見つかったので対処方法をメモしておきます。

まず、DynamoDBSessionManager の仕組みとしましては、簡単に説明すると PersistentManager の永続保存先が DynamoDB になっているという実装になっています。

つまり、実際のセッション管理を DynamoDB で行うのではなく、

メモリ不足を想定したスワップ先、およびフェイルオーバー時にセッション復帰するためのバックアップ先として DynamoDB が利用されます。

タイムアウト処理の際に Tomcat 内のセッションと DynamoDB 内のセッションを削除しますが、クラスタリング環境の場合、明示的にタイムアウト処理が呼ばれるとは限らないため、DynamoDB 内に期限切れのデータが残ることがあります。

DynamoDBSessionManager では ExpiredSessionReaper というスレッドで定期的にDynamoDB 内のデータの掃除を行います。

ただし、この ExpiredSessionReaper、配布されているリリースバージョン 1.0.0/1.0.1 では正常に動作しないようです。

    private boolean isExpired(long sessionDateInMillis) {
        return sessionDateInMillis > (System.currentTimeMillis() + expirationTimeInMillis);
    }

この期限切れ判定が間違っているようです。/trunk では以下のように修正されています。

    private boolean isExpired(long sessionDateInMillis) {
        return sessionDateInMillis < (System.currentTimeMillis() - expirationTimeInMillis);

これで判定については正しい挙動になるのですが、もう一点問題がありました。

ここの expirationTimeInMillis は maxInactiveInterval の値が利用されるのですが、 expirationTimeInMillis はミリ秒に対し maxInactiveInterval は秒の単位のため、 Tomcat に設定されているタイムアウト時間と食い違ってしまいます。

こちらについては DynamoDBSessionManager を以下のように修正することにより対処できます。

        expiredSessionReaper = new ExpiredSessionReaper(dynamo, tableName, this.maxInactiveInterval);
        ↓
        expiredSessionReaper = new ExpiredSessionReaper(dynamo, tableName, this.maxInactiveInterval * 1000);