1
- var DB = require ( 'sharedb' ) . DB ;
2
- var pg = require ( 'pg' ) ;
1
+ import { DB } from 'sharedb' ;
2
+ import pg from 'pg' ;
3
3
4
4
// Postgres-backed ShareDB database
5
5
6
- function PostgresDB ( options ) {
7
- if ( ! ( this instanceof PostgresDB ) ) return new PostgresDB ( options ) ;
8
- DB . call ( this , options ) ;
6
+ class PostgresDB {
7
+ constructor ( options ) {
8
+ DB . call ( this , options ) ;
9
9
10
- this . closed = false ;
10
+ this . closed = false ;
11
11
12
- this . pg_config = options ;
13
- } ;
14
- module . exports = PostgresDB ;
12
+ this . pg_config = options ;
13
+ }
15
14
16
- PostgresDB . prototype = Object . create ( DB . prototype ) ;
17
-
18
- PostgresDB . prototype . close = function ( callback ) {
19
- this . closed = true ;
20
- if ( callback ) callback ( ) ;
21
- } ;
15
+ close ( callback ) {
16
+ this . closed = true ;
17
+ if ( callback ) callback ( ) ;
18
+ }
22
19
23
- function rollback ( client , done ) {
24
- client . query ( 'ROLLBACK' , function ( err ) {
25
- return done ( err ) ;
26
- } )
27
- }
28
-
29
- // Persists an op and snapshot if it is for the next version. Calls back with
30
- // callback(err, succeeded)
31
- PostgresDB . prototype . commit = function ( collection , id , op , snapshot , options , callback ) {
32
- /*
33
- * op: CreateOp {
34
- * src: '24545654654646',
35
- * seq: 1,
36
- * v: 0,
37
- * create: { type: 'http://sharejs.org/types/JSONv0', data: { ... } },
38
- * m: { ts: 12333456456 } }
39
- * }
40
- * snapshot: PostgresSnapshot
41
- */
42
- pg . connect ( this . pg_config , function ( err , client , done ) {
43
- if ( err ) {
44
- done ( client ) ;
45
- callback ( err ) ;
46
- return ;
47
- }
48
- function commit ( ) {
49
- client . query ( 'COMMIT' , function ( err ) {
50
- done ( err ) ;
51
- if ( err ) {
52
- callback ( err ) ;
53
- } else {
54
- callback ( null , true ) ;
55
- }
56
- } )
57
- }
58
- client . query (
59
- 'SELECT max(version) AS max_version FROM ops WHERE collection = $1 AND doc_id = $2' ,
60
- [ collection , id ] ,
61
- function ( err , res ) {
62
- var max_version = res . rows [ 0 ] . max_version ;
63
- if ( max_version == null )
64
- max_version = 0 ;
65
- if ( snapshot . v !== max_version + 1 ) {
66
- return callback ( null , false ) ;
67
- }
68
- client . query ( 'BEGIN' , function ( err ) {
69
- client . query (
70
- 'INSERT INTO ops (collection, doc_id, version, operation) VALUES ($1, $2, $3, $4)' ,
71
- [ collection , id , snapshot . v , op ] ,
72
- function ( err , res ) {
73
- if ( err ) {
74
- // TODO: if err is "constraint violation", callback(null, false) instead
75
- rollback ( client , done ) ;
76
- callback ( err ) ;
77
- return ;
78
- }
79
- if ( snapshot . v === 1 ) {
80
- client . query (
81
- 'INSERT INTO snapshots (collection, doc_id, doc_type, version, data) VALUES ($1, $2, $3, $4, $5)' ,
82
- [ collection , id , snapshot . type , snapshot . v , snapshot . data ] ,
83
- function ( err , res ) {
84
- // TODO:
85
- // if the insert was successful and did insert, callback(null, true)
86
- // if the insert was successful and did not insert, callback(null, false)
87
- // if there was an error, rollback and callback(error)
88
- if ( err ) {
89
- rollback ( client , done ) ;
90
- callback ( err ) ;
91
- return ;
20
+ // Persists an op and snapshot if it is for the next version. Calls back with
21
+ // callback(err, succeeded)
22
+ commit ( collection , id , op , snapshot , options , callback ) {
23
+ /*
24
+ * op: CreateOp {
25
+ * src: '24545654654646',
26
+ * seq: 1,
27
+ * v: 0,
28
+ * create: { type: 'http://sharejs.org/types/JSONv0', data: { ... } },
29
+ * m: { ts: 12333456456 } }
30
+ * }
31
+ * snapshot: PostgresSnapshot
32
+ */
33
+ pg . connect ( this . pg_config , ( err , client , done ) => {
34
+ if ( err ) {
35
+ done ( client ) ;
36
+ callback ( err ) ;
37
+ return ;
38
+ }
39
+ function commit ( ) {
40
+ client . query ( 'COMMIT' , err => {
41
+ done ( err ) ;
42
+ if ( err ) {
43
+ callback ( err ) ;
44
+ } else {
45
+ callback ( null , true ) ;
46
+ }
47
+ } )
48
+ }
49
+ client . query (
50
+ 'SELECT max(version) AS max_version FROM ops WHERE collection = $1 AND doc_id = $2' ,
51
+ [ collection , id ] ,
52
+ ( err , res ) => {
53
+ let max_version = res . rows [ 0 ] . max_version ;
54
+ if ( max_version == null )
55
+ max_version = 0 ;
56
+ if ( snapshot . v !== max_version + 1 ) {
57
+ return callback ( null , false ) ;
58
+ }
59
+ client . query ( 'BEGIN' , err => {
60
+ client . query (
61
+ 'INSERT INTO ops (collection, doc_id, version, operation) VALUES ($1, $2, $3, $4)' ,
62
+ [ collection , id , snapshot . v , op ] ,
63
+ ( err , res ) => {
64
+ if ( err ) {
65
+ // TODO: if err is "constraint violation", callback(null, false) instead
66
+ rollback ( client , done ) ;
67
+ callback ( err ) ;
68
+ return ;
69
+ }
70
+ if ( snapshot . v === 1 ) {
71
+ client . query (
72
+ 'INSERT INTO snapshots (collection, doc_id, doc_type, version, data) VALUES ($1, $2, $3, $4, $5)' ,
73
+ [ collection , id , snapshot . type , snapshot . v , snapshot . data ] ,
74
+ ( err , res ) => {
75
+ // TODO:
76
+ // if the insert was successful and did insert, callback(null, true)
77
+ // if the insert was successful and did not insert, callback(null, false)
78
+ // if there was an error, rollback and callback(error)
79
+ if ( err ) {
80
+ rollback ( client , done ) ;
81
+ callback ( err ) ;
82
+ return ;
83
+ }
84
+ commit ( ) ;
92
85
}
93
- commit ( ) ;
94
- }
95
- )
96
- } else {
97
- client . query (
98
- 'UPDATE snapshots SET doc_type = $3, version = $4, data = $5 WHERE collection = $1 AND doc_id = $2 AND version = ($4 - 1)' ,
99
- [ collection , id , snapshot . type , snapshot . v , snapshot . data ] ,
100
- function ( err , res ) {
101
- // TODO:
102
- // if any rows were updated, success
103
- // if 0 rows were updated, rollback and not success
104
- // if error, rollback and not success
105
- if ( err ) {
106
- rollback ( client , done ) ;
107
- callback ( err ) ;
108
- return ;
86
+ )
87
+ } else {
88
+ client . query (
89
+ 'UPDATE snapshots SET doc_type = $3, version = $4, data = $5 WHERE collection = $1 AND doc_id = $2 AND version = ($4 - 1)' ,
90
+ [ collection , id , snapshot . type , snapshot . v , snapshot . data ] ,
91
+ ( err , res ) => {
92
+ // TODO:
93
+ // if any rows were updated, success
94
+ // if 0 rows were updated, rollback and not success
95
+ // if error, rollback and not success
96
+ if ( err ) {
97
+ rollback ( client , done ) ;
98
+ callback ( err ) ;
99
+ return ;
100
+ }
101
+ commit ( ) ;
109
102
}
110
- commit ( ) ;
111
- }
112
- )
103
+ )
104
+ }
113
105
}
114
- }
115
- )
116
- } )
117
- }
118
- )
119
- } )
120
- } ;
121
-
122
- // Get the named document from the database. The callback is called with (err,
123
- // snapshot). A snapshot with a version of zero is returned if the docuemnt
124
- // has never been created in the database.
125
- PostgresDB . prototype . getSnapshot = function ( collection , id , fields , options , callback ) {
126
- pg . connect ( this . pg_config , function ( err , client , done ) {
127
- if ( err ) {
128
- done ( client ) ;
129
- callback ( err ) ;
130
- return ;
131
- }
132
- client . query (
133
- 'SELECT version, data, doc_type FROM snapshots WHERE collection = $1 AND doc_id = $2 LIMIT 1' ,
134
- [ collection , id ] ,
135
- function ( err , res ) {
136
- done ( ) ;
137
- if ( err ) {
138
- callback ( err ) ;
139
- return ;
106
+ )
107
+ } )
140
108
}
141
- if ( res . rows . length ) {
142
- var row = res . rows [ 0 ]
143
- var snapshot = new PostgresSnapshot (
144
- id ,
145
- row . version ,
146
- row . doc_type ,
147
- row . data ,
148
- undefined // TODO: metadata
149
- )
150
- callback ( null , snapshot ) ;
151
- } else {
152
- var snapshot = new PostgresSnapshot (
153
- id ,
154
- 0 ,
155
- null ,
156
- undefined ,
157
- undefined
158
- )
159
- callback ( null , snapshot ) ;
160
- }
161
- }
162
- )
163
- } )
164
- } ;
109
+ )
110
+ } )
111
+ }
165
112
166
- // Get operations between [from, to) noninclusively. (Ie, the range should
167
- // contain start but not end).
168
- //
169
- // If end is null, this function should return all operations from start onwards.
170
- //
171
- // The operations that getOps returns don't need to have a version: field.
172
- // The version will be inferred from the parameters if it is missing.
173
- //
174
- // Callback should be called as callback(error, [list of ops]);
175
- PostgresDB . prototype . getOps = function ( collection , id , from , to , options , callback ) {
176
- pg . connect ( this . pg_config , function ( err , client , done ) {
177
- if ( err ) {
178
- done ( client ) ;
179
- callback ( err ) ;
180
- return ;
181
- }
182
- client . query (
183
- 'SELECT version, operation FROM ops WHERE collection = $1 AND doc_id = $2 AND version >= $3 AND version < $4' ,
184
- [ collection , id , from , to ] ,
185
- function ( err , res ) {
186
- done ( ) ;
187
- if ( err ) {
188
- callback ( err ) ;
189
- return ;
113
+ // Get the named document from the database. The callback is called with (err,
114
+ // snapshot). A snapshot with a version of zero is returned if the docuemnt
115
+ // has never been created in the database.
116
+ getSnapshot ( collection , id , fields , options , callback ) {
117
+ pg . connect ( this . pg_config , ( err , client , done ) => {
118
+ if ( err ) {
119
+ done ( client ) ;
120
+ callback ( err ) ;
121
+ return ;
122
+ }
123
+ client . query (
124
+ 'SELECT version, data, doc_type FROM snapshots WHERE collection = $1 AND doc_id = $2 LIMIT 1' ,
125
+ [ collection , id ] ,
126
+ ( err , res ) => {
127
+ done ( ) ;
128
+ if ( err ) {
129
+ callback ( err ) ;
130
+ return ;
131
+ }
132
+ if ( res . rows . length ) {
133
+ const row = res . rows [ 0 ] ;
134
+ var snapshot = new PostgresSnapshot (
135
+ id ,
136
+ row . version ,
137
+ row . doc_type ,
138
+ row . data ,
139
+ undefined // TODO: metadata
140
+ )
141
+ callback ( null , snapshot ) ;
142
+ } else {
143
+ var snapshot = new PostgresSnapshot (
144
+ id ,
145
+ 0 ,
146
+ null ,
147
+ undefined ,
148
+ undefined
149
+ )
150
+ callback ( null , snapshot ) ;
151
+ }
190
152
}
191
- callback ( null , res . rows . map ( function ( row ) {
192
- return row . operation ;
193
- } ) ) ;
153
+ )
154
+ } )
155
+ }
156
+
157
+ // Get operations between [from, to) noninclusively. (Ie, the range should
158
+ // contain start but not end).
159
+ //
160
+ // If end is null, this function should return all operations from start onwards.
161
+ //
162
+ // The operations that getOps returns don't need to have a version: field.
163
+ // The version will be inferred from the parameters if it is missing.
164
+ //
165
+ // Callback should be called as callback(error, [list of ops]);
166
+ getOps ( collection , id , from , to , options , callback ) {
167
+ pg . connect ( this . pg_config , ( err , client , done ) => {
168
+ if ( err ) {
169
+ done ( client ) ;
170
+ callback ( err ) ;
171
+ return ;
194
172
}
195
- )
196
- } )
197
- } ;
173
+ client . query (
174
+ 'SELECT version, operation FROM ops WHERE collection = $1 AND doc_id = $2 AND version >= $3 AND version < $4' ,
175
+ [ collection , id , from , to ] ,
176
+ ( err , res ) => {
177
+ done ( ) ;
178
+ if ( err ) {
179
+ callback ( err ) ;
180
+ return ;
181
+ }
182
+ callback ( null , res . rows . map ( row => row . operation ) ) ;
183
+ }
184
+ )
185
+ } )
186
+ }
187
+ }
188
+
189
+ export default PostgresDB ;
190
+
191
+ PostgresDB . prototype = Object . create ( DB . prototype ) ;
192
+
193
+ function rollback ( client , done ) {
194
+ client . query ( 'ROLLBACK' , err => done ( err ) )
195
+ }
198
196
199
197
function PostgresSnapshot ( id , version , type , data , meta ) {
200
198
this . id = id ;
201
199
this . v = version ;
202
200
this . type = type ;
203
201
this . data = data ;
204
202
this . m = meta ;
205
- }
203
+ }
0 commit comments