dispatch is the main loop of the client. It sends read messages to waiting calls to Call and BatchCall and subscription notifications to registered subscriptions.
(conn net.Conn)
| 513 | // It sends read messages to waiting calls to Call and BatchCall |
| 514 | // and subscription notifications to registered subscriptions. |
| 515 | func (c *Client) dispatch(conn net.Conn) { |
| 516 | // Spawn the initial read loop. |
| 517 | go c.read(conn) |
| 518 | |
| 519 | var ( |
| 520 | lastOp *requestOp // tracks last send operation |
| 521 | requestOpLock = c.requestOp // nil while the send lock is held |
| 522 | reading = true // if true, a read loop is running |
| 523 | ) |
| 524 | defer close(c.didQuit) |
| 525 | defer func() { |
| 526 | c.closeRequestOps(ErrClientQuit) |
| 527 | conn.Close() |
| 528 | if reading { |
| 529 | // Empty read channels until read is dead. |
| 530 | for { |
| 531 | select { |
| 532 | case <-c.readResp: |
| 533 | case <-c.readErr: |
| 534 | return |
| 535 | } |
| 536 | } |
| 537 | } |
| 538 | }() |
| 539 | |
| 540 | for { |
| 541 | select { |
| 542 | case <-c.close: |
| 543 | return |
| 544 | |
| 545 | // Read path. |
| 546 | case batch := <-c.readResp: |
| 547 | for _, msg := range batch { |
| 548 | switch { |
| 549 | case msg.isNotification(): |
| 550 | log.Debug("", "msg", func() string { |
| 551 | return fmt.Sprint("<-readResp: notification ", msg) |
| 552 | }()) |
| 553 | c.handleNotification(msg) |
| 554 | case msg.isResponse(): |
| 555 | log.Debug("", "msg", func() string { |
| 556 | return fmt.Sprint("<-readResp: response ", msg) |
| 557 | }()) |
| 558 | c.handleResponse(msg) |
| 559 | default: |
| 560 | log.Debug("", "msg", func() string { |
| 561 | return fmt.Sprint("<-readResp: dropping weird message", msg) |
| 562 | }()) |
| 563 | // TODO: maybe close |
| 564 | } |
| 565 | } |
| 566 | |
| 567 | case err := <-c.readErr: |
| 568 | log.Debug("<-readErr", "err", err) |
| 569 | c.closeRequestOps(err) |
| 570 | conn.Close() |
| 571 | reading = false |
| 572 |
no test coverage detected