func (c *cacheFilter) Call(ctx context.Context, request *transport.Request, out transport.UnaryOutbound) (*transport.Response, error) { data := *c // Read the entire request body to match against the cache body, err := ioutil.ReadAll(request.Body) if err != nil { return nil, err } request.Body = ioutil.NopCloser(bytes.NewReader(body)) if v, ok := data[string(body)]; ok { fmt.Println("cache hit") return &transport.Response{ Headers: v.Headers, Body: ioutil.NopCloser(bytes.NewReader(v.Body)), }, nil } fmt.Println("cache miss") res, err := out.Call(ctx, request) if err != nil { return nil, err } defer res.Body.Close() resBody, err := ioutil.ReadAll(res.Body) if err != nil { return nil, err } data[string(body)] = entry{Headers: res.Headers, Body: resBody} res.Body = ioutil.NopCloser(bytes.NewReader(resBody)) return res, nil }
// Phone implements the phone procedure func Phone(ctx context.Context, reqMeta yarpc.ReqMeta, body *PhoneRequest) (*PhoneResponse, yarpc.ResMeta, error) { var outbound transport.UnaryOutbound switch { case body.Transport.HTTP != nil: t := body.Transport.HTTP url := fmt.Sprintf("http://%s:%d", t.Host, t.Port) outbound = ht.NewOutbound(url) case body.Transport.TChannel != nil: t := body.Transport.TChannel hostport := fmt.Sprintf("%s:%d", t.Host, t.Port) ch, err := tchannel.NewChannel("yarpc-test-client", nil) if err != nil { return nil, nil, fmt.Errorf("failed to build TChannel: %v", err) } outbound = tch.NewOutbound(ch, tch.HostPort(hostport)) default: return nil, nil, fmt.Errorf("unconfigured transport") } if err := outbound.Start(transport.NoDeps); err != nil { return nil, nil, err } defer outbound.Stop() // TODO use reqMeta.Service for caller client := json.New(channel.MultiOutbound("yarpc-test", body.Service, transport.Outbounds{ Unary: outbound, })) resBody := PhoneResponse{ Service: "yarpc-test", // TODO use reqMeta.Service Procedure: reqMeta.Procedure(), } ctx, cancel := context.WithTimeout(ctx, 500*time.Millisecond) defer cancel() _, err := client.Call( ctx, yarpc.NewReqMeta().Procedure(body.Procedure), body.Body, &resBody.Body) if err != nil { return nil, nil, err } return &resBody, nil, nil }
// Call implements the yarpc transport filter interface func (r *Recorder) Call( ctx context.Context, request *transport.Request, out transport.UnaryOutbound) (*transport.Response, error) { log := r.logger requestRecord := r.requestToRequestRecord(request) requestHash := r.hashRequestRecord(&requestRecord) filepath := r.makeFilePath(request, requestHash) switch r.mode { case Replay: cachedRecord, err := r.loadRecord(filepath) if err != nil { log.Fatal(err) } response := r.recordToResponse(cachedRecord) return &response, nil case Append: cachedRecord, err := r.loadRecord(filepath) if err == nil { response := r.recordToResponse(cachedRecord) return &response, nil } fallthrough case Overwrite: response, err := out.Call(ctx, request) if err == nil { cachedRecord := record{ Version: currentRecordVersion, Request: requestRecord, Response: r.responseToResponseRecord(response), } r.saveRecord(filepath, &cachedRecord) } return response, err default: panic(fmt.Sprintf("invalid record mode: %v", r.mode)) } }
func (c *countFilter) Call( ctx context.Context, req *transport.Request, o transport.UnaryOutbound) (*transport.Response, error) { c.Count++ return o.Call(ctx, req) }
func (requestLogFilter) Call( ctx context.Context, request *transport.Request, out transport.UnaryOutbound) (*transport.Response, error) { fmt.Printf("sending request %q to service %q (encoding %q)\n", request.Procedure, request.Service, request.Encoding) return out.Call(ctx, request) }