github.com/whiteboxio/flow@v0.0.3-0.20190918184116-508d75d68a2c/pkg/corev1alpha1/x/meta_parser.go (about)

     1  package x
     2  
     3  import (
     4  	"bytes"
     5  	"net/url"
     6  	"strings"
     7  	"sync"
     8  
     9  	core "github.com/awesome-flow/flow/pkg/corev1alpha1"
    10  )
    11  
    12  const (
    13  	MetaDelimByte = ' '
    14  )
    15  
    16  type MetaParser struct {
    17  	name  string
    18  	ctx   *core.Context
    19  	queue chan *core.Message
    20  	wg    sync.WaitGroup
    21  }
    22  
    23  var _ core.Actor = (*MetaParser)(nil)
    24  
    25  func NewMetaParser(name string, ctx *core.Context, params core.Params) (core.Actor, error) {
    26  	return &MetaParser{
    27  		name:  name,
    28  		ctx:   ctx,
    29  		queue: make(chan *core.Message),
    30  	}, nil
    31  }
    32  
    33  func (m *MetaParser) Name() string {
    34  	return m.name
    35  }
    36  
    37  func (m *MetaParser) Start() error {
    38  	return nil
    39  }
    40  
    41  func (m *MetaParser) Stop() error {
    42  	close(m.queue)
    43  	m.wg.Wait()
    44  	return nil
    45  }
    46  
    47  func (m *MetaParser) Connect(nthreads int, peer core.Receiver) error {
    48  	for i := 0; i < nthreads; i++ {
    49  		m.wg.Add(1)
    50  		go func() {
    51  			for msg := range m.queue {
    52  				if err := peer.Receive(msg); err != nil {
    53  					msg.Complete(core.MsgStatusFailed)
    54  					m.ctx.Logger().Error("meta parser %q failed to send message: %s", m.name, err)
    55  				}
    56  			}
    57  			m.wg.Done()
    58  		}()
    59  	}
    60  	return nil
    61  }
    62  
    63  func (m *MetaParser) Receive(msg *core.Message) error {
    64  	parsed, err := parseMsgMeta(msg)
    65  	if err != nil {
    66  		return err
    67  	}
    68  	m.queue <- parsed
    69  	return nil
    70  }
    71  
    72  func parseMsgMeta(msg *core.Message) (*core.Message, error) {
    73  	fullbody := msg.Body()
    74  	spix := bytes.IndexByte(fullbody, MetaDelimByte)
    75  	if spix == -1 {
    76  		return msg, nil
    77  	}
    78  	meta, body := fullbody[:spix], fullbody[spix+1:]
    79  	values, err := url.ParseQuery(string(meta))
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  	for k, vs := range values {
    84  		msg.SetMeta(k, strings.Join(vs, ","))
    85  	}
    86  	msg.SetBody(body)
    87  	return msg, nil
    88  }