1

クエリを閉じた直後にプールを閉じると、この例外が発生します。

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();
    });
  });
}
4

1 に答える 1