QtProtobuf  0.6
Protobuf plugin to generate Qt classes
qabstractgrpcclient.h
1 /*
2  * MIT License
3  *
4  * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>
5  *
6  * This file is part of QtProtobuf project https://git.semlanik.org/semlanik/qtprotobuf
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy of this
9  * software and associated documentation files (the "Software"), to deal in the Software
10  * without restriction, including without limitation the rights to use, copy, modify,
11  * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
12  * to permit persons to whom the Software is furnished to do so, subject to the following
13  * conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in all copies
16  * or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
19  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
20  * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
21  * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  */
25 
26 #pragma once //QAbstractGrpcClient
27 
28 #include <memory>
29 #include <functional>
30 #include <type_traits>
31 
32 #include <QObject>
33 #include <QPointer>
34 #include <QByteArray>
35 
36 #include <qtprotobuflogging.h>
37 #include <qabstractprotobufserializer.h>
38 
39 #include "qabstractgrpcchannel.h"
40 
41 #include "qtgrpcglobal.h"
42 
47 namespace QtProtobuf {
48 
49 class QGrpcAsyncReply;
50 class QGrpcSubscription;
51 class QGrpcAsyncOperationBase;
52 class QAbstractGrpcChannel;
53 class QAbstractGrpcClientPrivate;
54 
58 using SubscriptionHandler = std::function<void(const QByteArray&)>;
59 
66 class Q_GRPC_EXPORT QAbstractGrpcClient : public QObject
67 {
68  Q_OBJECT
69 public:
78  void attachChannel(const std::shared_ptr<QAbstractGrpcChannel> &channel);
79 
80 signals:
86  void error(const QGrpcStatus &status);
87 
88 protected:
89  QAbstractGrpcClient(const QString &service, QObject *parent = nullptr);
90  virtual ~QAbstractGrpcClient();
91 
99  template<typename A, typename R>
100  QGrpcStatus call(const QString &method, const A &arg, const QPointer<R> &ret) {
102  if (ret.isNull()) {
103  static const QString errorString("Unable to call method: %1. Pointer to return data is null");
104  status = QGrpcStatus{QGrpcStatus::InvalidArgument, errorString.arg(method)};
105  error(status);
106  qProtoCritical() << errorString.arg(method);
107  return status;
108  }
109 
110  QByteArray retData;
111  status = call(method, arg.serialize(serializer()), retData);
112  if (status == QGrpcStatus::StatusCode::Ok) {
113  return tryDeserialize(*ret, retData);
114  }
115  return status;
116  }
117 
124  template<typename A>
125  QGrpcAsyncReplyShared call(const QString &method, const A &arg) {
126  return call(method, arg.serialize(serializer()));
127  }
128 
137  template<typename A>
138  QGrpcSubscriptionShared subscribe(const QString &method, const A &arg) {
139  return subscribe(method, arg.serialize(serializer()));
140  }
141 
152  template<typename A, typename R>
153  QGrpcSubscriptionShared subscribe(const QString &method, const A &arg, const QPointer<R> &ret) {
154  if (ret.isNull()) {
155  static const QString nullPointerError("Unable to subscribe method: %1. Pointer to return data is null");
156  error({QGrpcStatus::InvalidArgument, nullPointerError.arg(method)});
157  qProtoCritical() << nullPointerError.arg(method);
158  return nullptr;
159  }
160 
161  return subscribe(method, arg.serialize(serializer()), [ret, this](const QByteArray &data) {
162  if (!ret.isNull()) {
163  tryDeserialize(*ret, data);
164  } else {
165  static const QLatin1String nullPointerError("Pointer to return data is null while subscription update received");
166  error({QGrpcStatus::InvalidArgument, nullPointerError});
167  qProtoCritical() << nullPointerError;
168  }
169  });
170  }
171 
176  void cancel(const QString &method);
177 
182  QAbstractProtobufSerializer *serializer() const;
183 
184  friend class QGrpcAsyncOperationBase;
185 private:
187  QGrpcStatus call(const QString &method, const QByteArray &arg, QByteArray &ret);
188 
190  QGrpcAsyncReplyShared call(const QString &method, const QByteArray &arg);
191 
193  QGrpcSubscriptionShared subscribe(const QString &method, const QByteArray &arg, const QtProtobuf::SubscriptionHandler &handler = {});
194 
199  template<typename R>
200  QGrpcStatus tryDeserialize(R &ret, const QByteArray &retData) {
202  try {
203  ret.deserialize(serializer(), retData);
204  } catch (std::invalid_argument &) {
205  static const QLatin1String invalidArgumentErrorMessage("Response deserialization failed invalid field found");
206  status = {QGrpcStatus::InvalidArgument, invalidArgumentErrorMessage};
207  error(status);
208  qProtoCritical() << invalidArgumentErrorMessage;
209  } catch (std::out_of_range &) {
210  static const QLatin1String outOfRangeErrorMessage("Invalid size of received buffer");
211  status = {QGrpcStatus::OutOfRange, outOfRangeErrorMessage};
212  error(status);
213  qProtoCritical() << outOfRangeErrorMessage;
214  } catch (...) {
215  status = {QGrpcStatus::Internal, QLatin1String("Unknown exception caught during deserialization")};
216  error(status);
217  }
218  return status;
219  }
220 
221  Q_DISABLE_COPY_MOVE(QAbstractGrpcClient)
222 
223  std::unique_ptr<QAbstractGrpcClientPrivate> dPtr;
224 };
225 }
The QAbstractGrpcClient class is bridge between gRPC clients and channels.
Definition: qabstractgrpcclient.h:67
void cancel(const QString &method)
Canceles all subscriptions for specified method.
void error(const QGrpcStatus &status)
error signal is emited by client when error occured in channel or while serialization/deserialization
The QAbstractProtobufSerializer class is interface that represents basic functions for serialization/...
Definition: qabstractprotobufserializer.h:72
The QGrpcStatus class contains information about last gRPC operation.
Definition: qgrpcstatus.h:58
@ Ok
No error.
Definition: qgrpcstatus.h:70
@ OutOfRange
The operation was attempted past the valid range.
Definition: qgrpcstatus.h:82
@ Internal
Internal errors.
Definition: qgrpcstatus.h:84
@ InvalidArgument
The client specified an invalid argument.
Definition: qgrpcstatus.h:73