func (s *Supervisor) sendChunk(c client.Client, chunk []*FileData) error { lines := make([]client.Data, 0, len(chunk)) for _, fileData := range chunk { lines = append(lines, fileData.Data) } return c.Send(lines) }
// sendReadyChunksToClient reads from the readyChunks channel for a particular // client, sending those chunks to the remote system. This function is also // responsible for snapshotting progress and unlocking the readers after it has // successfully sent. func (s *Supervisor) sendReadyChunksToClient(client client.Client) { backoff := &ExponentialBackoff{Minimum: 50 * time.Millisecond, Maximum: 5000 * time.Millisecond} for { var readyChunk *readyChunk select { case <-s.stopRequest: return case readyChunk = <-s.retryChunks: // got a retry chunk; use it default: // pull from the default readyChunk queue select { case <-s.stopRequest: return case readyChunk = <-s.readyChunks: // got a chunk } } if readyChunk != nil { GlobalStatistics.SetClientStatus(client.Name(), clientStatusSending) if err := s.sendChunk(client, readyChunk.Chunk); err != nil { grohl.Report(err, grohl.Data{"msg": "failed to send chunk", "resolution": "retrying"}) GlobalStatistics.SetClientStatus(client.Name(), clientStatusRetrying) // Put the chunk back on the queue for someone else to try select { case <-s.stopRequest: return case s.retryChunks <- readyChunk: // continue } // Backoff select { case <-s.stopRequest: return case <-time.After(backoff.Next()): // continue } } else { backoff.Reset() GlobalStatistics.IncrementClientLinesSent(client.Name(), len(readyChunk.Chunk)) // Snapshot progress if err := s.acknowledgeChunk(readyChunk.Chunk); err != nil { grohl.Report(err, grohl.Data{"msg": "failed to acknowledge progress", "resolution": "skipping"}) } s.readerPool.UnlockAll(readyChunk.LockedReaders) } } } }