コード例 #1
0
ファイル: forensiq.go プロジェクト: jamloop/rtbkit
func (c *Client) query(ctx context.Context, qs string) (value *jq.Value, err error) {
	url := defaults.String(c.URL, "http://api.forensiq.com") + "/check?" + qs

	// perform the request
	resp, err := c.HTTP.Get(ctx, url)
	if err != nil {
		return
	}

	// and parse the response back
	value = new(jq.Value)
	err = value.UnmarshalFrom(resp.Body)
	return
}
コード例 #2
0
ファイル: forensiq.go プロジェクト: jamloop/rtbkit
// Process sends a request to query the /check endpoint.
// The response is attached to the request.
func (c *Client) Process(ctx context.Context, r rtb.Request) (err error) {
	ctx = trace.Enter(ctx, "Forensiq")

	// ready?
	if !c.HTTP.Ready() {
		err = ErrUnavailable
		trace.Error(ctx, "Errors.Ready", err)
		return
	}

	var args url.Values

	// fast path in case the request is already prepared
	if p, ok := r.(*request); ok {
		args = p.values
	} else {
		args, err = c.prepare(r)
		if err != nil {
			trace.Error(ctx, "Errors.Prepare", err)
			return
		}
	}

	qs := args.Encode()

	// look into the memory cache or perform the query
	value := c.fromCache(qs)
	if value != nil {
		trace.Count(ctx, "CacheHit", 1)
	} else {
		value, err = c.query(ctx, qs)
		if err != nil {
			trace.Error(ctx, "Errors.Request", err)
			return
		}

		c.intoCache(qs, value)
	}

	// hold the result
	r.Attach(defaults.String(c.Target, "forensiq"), value)

	trace.Leave(ctx, "Check")
	return
}
コード例 #3
0
ファイル: forensiq.go プロジェクト: jamloop/rtbkit
func (c *Client) prepare(r rtb.Request) (result url.Values, err error) {
	extractor, ok := r.Component(defaults.String(c.Source, "fields")).(rtb.Extractor)
	if !ok {
		err = rtb.ErrNoExtractor
		return
	}

	args := url.Values{
		"ck":     []string{c.ClientKey},
		"output": []string{"json"},
		"rt":     []string{"display"},
	}

	extract := func(key string, value []string) {
		item := extractor.Extract(value...)
		if item == nil {
			return
		}

		args.Set(key, fmt.Sprintf("%v", item))
	}

	// extract fields
	for key, value := range c.Fields {
		extract(key, value)
	}

	// valid?
	fields := []string{"ck", "rt", "ip", "seller"}
	for i := range fields {
		items := args[fields[i]]
		if len(items) == 0 || items[0] == "" {
			err = ErrMissingFields
			return
		}
	}

	result = args
	return
}
コード例 #4
0
ファイル: forensiq.go プロジェクト: jamloop/rtbkit
// HealthCheck sends a request to query the /ready endpoint.
func (c *Client) HealthCheck() error {
	url := defaults.String(c.URL, "http://api.forensiq.com") + "/ready"
	return c.HTTP.HealthCheck(url)
}
コード例 #5
0
ファイル: forensiq.go プロジェクト: jamloop/rtbkit
// Start installs the health monitor of the Forensiq API.
func (c *Client) Start() error {
	url := defaults.String(c.URL, "http://api.forensiq.com") + "/ready"
	c.HTTP.MonitorHealth(url)
	return nil
}
コード例 #6
0
ファイル: server.go プロジェクト: jamloop/rtbkit
// Start installs the server and starts serving requests until the server is closed.
func (s *Server) Start() (err error) {
	s.Server.Handler = s

	// open socket
	s.listen, err = net.Listen("tcp", defaults.String(s.Server.Addr, ":http"))
	if err != nil {
		return
	}

	s.name = defaults.String(s.Name, s.listen.Addr().String())

	// provide a default read timeout if missing
	if 0 == s.Server.ReadTimeout {
		s.Server.ReadTimeout = time.Minute
	}

	// track new/closed HTTP connections
	s.conns = make(map[net.Conn]http.ConnState)

	cs := s.Server.ConnState
	s.Server.ConnState = func(conn net.Conn, state http.ConnState) {
		s.mu.Lock()
		defer s.mu.Unlock()

		switch state {
		case http.StateNew:
			atomic.AddInt64(&s.count, +1)
			s.wg.Add(1)
			s.conns[conn] = state
		case http.StateClosed, http.StateHijacked:
			atomic.AddInt64(&s.count, -1)
			s.wg.Done()
			delete(s.conns, conn)
		case http.StateActive, http.StateIdle:
			s.conns[conn] = state
		}

		if nil != cs {
			cs(conn, state)
		}
	}

	// update metrics
	s.tick = Tick(time.Second, func() {
		ctx := trace.Start(trace.SetHandler(context.Background(), s.Tracer), s.name+".Tick", "")
		trace.Set(ctx, "Connections", atomic.LoadInt64(&s.count))
		trace.Set(ctx, "State", atomic.LoadInt64(&s.ready))
		trace.Leave(ctx, "Ticked")
	})

	// serve requests
	go func() {
		s.Server.Serve(s.listen)
	}()

	// set ready
	if !atomic.CompareAndSwapInt64(&s.ready, 0, 1) {
		panic("server is already ready to serve requests")
	}

	return
}