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 }
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()) }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }