github.com/saucelabs/saucectl@v0.175.1/internal/http/cloudevents.go (about)

     1  package http
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"time"
     7  
     8  	cloudevents "github.com/cloudevents/sdk-go/v2"
     9  	"github.com/gorilla/websocket"
    10  	"github.com/saucelabs/saucectl/internal/imagerunner"
    11  )
    12  
    13  type WebSocketAsyncEventTransport struct {
    14  	ws *websocket.Conn
    15  }
    16  
    17  func NewWebSocketAsyncEventTransport(ws *websocket.Conn) *WebSocketAsyncEventTransport {
    18  	return &WebSocketAsyncEventTransport{
    19  		ws: ws,
    20  	}
    21  }
    22  
    23  func (aet *WebSocketAsyncEventTransport) ReadMessage() (string, error) {
    24  	_, msg, err := aet.ws.ReadMessage()
    25  	return string(msg), err
    26  }
    27  
    28  func (aet *WebSocketAsyncEventTransport) Close() error {
    29  	return aet.ws.Close()
    30  }
    31  
    32  type AsyncEventParser struct {
    33  	lastLogTime time.Time
    34  }
    35  
    36  func NewAsyncEventMgr() (*AsyncEventParser, error) {
    37  	asyncEventManager := AsyncEventParser{
    38  		lastLogTime: time.Now(),
    39  	}
    40  
    41  	return &asyncEventManager, nil
    42  }
    43  
    44  func (a *AsyncEventParser) ParseEvent(event string) (*imagerunner.AsyncEvent, error) {
    45  	e := cloudevents.NewEvent()
    46  	err := json.Unmarshal([]byte(event), &e)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	data := map[string]string{}
    52  	err = e.DataAs(&data)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  
    57  	asyncEvent := imagerunner.AsyncEvent{
    58  		Type: e.Type(),
    59  		Data: data,
    60  	}
    61  
    62  	if asyncEvent.Type == "com.saucelabs.so.v1.log" {
    63  		asyncEvent.LineSequence, err = parseLineSequence(&e)
    64  		if err != nil {
    65  			return nil, err
    66  		}
    67  		a.lastLogTime = time.Now()
    68  	}
    69  
    70  	return &asyncEvent, nil
    71  }
    72  
    73  func (a *AsyncEventParser) IsLogIdle() bool {
    74  	return time.Since(a.lastLogTime) > 30*time.Second
    75  }
    76  
    77  func parseLineSequence(cloudEvent *cloudevents.Event) (string, error) {
    78  	// The extension is not necessarily present, so ignore errors.
    79  	ls, _ := cloudEvent.Context.GetExtension("linesequence")
    80  	lineseq, ok := ls.(string)
    81  	if !ok {
    82  		return "", fmt.Errorf("linesequence is not a string")
    83  	}
    84  	return lineseq, nil
    85  }