(ctx context.Context, logger *zap.Logger, clientConn net.Conn, mockDb integrations.MockMemDb, decodeCtx *wire.DecodeContext, opts models.OutgoingOptions)
| 17 | ) |
| 18 | |
| 19 | func simulateCommandPhase(ctx context.Context, logger *zap.Logger, clientConn net.Conn, mockDb integrations.MockMemDb, decodeCtx *wire.DecodeContext, opts models.OutgoingOptions) error { |
| 20 | |
| 21 | // Log initial mock state at the start of command phase |
| 22 | total, cfg, data := mockDb.GetMySQLCounts() |
| 23 | logger.Debug("Command phase starting", |
| 24 | zap.Int("total_mysql_mocks", total), |
| 25 | zap.Int("config_mocks", cfg), |
| 26 | zap.Int("data_mocks_available", data)) |
| 27 | |
| 28 | commandCount := 0 |
| 29 | for { |
| 30 | select { |
| 31 | case <-ctx.Done(): |
| 32 | return ctx.Err() |
| 33 | default: |
| 34 | commandCount++ |
| 35 | |
| 36 | logger.Debug("Starting new command iteration", |
| 37 | zap.Int("command_count", commandCount)) |
| 38 | |
| 39 | // Set a read deadline on the client connection. |
| 40 | // opts.SQLDelay is a time.Duration; multiplying by time.Second (the old |
| 41 | // code) either produced 0 when the caller sent SQLDelay=0 or overflowed |
| 42 | // int64 when the caller sent a real seconds-valued Duration — both cases |
| 43 | // expired the deadline immediately and hot-looped at 50ms/iter forever. |
| 44 | readTimeout := 2 * opts.SQLDelay |
| 45 | if readTimeout < time.Second { |
| 46 | readTimeout = 2 * time.Second |
| 47 | } |
| 48 | err := clientConn.SetReadDeadline(time.Now().Add(readTimeout)) |
| 49 | if err != nil { |
| 50 | utils.LogError(logger, err, "failed to set read deadline on client conn") |
| 51 | return err |
| 52 | } |
| 53 | |
| 54 | logger.Debug("About to read next command from client", |
| 55 | zap.Int("command_count", commandCount), |
| 56 | zap.Duration("read_timeout", readTimeout)) |
| 57 | |
| 58 | // read the command from the client |
| 59 | command, err := mysqlUtils.ReadPacketBuffer(ctx, logger, clientConn) |
| 60 | if err != nil { |
| 61 | if ne, ok := err.(net.Error); ok && ne.Timeout() { |
| 62 | // Idle wait: keep the connection open and continue polling |
| 63 | logger.Debug("read timeout waiting for next client command; keeping connection open") |
| 64 | // Optional: back off a bit to avoid hot loop |
| 65 | time.Sleep(50 * time.Millisecond) |
| 66 | // Clear deadline or set another future deadline, then keep looping |
| 67 | _ = clientConn.SetReadDeadline(time.Now().Add(readTimeout)) |
| 68 | continue |
| 69 | } |
| 70 | if err == io.EOF { |
| 71 | logger.Debug("client closed the connection (EOF)") |
| 72 | } else { |
| 73 | utils.LogError(logger, err, "failed to read command packet from client") |
| 74 | } |
| 75 | return err |
| 76 | } |
no test coverage detected