// AddScopedReq adds a server-scoped request (from the server request `from`) to our multi-client
// with the `uid` that uniquely identifies the request within the group (for getting response from `Outcome`)
func (c *defClient) AddScopedReq(sr *ScopedReq) MultiClient {
	c.Lock()
	defer c.Unlock()
	if _, exists := c.requests[sr.Uid]; exists {
		panic(fmt.Sprintf("Cannot add scoped request with UID '%v' - already exists within this MultiClient", sr.Uid))
	}
	from := sr.From
	if from == nil {
		from = c.defaultFromScope
	}

	var clientReq *client.Request
	var err error

	// if no from, just use normal client request
	if from == nil {
		clientReq, err = client.NewRequest(sr.Service, sr.Endpoint, sr.Req)
	} else {
		clientReq, err = from.ScopedRequest(sr.Service, sr.Endpoint, sr.Req)
	}

	c.requests[sr.Uid] = clientReq
	c.responses[sr.Uid] = sr.Rsp
	if err != nil {
		c.errors.set(sr.Uid, clientReq,
			errors.InternalServerError("com.hailocab.kernel.multirequest.badrequest", err.Error()), from)
	} else {
		clientReq.SetOptions(sr.Options)
	}

	return c
}
// matches tests if this stub matches our request - not thread safe
func (s *Stub) matches(req *client.Request) bool {
	if req == nil {
		return false
	}
	if s.Service != req.Service() || s.Endpoint != req.Endpoint() {
		return false
	}
	if s.invocationLimit > 0 && len(s.matched) >= s.invocationLimit {
		return false
	}
	if s.payload != nil {
		clone := proto.Clone(s.payload)
		req.Unmarshal(clone)
		if !proto.Equal(s.payload, clone) {
			return false
		}
	}

	// got a match
	if s.matched == nil {
		s.matched = make([]*client.Request, 0)
	}
	s.matched = append(s.matched, req)
	return true
}