tupleRange, tuplePrepend
[folly.git] / folly / wangle / service / Service.h
1 /*
2  * Copyright 2015 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17
18 #include <folly/futures/Future.h>
19 #include <folly/Memory.h>
20
21 #include <folly/wangle/bootstrap/ServerBootstrap.h>
22 #include <folly/wangle/bootstrap/ClientBootstrap.h>
23 #include <folly/wangle/channel/Pipeline.h>
24 #include <folly/wangle/channel/AsyncSocketHandler.h>
25
26 namespace folly {
27
28 /**
29  * A Service is an asynchronous function from Request to
30  * Future<Response>. It is the basic unit of the RPC interface.
31  */
32 template <typename Req, typename Resp = Req>
33 class Service {
34  public:
35   virtual Future<Resp> operator()(Req request) = 0;
36   virtual ~Service() {}
37 };
38
39 /**
40  * A Filter acts as a decorator/transformer of a service. It may apply
41  * transformations to the input and output of that service:
42  *
43  *          class MyService
44  *
45  * ReqA  -> |
46  *          | -> ReqB
47  *          | <- RespB
48  * RespA <- |
49  *
50  * For example, you may have a service that takes Strings and parses
51  * them as Ints.  If you want to expose this as a Network Service via
52  * Thrift, it is nice to isolate the protocol handling from the
53  * business rules. Hence you might have a Filter that converts back
54  * and forth between Thrift structs:
55  *
56  * [ThriftIn -> (String  ->  Int) -> ThriftOut]
57  */
58 template <typename ReqA, typename RespA,
59           typename ReqB = ReqA, typename RespB = RespA>
60 class Filter {
61   public:
62   virtual Future<RespA> operator()(
63     Service<ReqB, RespB>* service, ReqA request) = 0;
64   std::unique_ptr<Service<ReqA, RespA>> compose(
65     Service<ReqB, RespB>* service);
66   virtual ~Filter() {}
67 };
68
69 template <typename ReqA, typename RespA,
70           typename ReqB = ReqA, typename RespB = RespA>
71 class ComposedService : public Service<ReqA, RespA> {
72   public:
73   ComposedService(Service<ReqB, RespB>* service,
74                   Filter<ReqA, RespA, ReqB, RespB>* filter)
75     : service_(service)
76     , filter_(filter) {}
77   virtual Future<RespA> operator()(ReqA request) override {
78     return (*filter_)(service_, request);
79   }
80
81   ~ComposedService(){}
82   private:
83   Service<ReqB, RespB>* service_;
84   Filter<ReqA, RespA, ReqB, RespB>* filter_;
85 };
86
87 template <typename ReqA, typename RespA,
88           typename ReqB, typename RespB>
89   std::unique_ptr<Service<ReqA, RespA>>
90     Filter<ReqA, RespA, ReqB, RespB>::compose(Service<ReqB, RespB>* service) {
91   return  folly::make_unique<ComposedService<ReqA, RespA, ReqB, RespB>>(
92     service, this);
93 }
94
95 /**
96  * A factory that creates services, given a client.  This lets you
97  * make RPC calls on the Service interface over a client's pipeline.
98  *
99  * Clients can be reused after you are done using the service.
100  */
101 template <typename Pipeline, typename Req, typename Resp>
102 class ServiceFactory {
103  public:
104   virtual Future<Service<Req, Resp>*> operator()(
105     ClientBootstrap<Pipeline>* client) = 0;
106
107   virtual ~ServiceFactory() = default;
108 };
109
110 } // namespace