github.com/jfrog/jfrog-cli-go@v1.22.1-0.20200318093948-4826ef344ffd/bintray/commands/stream.go (about)

     1  package commands
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/jfrog/jfrog-cli-go/bintray/helpers"
     6  	"github.com/jfrog/jfrog-client-go/bintray/auth"
     7  	"io"
     8  	"net/http"
     9  	"strings"
    10  	"time"
    11  )
    12  
    13  const streamUrl = "%vstream/%v"
    14  const timeout = 90
    15  const timeoutDuration = timeout * time.Second
    16  const onErrorReconnectDuration = 3 * time.Second
    17  
    18  func Stream(streamDetails *StreamDetails, writer io.Writer) {
    19  	var resp *http.Response
    20  	var connected bool
    21  	lastServerInteraction := time.Now()
    22  	streamManager := createStreamManager(streamDetails)
    23  
    24  	go func() {
    25  		for {
    26  			connected = false
    27  			var connectionEstablished bool
    28  			connectionEstablished, resp = streamManager.Connect()
    29  			if !connectionEstablished {
    30  				time.Sleep(onErrorReconnectDuration)
    31  				continue
    32  			}
    33  			lastServerInteraction = time.Now()
    34  			connected = true
    35  			streamManager.ReadStream(resp, writer, &lastServerInteraction)
    36  		}
    37  	}()
    38  
    39  	for true {
    40  		if !connected {
    41  			time.Sleep(timeoutDuration)
    42  			continue
    43  		}
    44  		if time.Since(lastServerInteraction) < timeoutDuration {
    45  			time.Sleep(timeoutDuration - time.Now().Sub(lastServerInteraction))
    46  			continue
    47  		}
    48  		if resp != nil {
    49  			resp.Body.Close()
    50  			time.Sleep(timeoutDuration)
    51  			continue
    52  		}
    53  	}
    54  	return
    55  }
    56  
    57  func buildIncludeFilterMap(filterPattern string) map[string]struct{} {
    58  	if filterPattern == "" {
    59  		return nil
    60  	}
    61  	result := make(map[string]struct{})
    62  	var empty struct{}
    63  	splittedFilters := strings.Split(filterPattern, ";")
    64  	for _, v := range splittedFilters {
    65  		result[v] = empty
    66  	}
    67  	return result
    68  }
    69  
    70  func createStreamManager(streamDetails *StreamDetails) *helpers.StreamManager {
    71  	return &helpers.StreamManager{
    72  		Url:               fmt.Sprintf(streamUrl, streamDetails.BintrayDetails.GetApiUrl(), streamDetails.Subject),
    73  		HttpClientDetails: streamDetails.BintrayDetails.CreateHttpClientDetails(),
    74  		IncludeFilter:     buildIncludeFilterMap(streamDetails.Include)}
    75  }
    76  
    77  type StreamDetails struct {
    78  	BintrayDetails auth.BintrayDetails
    79  	Subject        string
    80  	Include        string
    81  }