@@ -89,4 +89,85 @@ describe('error recovery', () => {
89
89
await client . end ( )
90
90
} )
91
91
} )
92
+
93
+ it ( 'should work if used after timeout error' , async ( ) => {
94
+ const pool = new Pool ( { max : 1 , connectionTimeoutMillis : 400 , statement_timeout : 400 } )
95
+
96
+ const res1 = await pool . query ( 'SELECT 1 AS a' )
97
+ assert . deepStrictEqual ( res1 . rows , [ { a : 1 } ] )
98
+
99
+ const query = new QueryStream ( 'SELECT 2 AS b' )
100
+ const client = await pool . connect ( )
101
+ const stream = await client . query ( query )
102
+
103
+ await assert . rejects ( ( ) => pool . query ( 'SELECT TRUE' ) , { message : 'timeout exceeded when trying to connect' } )
104
+
105
+ await stream . destroy ( )
106
+ await client . release ( )
107
+
108
+ const res2 = await pool . query ( 'SELECT 4 AS d' )
109
+ assert . deepStrictEqual ( res2 . rows , [ { d : 4 } ] )
110
+
111
+ await pool . end ( )
112
+ } )
113
+
114
+ it ( 'should work if used after syntax error' , async ( ) => {
115
+ const pool = new Pool ( { max : 1 , statement_timeout : 100 } ) // statement_timeout is required here, so maybe this is just another timeout error?
116
+
117
+ const res1 = await pool . query ( 'SELECT 1 AS a' )
118
+ assert . deepStrictEqual ( res1 . rows , [ { a : 1 } ] )
119
+
120
+ const query = new QueryStream ( 'SELECT 2 AS b' )
121
+ const client = await pool . connect ( )
122
+ const stream = await client . query ( query )
123
+
124
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) )
125
+
126
+ await stream . destroy ( )
127
+ await client . release ( )
128
+
129
+ const res2 = await pool . query ( 'SELECT 4 AS d' )
130
+ assert . deepStrictEqual ( res2 . rows , [ { d : 4 } ] )
131
+
132
+ await pool . end ( )
133
+ } )
134
+
135
+ it ( 'should work after cancelling query' , async ( ) => {
136
+ const pool = new Pool ( )
137
+ const conn = await pool . connect ( )
138
+
139
+ // Get connection PID for sake of pg_cancel_backend() call
140
+ const result = await conn . query ( 'SELECT pg_backend_pid() AS pid;' )
141
+ const { pid } = result . rows [ 0 ]
142
+
143
+ const stream = conn . query ( new QueryStream ( 'SELECT pg_sleep(10);' ) )
144
+ stream . on ( 'data' , ( chunk ) => {
145
+ // Switches stream into readableFlowing === true mode
146
+ } )
147
+ stream . on ( 'error' , ( err ) => {
148
+ // Errors are expected due to pg_cancel_backend() call
149
+ } )
150
+
151
+ // Create a promise that is resolved when the stream is closed
152
+ const closed = new Promise ( ( res ) => {
153
+ stream . on ( 'close' , res )
154
+ } )
155
+
156
+ // Wait 100ms before cancelling the query
157
+ await new Promise ( ( res ) => setTimeout ( res , 100 ) )
158
+
159
+ // Cancel pg_sleep(10) query
160
+ await pool . query ( 'SELECT pg_cancel_backend($1);' , [ pid ] )
161
+
162
+ // Destroy stream and wait for it to be closed
163
+ stream . destroy ( )
164
+ await closed
165
+
166
+ // Subsequent query on same connection should succeed
167
+ const res = await conn . query ( 'SELECT 1 AS a;' )
168
+ assert . deepStrictEqual ( res . rows , [ { a : 1 } ] )
169
+
170
+ conn . release ( )
171
+ await pool . end ( )
172
+ } )
92
173
} )
0 commit comments