var Sequelize = require('sequelize');

module.exports = function (connect)
{
    function MySQLStore(database, user, password, options)
    {
        var self = this;
        options = options || {};
        connect.session.Store.call(this, options);
        
        var sequelize = new Sequelize(database, user, password, options);
        var Session = sequelize.define('Session', {
            sid: Sequelize.STRING,
            expires: Sequelize.DATE,
            json: Sequelize.TEXT
        });
        
        sequelize.sync()
        .on('failure', function (error)
        {
            console.log(error);
        });
        
        // Check once a minute for expired sessions.
        setInterval(function ()
        {
            Session.findAll({where: ['expires < ?', new Date()]}).on('success', function (sessions)
            {
                console.log('Destroying ' + sessions.length + ' expired sessions.');
                for (var i in sessions)
                {
                    sessions[i].destroy();
                }
            })
            .on('failure', function (error)
            {
                console.log('Failed to fetch expired sessions:');
                console.log(error);
            });
        }, 60000);
        
        this.get = function (sid, fn)
        {
            Session.find({where: {sid: sid}}).on('success', function (record)
            {
                var session = record && JSON.parse(record.json);
                fn(null, session);
            })
            .on('failure', function (error)
            {
                fn(error, null);
            });
        };
        
        this.set = function (sid, session, fn)
        {
            Session.find({where: {sid: sid}}).on('success', function (record)
            {
                if (record)
                {
                    clearTimeout(record.expirationTimeoutID);
                }
                else
                {
                    record = Session.build({sid: sid});
                }
                record.json = JSON.stringify(session);
                record.expires = session.cookie.expires || new Date('2050-12-31 23:59:59');
                
                record.save().on('success', function ()
                {
                    fn && fn();
                })
                .on('failure', function (error)
                {
                    fn && fn(error);
                });
            })
            .on('failure', function (error)
            {
                fn && fn(error);
            });
        };
        
        this.destroy = function (sid, fn)
        {
            self.get(sid, function (error, record)
            {
                if (error) return fn && fn(error);
                if (record)
                {
                    record.destroy().on('success', function ()
                    {
                        console.log('Session ' + sid + ' has been destroyed.');
                        fn && fn();
                    })
                    .on('failure', function (error)
                    {
                        console.log('Session ' + sid + ' could not be destroyed:');
                        console.log(error);
                        fn && fn(error);
                    });
                }
                else fn && fn();
            });
        };
        
        this.length = function (callback)
        {
            Session.count()
            .on('success', callback)
            .on('failure', function () { callback(null); });
        };
        
        this.clear = function (callback)
        {
            sequelize.sync({force: true});
        };
    }
    
    MySQLStore.prototype.__proto__ = connect.session.Store.prototype;
    
    return MySQLStore;
};

@@ -139,33 +139,8 @@
   %7B%0A
-        var self = this;%0A
     
@@ -220,32 +220,325 @@
 ions);%0A        %0A
+        var self = this,%0A            forceSync = options.forceSync %7C%7C false,%0A            checkExpirationInterval = options.checkExpirationInterval %7C%7C 1000*60*10, // default 10 minutes.%0A            defaultExpiration = options.defaultExpiration %7C%7C 1000*60*60*24*365; // default 1 year.%0A        %0A
         var sequ
@@ -587,32 +587,41 @@
 word, options);%0A
+        %0A
         var Sess
@@ -726,12 +726,15 @@
 ize.
-DATE
+INTEGER
 ,%0A  
@@ -808,16 +808,34 @@
 ze.sync(
+%7Bforce: forceSync%7D
 )%0A      
@@ -952,25 +952,33 @@
 eck 
-once a minute for
+periodically to clear out
  exp
@@ -1090,21 +1090,53 @@
 ?', 
-new Date()%5D%7D)
+Math.round(Date.now() / 1000)%5D%7D)%0A            
 .on(
@@ -1590,13 +1590,31 @@
  %7D, 
-60000
+checkExpirationInterval
 );%0A 
@@ -1706,32 +1706,45 @@
 re: %7Bsid: sid%7D%7D)
+%0A            
 .on('success', f
@@ -2118,16 +2118,29 @@
 : sid%7D%7D)
+%0A            
 .on('suc
@@ -2488,23 +2488,131 @@
         
-record.
+%0A                // Set expiration to match the cookie or 1 year in the future if unspecified.%0A                var 
 expires 
@@ -2613,16 +2613,17 @@
 pires = 
+(
 session.
@@ -2641,41 +2641,294 @@
 res 
-%7C%7C new Date('2050-12-31 23:59:59'
+?%0A                               new Date(session.cookie.expires) :%0A                               new Date(Date.now() + defaultExpiration));%0A                // Note: JS uses milliseconds, but we want integer seconds.%0A                record.expires = Math.round(expires.getTime() / 1000
 );%0A 
@@ -2972,16 +2972,33 @@
 d.save()
+%0A                
 .on('suc
@@ -3600,16 +3600,37 @@
 estroy()
+%0A                    
 .on('suc

Fix clearing of expired sessions. This uses polling to periodically check for expired sessions.