クエリを閉じた直後にプールを閉じると、この例外が発生します。
Uncaught Error: Bad state: Cannot write to socket, it is closed
Stack Trace:
#0 BufferedSocket.writeBufferPart (package:sqljocky/src/buffered_socket.dart:114:7)
#1 BufferedSocket.writeBuffer (package:sqljocky/src/buffered_socket.dart:108:27)
#2 _Connection._sendBufferPart (package:sqljocky/src/connection.dart:261:31)
#3 _Connection._sendBuffer (package:sqljocky/src/connection.dart:249:29)
#4 _Connection.processHandler (package:sqljocky/src/connection.dart:289:16)
#5 ConnectionPool._closeQuery.<anonymous closure> (package:sqljocky/src/connection_pool.dart:220:29)
#6 _rootRunUnary (dart:async/zone.dart:730)
#7 _RootZone.runUnary (dart:async/zone.dart:864)
#8 _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:488)
#9 _Future._propagateToListeners (dart:async/future_impl.dart:571)
#10 _Future._completeWithValue (dart:async/future_impl.dart:331)
#11 _Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:393)
#12 _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:23)
#13 _asyncRunCallback (dart:async/schedule_microtask.dart:32)
#14 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:128)
Unhandled exception:
Bad state: Cannot write to socket, it is closed
#0 _rootHandleUncaughtError.<anonymous closure>.<anonymous closure> (dart:async/zone.dart:713)
#1 _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:23)
#2 _asyncRunCallback (dart:async/schedule_microtask.dart:32)
#3 _asyncRunCallback (dart:async/schedule_microtask.dart:36)
#4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:128)
問題は、クエリのクローズが Future を内部的に起動することであると思われるため、クローズが実際に終了する前に close() 関数が返されます。
void _closeQuery(Query q, bool retain) {
_log.finest("Closing query: ${q.sql}");
for (var cnx in _pool) {
var preparedQuery = cnx.removePreparedQueryFromCache(q.sql);
if (preparedQuery != null) {
_waitUntilReady(cnx).then((_) {
_log.finest("Connection ready - closing query: ${q.sql}");
var handler = new _CloseStatementHandler(preparedQuery.statementHandlerId);
cnx.autoRelease = !retain;
cnx.processHandler(handler, noResponse: true);
});
}
}
}
プールがすぐに閉じられ、ソケットがすぐに閉じられます。これは、クエリのクローズ (Future のためにプールがクローズされるまで遅延される) が失敗し、ソケットを介して必要な情報を送信できないことを意味します。https://github.com/jamesots/sqljocky/issues/44で sqljocky へのチケットをオープンしましたが、応答がありません。応答を得るのに時間がかかる場合は回避策が必要です。
このコードにより、100% の確率で問題を再現できました。
Future _putMethod(RestRequest request) {
return new Future.sync(() {
mysql.ConnectionPool pool = getConnectionPool();
return pool.prepare("SELECT * FROM files").then((mysql.Query query) {
return query.execute().then((result) {
// Do something?
}).then((_) {
this._log.info("Closing");
query.close();
});
}).then((_) {
pool.close();
});
});
}