Ejemplo n.º 1
0
func (k *kv) Get(ctx context.Context, req *proto.GetRequest, rsp *proto.GetResponse) error {
	mtx.RLock()
	defer mtx.RUnlock()

	item, ok := items[req.Key]
	if !ok {
		return errors.NotFound(serviceName, "not found")
	}

	// non expiring key
	if item.Expiration <= 0 {
		rsp.Item = item.Item
		return nil
	}

	// expiring key

	t := time.Now().Unix()

	if delta := t - item.Timestamp; delta > item.Expiration {
		// not yet reaped but you can't have it either
		return errors.NotFound(serviceName, "not found")
	}

	rsp.Item = item.Item
	return nil
}
Ejemplo n.º 2
0
func (m *MockClient) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
	m.Lock()
	defer m.Unlock()

	response, ok := m.Response[req.Service()]
	if !ok {
		return errors.NotFound("go.micro.client.mock", "service not found")
	}

	for _, r := range response {
		if r.Method != req.Method() {
			continue
		}

		if r.Error != nil {
			return r.Error
		}

		v := reflect.ValueOf(rsp)

		if t := reflect.TypeOf(rsp); t.Kind() == reflect.Ptr {
			v = reflect.Indirect(v)
		}

		v.Set(reflect.ValueOf(r.Response))

		return nil
	}

	return fmt.Errorf("rpc: can't find service %s", req.Method())
}
Ejemplo n.º 3
0
func (r *Router) SelectStream(ctx context.Context, req *proto.SelectRequest, stream proto.Router_SelectStreamStream) error {
	// TODO: process filters

	if len(req.Service) == 0 {
		return errors.BadRequest("go.micro.srv.router.Router.Select", "invalid service name")
	}

	t := time.NewTicker(time.Duration(router.DefaultExpiry) * time.Second)
	defer t.Stop()

	for {
		services, err := router.Select(req.Service)
		if err != nil && err == selector.ErrNotFound {
			return errors.NotFound("go.micro.srv.router.Router.SelectStream", err.Error())
		} else if err != nil {
			return errors.InternalServerError("go.micro.srv.router.Router.SelectStream", err.Error())
		}

		if err := stream.Send(&proto.SelectResponse{
			Services: services,
			Expires:  time.Now().Unix() + int64(router.DefaultExpiry),
		}); err != nil {
			return err
		}

		<-t.C
	}

	return nil
}
Ejemplo n.º 4
0
func (r *rpcClient) Stream(ctx context.Context, request Request, opts ...CallOption) (Streamer, error) {
	var copts CallOptions
	for _, opt := range opts {
		opt(&copts)
	}

	next, err := r.opts.Selector.Select(request.Service(), copts.SelectOptions...)
	if err != nil && err == selector.ErrNotFound {
		return nil, errors.NotFound("go.micro.client", err.Error())
	} else if err != nil {
		return nil, errors.InternalServerError("go.micro.client", err.Error())
	}

	var stream Streamer
	var grr error

	for i := 0; i < r.opts.Retries; i++ {
		node, err := next()
		if err != nil && err == selector.ErrNotFound {
			return nil, errors.NotFound("go.micro.client", err.Error())
		} else if err != nil {
			return nil, errors.InternalServerError("go.micro.client", err.Error())
		}

		address := node.Address
		if node.Port > 0 {
			address = fmt.Sprintf("%s:%d", address, node.Port)
		}

		stream, grr = r.stream(ctx, address, request)
		r.opts.Selector.Mark(request.Service(), node, grr)

		// bail early if succeeds
		if grr == nil {
			return stream, nil
		}
	}

	return stream, grr
}
Ejemplo n.º 5
0
func (r *rpcClient) Call(ctx context.Context, request Request, response interface{}, opts ...CallOption) error {
	var copts CallOptions
	for _, opt := range opts {
		opt(&copts)
	}

	next, err := r.opts.Selector.Select(request.Service(), copts.SelectOptions...)
	if err != nil && err == selector.ErrNotFound {
		return errors.NotFound("go.micro.client", err.Error())
	} else if err != nil {
		return errors.InternalServerError("go.micro.client", err.Error())
	}

	var grr error

	for i := 0; i < r.opts.Retries; i++ {
		node, err := next()
		if err != nil && err == selector.ErrNotFound {
			return errors.NotFound("go.micro.client", err.Error())
		} else if err != nil {
			return errors.InternalServerError("go.micro.client", err.Error())
		}

		address := node.Address
		if node.Port > 0 {
			address = fmt.Sprintf("%s:%d", address, node.Port)
		}

		grr = r.call(ctx, address, request, response)
		r.opts.Selector.Mark(request.Service(), node, grr)

		// if the call succeeded lets bail early
		if grr == nil {
			return nil
		}
	}

	return grr
}
Ejemplo n.º 6
0
func (m *Monitor) HealthChecks(ctx context.Context, req *proto.HealthChecksRequest, rsp *proto.HealthChecksResponse) error {
	if req.Limit == 0 {
		req.Limit = 10
	}
	hcs, err := monitor.DefaultMonitor.HealthChecks(req.Id, req.Status, int(req.Limit), int(req.Offset))
	if err != nil && err == monitor.ErrNotFound {
		return errors.NotFound("go.micro.srv.monitoring.Monitor.HealthCheck", err.Error())
	} else if err != nil {
		return errors.InternalServerError("go.micro.srv.monitoring.Monitor.HealthCheck", err.Error())
	}

	rsp.Healthchecks = hcs
	return nil
}
Ejemplo n.º 7
0
func (r *Label) Read(ctx context.Context, req *proto.ReadRequest, rsp *proto.ReadResponse) error {
	if len(req.Id) == 0 {
		return errors.BadRequest("go.micro.srv.router.Label.Read", "invalid id")
	}

	l, err := label.Read(req.Id)
	if err != nil {
		if err == db.ErrNotFound {
			return errors.NotFound("go.micro.srv.router.Label.Read", err.Error())
		}
		return errors.InternalServerError("go.micro.srv.router.Label.Read", err.Error())
	}

	rsp.Label = l

	return nil
}
Ejemplo n.º 8
0
func (r *Router) Select(ctx context.Context, req *proto.SelectRequest, rsp *proto.SelectResponse) error {
	// TODO: process filters

	if len(req.Service) == 0 {
		return errors.BadRequest("go.micro.srv.router.Router.Select", "invalid service name")
	}

	services, err := router.Select(req.Service)
	if err != nil && err == selector.ErrNotFound {
		return errors.NotFound("go.micro.srv.router.Router.Select", err.Error())
	} else if err != nil {
		return errors.InternalServerError("go.micro.srv.router.Router.Select", err.Error())
	}

	rsp.Services = services
	rsp.Expires = time.Now().Unix() + int64(router.DefaultExpiry)

	return nil
}
Ejemplo n.º 9
0
func (d *DB) Read(ctx context.Context, req *mdb.ReadRequest, rsp *mdb.ReadResponse) error {
	if err := validateDB("DB.Read", req.Database); err != nil {
		return err
	}

	if len(req.Id) == 0 {
		return errors.BadRequest("go.micro.srv.db.DB.Read", "invalid id")
	}

	r, err := db.Read(req.Database, req.Id)
	if err != nil && err == db.ErrNotFound {
		return errors.NotFound("go.micro.srv.db.DB.Read", "not found")
	} else if err != nil {
		return errors.InternalServerError("go.micro.srv.db.DB.Read", err.Error())
	}

	rsp.Record = r

	return nil
}
Ejemplo n.º 10
0
func (g *grpcClient) Stream(ctx context.Context, req client.Request, opts ...client.CallOption) (client.Streamer, error) {
	// make a copy of call opts
	callOpts := g.opts.CallOptions
	for _, opt := range opts {
		opt(&callOpts)
	}

	// get next nodes from the selector
	next, err := g.opts.Selector.Select(req.Service(), callOpts.SelectOptions...)
	if err != nil && err == selector.ErrNotFound {
		return nil, errors.NotFound("go.micro.client", err.Error())
	} else if err != nil {
		return nil, errors.InternalServerError("go.micro.client", err.Error())
	}

	// check if we already have a deadline
	d, ok := ctx.Deadline()
	if !ok {
		// no deadline so we create a new one
		ctx, _ = context.WithTimeout(ctx, callOpts.RequestTimeout)
	} else {
		// got a deadline so no need to setup context
		// but we need to set the timeout we pass along
		opt := client.WithRequestTimeout(d.Sub(time.Now()))
		opt(&callOpts)
	}

	// should we noop right here?
	select {
	case <-ctx.Done():
		return nil, errors.New("go.micro.client", fmt.Sprintf("%v", ctx.Err()), 408)
	default:
	}

	call := func(i int) (client.Streamer, error) {
		// call backoff first. Someone may want an initial start delay
		t, err := callOpts.Backoff(ctx, req, i)
		if err != nil {
			return nil, errors.InternalServerError("go.micro.client", err.Error())
		}

		// only sleep if greater than 0
		if t.Seconds() > 0 {
			time.Sleep(t)
		}

		node, err := next()
		if err != nil && err == selector.ErrNotFound {
			return nil, errors.NotFound("go.micro.client", err.Error())
		} else if err != nil {
			return nil, errors.InternalServerError("go.micro.client", err.Error())
		}

		addr := node.Address
		if node.Port > 0 {
			addr = fmt.Sprintf("%s:%d", addr, node.Port)
		}

		stream, err := g.stream(ctx, addr, req, callOpts)
		g.opts.Selector.Mark(req.Service(), node, err)
		return stream, err
	}

	type response struct {
		stream client.Streamer
		err    error
	}

	ch := make(chan response, callOpts.Retries)
	var grr error

	for i := 0; i < callOpts.Retries; i++ {
		go func() {
			s, err := call(i)
			ch <- response{s, err}
		}()

		select {
		case <-ctx.Done():
			return nil, errors.New("go.micro.client", fmt.Sprintf("%v", ctx.Err()), 408)
		case rsp := <-ch:
			// if the call succeeded lets bail early
			if rsp.err == nil {
				return rsp.stream, nil
			}

			retry, rerr := callOpts.Retry(ctx, req, i, err)
			if rerr != nil {
				return nil, rerr
			}

			if !retry {
				return nil, rsp.err
			}

			grr = rsp.err
		}
	}

	return nil, grr
}
Ejemplo n.º 11
0
func (g *grpcClient) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
	// make a copy of call opts
	callOpts := g.opts.CallOptions
	for _, opt := range opts {
		opt(&callOpts)
	}

	// get next nodes from the selector
	next, err := g.opts.Selector.Select(req.Service(), callOpts.SelectOptions...)
	if err != nil && err == selector.ErrNotFound {
		return errors.NotFound("go.micro.client", err.Error())
	} else if err != nil {
		return errors.InternalServerError("go.micro.client", err.Error())
	}

	// check if we already have a deadline
	d, ok := ctx.Deadline()
	if !ok {
		// no deadline so we create a new one
		ctx, _ = context.WithTimeout(ctx, callOpts.RequestTimeout)
	} else {
		// got a deadline so no need to setup context
		// but we need to set the timeout we pass along
		opt := client.WithRequestTimeout(d.Sub(time.Now()))
		opt(&callOpts)
	}

	// should we noop right here?
	select {
	case <-ctx.Done():
		return errors.New("go.micro.client", fmt.Sprintf("%v", ctx.Err()), 408)
	default:
	}

	// make copy of call method
	gcall := g.call

	// wrap the call in reverse
	for i := len(callOpts.CallWrappers); i > 0; i-- {
		gcall = callOpts.CallWrappers[i-1](gcall)
	}

	// return errors.New("go.micro.client", "request timeout", 408)
	call := func(i int) error {
		// call backoff first. Someone may want an initial start delay
		t, err := callOpts.Backoff(ctx, req, i)
		if err != nil {
			return errors.InternalServerError("go.micro.client", err.Error())
		}

		// only sleep if greater than 0
		if t.Seconds() > 0 {
			time.Sleep(t)
		}

		// select next node
		node, err := next()
		if err != nil && err == selector.ErrNotFound {
			return errors.NotFound("go.micro.client", err.Error())
		} else if err != nil {
			return errors.InternalServerError("go.micro.client", err.Error())
		}

		// set the address
		addr := node.Address
		if node.Port > 0 {
			addr = fmt.Sprintf("%s:%d", addr, node.Port)
		}

		// make the call
		err = gcall(ctx, addr, req, rsp, callOpts)
		g.opts.Selector.Mark(req.Service(), node, err)
		return err
	}

	ch := make(chan error, callOpts.Retries)
	var gerr error

	for i := 0; i < callOpts.Retries; i++ {
		go func() {
			ch <- call(i)
		}()

		select {
		case <-ctx.Done():
			return errors.New("go.micro.client", fmt.Sprintf("%v", ctx.Err()), 408)
		case err := <-ch:
			// if the call succeeded lets bail early
			if err == nil {
				return nil
			}

			retry, rerr := callOpts.Retry(ctx, req, i, err)
			if rerr != nil {
				return rerr
			}

			if !retry {
				return err
			}

			gerr = err
		}
	}

	return gerr
}