@@ -5,75 +5,82 @@ const gc = require('think-gc');
5
5
const initSessionData = Symbol ( 'think-session-mysql-init' ) ;
6
6
7
7
/*
8
- DROP TABLE IF EXISTS `think_session`;
9
- CREATE TABLE `think_session` (
10
- `id` int(11) unsigned NOT NULL AUTO_INCREMENT ,
11
- `cookie` varchar(255) NOT NULL DEFAULT '' ,
12
- `data` text ,
13
- `expire` bigint (11) NOT NULL,
14
- PRIMARY KEY (`id`),
15
- UNIQUE KEY `cookie` (`cookie`),
16
- KEY `expire` (`expire`)
17
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
8
+ CREATE TABLE `think_session` (
9
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
10
+ `cookie` varchar(255) NOT NULL DEFAULT '' ,
11
+ `data` text ,
12
+ `expire` bigint(11) NOT NULL DEFAULT '0' ,
13
+ `maxage` int (11) NOT NULL DEFAULT '0' ,
14
+ PRIMARY KEY (`id`),
15
+ UNIQUE KEY `cookie` (`cookie`),
16
+ KEY `expire` (`expire`)
17
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
18
18
*/
19
19
20
20
/**
21
21
* use mysql to store session
22
22
*
23
23
*/
24
24
class MysqlSession {
25
- constructor ( options = { } , ctx ) {
25
+ constructor ( options = { } , ctx , cookieOptions ) {
26
26
assert ( options . cookie , '.cookie required' ) ;
27
- const modelConfig = think . config ( 'model' ) ;
28
- const useModel = modelConfig [ modelConfig . type ] ;
29
- if ( useModel . handle . name . toLowerCase ( ) . indexOf ( 'mysql' ) > - 1 ) {
30
- this . options = Object . assign ( { } , useModel , options ) ;
31
- } else {
32
- this . options = options ;
33
- }
34
- this . mysql = mysql . getInstance ( this . options ) ;
27
+ this . options = options ;
28
+ this . cookieOptions = cookieOptions ;
29
+ this . mysql = mysql . getInstance ( helper . omit ( options , 'cookie' ) ) ;
35
30
this . ctx = ctx ;
36
31
this . data = { } ;
37
32
this . tableName = ( this . options . prefix || '' ) + 'session' ;
33
+ this . status = 0 ;
34
+ this . maxAge = this . options . maxAge || 0 ;
35
+ this . expire = 0 ;
38
36
this . gcType = `session_mysql` ;
39
37
gc ( this , this . options . gcInterval ) ;
40
38
}
41
39
42
-
43
40
[ initSessionData ] ( ) {
44
41
if ( this . initPromise ) {
45
42
return this . initPromise ;
46
43
}
47
44
if ( this . options . fresh || this . status === - 1 ) {
48
- return this . initPromise = Promise . resolve ( ) ;
45
+ this . initPromise = Promise . resolve ( ) ;
46
+ return this . initPromise ;
49
47
}
50
48
51
49
// flush session when request finish
52
50
this . ctx . res . once ( 'finish' , ( ) => {
53
51
this . flush ( ) ;
54
52
} ) ;
55
-
53
+
56
54
this . initPromise = this . mysql . query ( {
57
55
sql : `SELECT * FROM ${ this . tableName } WHERE cookie = ? ` ,
58
56
values : [ this . options . cookie ]
59
57
} ) . then ( row => {
60
- if ( row . length === 0 ) return ;
61
- //session data is expired
62
- if ( row [ 0 ] . expire < Date . now ( ) ) {
58
+ if ( row . length === 0 ) return ;
59
+ // session data is expired
60
+ if ( row [ 0 ] . expire < Date . now ( ) ) {
63
61
return this . delete ( ) ;
64
62
}
65
- let content = row [ 0 ] . data ;
66
- content = JSON . parse ( content ) ;
67
- if ( helper . isEmpty ( content ) ) return ;
68
- this . data = content ;
69
- } ) . catch (
70
- err => console . log ( err )
71
- ) ;
72
-
73
-
63
+ const content = row [ 0 ] . data ;
64
+ this . data = JSON . parse ( content ) || { } ;
65
+ if ( row [ 0 ] . maxAge ) {
66
+ this . maxAge = row [ 0 ] . maxAge ;
67
+ }
68
+ this . expire = row [ 0 ] . expire ;
69
+ this . autoUpdate ( ) ;
70
+ } ) ;
74
71
return this . initPromise ;
75
72
}
76
-
73
+ autoUpdate ( ) {
74
+ if ( this . maxAge && this . expire ) {
75
+ const rate = ( this . expire - Date . now ( ) ) / this . maxAge ;
76
+ if ( rate < this . cookieOptions . autoUpdateRate ) {
77
+ this . status = 1 ;
78
+ this . cookieOptions . maxAge = this . maxAge ;
79
+ // update cookie maxAge
80
+ this . ctx . cookie ( this . cookieOptions . name , this . options . cookie , this . cookieOptions ) ;
81
+ }
82
+ }
83
+ }
77
84
get ( name ) {
78
85
return this [ initSessionData ] ( ) . then ( ( ) => {
79
86
if ( this . options . autoUpdate ) {
@@ -86,9 +93,9 @@ class MysqlSession {
86
93
set ( name , value ) {
87
94
return this [ initSessionData ] ( ) . then ( ( ) => {
88
95
this . status = 1 ;
89
- if ( value === null ) {
96
+ if ( value === null ) {
90
97
delete this . data [ name ] ;
91
- } else {
98
+ } else {
92
99
this . data [ name ] = value ;
93
100
}
94
101
} ) ;
@@ -107,25 +114,25 @@ class MysqlSession {
107
114
this . mysql . execute ( {
108
115
sql : `DELETE FROM ${ this . tableName } WHERE cookie=?` ,
109
116
values : [ this . options . cookie ]
110
- } )
117
+ } ) ;
111
118
} else if ( this . status === 1 ) {
112
119
this . status = 0 ;
113
120
// insert or update data
114
- const maxAge = Date . now ( ) + helper . ms ( this . options . maxAge || 0 ) ;
115
- let fields = [ this . options . cookie , JSON . stringify ( this . data ) , maxAge ] ;
121
+ const expire = Date . now ( ) + this . maxAge ;
122
+ const fields = [ this . options . cookie , JSON . stringify ( this . data ) , expire , this . maxAge ] ;
116
123
this . mysql . execute ( {
117
- sql : `INSERT INTO ${ this . tableName } (cookie, data, expire) VALUES(?, ?, ?)
118
- ON DUPLICATE KEY UPDATE data=?, expire=?` ,
119
- values : [ ...fields , fields [ 1 ] , fields [ 2 ] ]
120
- } )
124
+ sql : `INSERT INTO ${ this . tableName } (cookie, data, expire, maxage ) VALUES(?, ?, ?, ?)
125
+ ON DUPLICATE KEY UPDATE data=?, expire=?, maxage=? ` ,
126
+ values : [ ...fields , fields [ 1 ] , fields [ 2 ] , fields [ 3 ] ]
127
+ } ) ;
121
128
}
122
129
return Promise . resolve ( ) ;
123
130
}
124
131
125
- gc ( ) {
126
- this . mysql . execute ( {
127
- sql : `DELETE FROM ${ this . tableName } WHERE expire < ROUND(UNIX_TIMESTAMP(CURTIME(4)) * 1000)` ,
128
- } )
132
+ gc ( ) {
133
+ return this . mysql . execute ( {
134
+ sql : `DELETE FROM ${ this . tableName } WHERE expire < ${ Date . now ( ) } `
135
+ } ) ;
129
136
}
130
137
}
131
138
module . exports = MysqlSession ;
0 commit comments