Пример #1
0
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)
}
Пример #2
0
// 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)
			}
		}
	}
}