2022-10-20 11:49:27 +00:00
|
|
|
// Copyright (C) 2022 The Qt Company Ltd.
|
|
|
|
|
// Copyright (C) 2019 Alexey Edelev <semlanik@gmail.com>
|
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
|
|
|
|
|
2024-07-03 09:02:17 +00:00
|
|
|
#include <QtGrpc/private/qtgrpcglobal_p.h>
|
|
|
|
|
#include <QtGrpc/qgrpcoperation.h>
|
|
|
|
|
#include <QtGrpc/qgrpcoperationcontext.h>
|
|
|
|
|
|
2023-02-08 14:46:54 +00:00
|
|
|
#include <QtCore/private/qobject_p.h>
|
2024-04-15 11:01:07 +00:00
|
|
|
#include <QtCore/qatomic.h>
|
2024-07-23 16:10:49 +00:00
|
|
|
#include <QtCore/qbytearray.h>
|
2023-09-05 10:39:18 +00:00
|
|
|
#include <QtCore/qeventloop.h>
|
2024-04-15 11:01:07 +00:00
|
|
|
#include <QtCore/qpointer.h>
|
2023-02-08 14:46:54 +00:00
|
|
|
|
2022-10-20 11:49:27 +00:00
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
|
2023-08-06 20:07:05 +00:00
|
|
|
using namespace Qt::StringLiterals;
|
|
|
|
|
|
2022-10-20 11:49:27 +00:00
|
|
|
/*!
|
2022-12-16 08:55:22 +00:00
|
|
|
\class QGrpcOperation
|
2023-03-10 09:49:15 +00:00
|
|
|
\inmodule QtGrpc
|
2022-12-16 08:55:22 +00:00
|
|
|
\brief The QGrpcOperation class implements common logic to
|
2023-08-06 20:07:05 +00:00
|
|
|
handle the gRPC communication from the client side.
|
2022-12-08 12:53:08 +00:00
|
|
|
*/
|
2022-10-20 11:49:27 +00:00
|
|
|
|
|
|
|
|
/*!
|
2024-05-24 12:34:17 +00:00
|
|
|
\fn void QGrpcOperation::finished(const QGrpcStatus &status)
|
2022-12-08 12:53:08 +00:00
|
|
|
|
|
|
|
|
This signal indicates the end of communication for this call.
|
|
|
|
|
|
2024-05-24 12:34:17 +00:00
|
|
|
If this signal is emitted the respective operation when it's finished with
|
|
|
|
|
the respective \a status.
|
2024-08-20 16:07:01 +00:00
|
|
|
|
|
|
|
|
\note This signal is emitted only once, and in most cases, you will want to
|
|
|
|
|
disconnect right after receiving it to avoid issues, such as lambda
|
|
|
|
|
captures not being destroyed after receiving the signal. An easy way to
|
|
|
|
|
achieve this is by using the Qt::SingleShotConnection \l {Qt::}
|
|
|
|
|
{ConnectionType}.
|
2022-12-08 12:53:08 +00:00
|
|
|
*/
|
2022-10-20 11:49:27 +00:00
|
|
|
|
2023-02-08 14:46:54 +00:00
|
|
|
class QGrpcOperationPrivate : public QObjectPrivate
|
|
|
|
|
{
|
|
|
|
|
Q_DECLARE_PUBLIC(QGrpcOperation)
|
|
|
|
|
public:
|
2024-06-21 09:51:29 +00:00
|
|
|
explicit QGrpcOperationPrivate(std::shared_ptr<QGrpcOperationContext> &&operationContext_)
|
|
|
|
|
: operationContext(operationContext_)
|
2023-04-21 10:01:26 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-08 14:46:54 +00:00
|
|
|
QByteArray data;
|
2024-06-21 09:29:21 +00:00
|
|
|
std::shared_ptr<QGrpcOperationContext> operationContext;
|
2023-09-05 10:39:18 +00:00
|
|
|
QAtomicInteger<bool> isFinished{ false };
|
2023-02-08 14:46:54 +00:00
|
|
|
};
|
|
|
|
|
|
2024-06-21 09:29:21 +00:00
|
|
|
QGrpcOperation::QGrpcOperation(std::shared_ptr<QGrpcOperationContext> operationContext,
|
2024-04-09 11:01:28 +00:00
|
|
|
QObject *parent)
|
2024-06-21 09:29:21 +00:00
|
|
|
: QObject(*new QGrpcOperationPrivate(std::move(operationContext)), parent)
|
2022-10-20 11:49:27 +00:00
|
|
|
{
|
2024-06-21 09:29:21 +00:00
|
|
|
Q_D(QGrpcOperation);
|
|
|
|
|
[[maybe_unused]] bool valid = QObject::connect(d->operationContext.get(),
|
|
|
|
|
&QGrpcOperationContext::messageReceived, this,
|
2024-05-15 15:53:53 +00:00
|
|
|
[this](const QByteArray &data) {
|
|
|
|
|
Q_D(QGrpcOperation);
|
|
|
|
|
d->data = data;
|
|
|
|
|
});
|
2023-08-06 20:07:05 +00:00
|
|
|
Q_ASSERT_X(valid, "QGrpcOperation::QGrpcOperation",
|
2024-05-15 15:53:53 +00:00
|
|
|
"Unable to make connection to the 'messageReceived' signal");
|
2023-08-06 20:07:05 +00:00
|
|
|
|
2024-06-21 09:29:21 +00:00
|
|
|
valid = QObject::connect(d->operationContext.get(), &QGrpcOperationContext::finished, this,
|
|
|
|
|
[this](const QGrpcStatus &status) {
|
2024-05-24 12:34:17 +00:00
|
|
|
if (!isFinished()) {
|
2024-06-21 11:13:40 +00:00
|
|
|
Q_D(QGrpcOperation);
|
|
|
|
|
d->isFinished.storeRelaxed(true);
|
2024-05-24 12:34:17 +00:00
|
|
|
emit this->finished(status);
|
|
|
|
|
}
|
2023-09-05 10:39:18 +00:00
|
|
|
});
|
2023-08-06 20:07:05 +00:00
|
|
|
Q_ASSERT_X(valid, "QGrpcOperation::QGrpcOperation",
|
|
|
|
|
"Unable to make connection to the 'finished' signal");
|
2022-10-20 11:49:27 +00:00
|
|
|
}
|
|
|
|
|
|
2022-12-09 12:03:04 +00:00
|
|
|
QGrpcOperation::~QGrpcOperation() = default;
|
|
|
|
|
|
2023-02-08 14:46:54 +00:00
|
|
|
/*!
|
2024-08-23 21:28:44 +00:00
|
|
|
\fn template <typename T, QtProtobuf::if_protobuf_message<T> = true> std::optional<T> QGrpcOperation::read() const
|
2024-06-24 10:32:34 +00:00
|
|
|
|
|
|
|
|
Reads a message from a raw byte array stored within this QGrpcOperation
|
|
|
|
|
instance.
|
|
|
|
|
|
|
|
|
|
Returns an optional deserialized message. On failure, \c {std::nullopt} is
|
|
|
|
|
returned.
|
|
|
|
|
|
|
|
|
|
The error can be retrieved using \l deserializationError.
|
|
|
|
|
|
2024-07-05 12:13:49 +00:00
|
|
|
\note This function only participates in overload resolution if \c T is a
|
|
|
|
|
subclass of QProtobufMessage.
|
|
|
|
|
|
2024-06-24 10:32:34 +00:00
|
|
|
\sa read, deserializationError, deserializationErrorString
|
2023-02-08 14:46:54 +00:00
|
|
|
*/
|
|
|
|
|
|
2024-01-14 18:12:17 +00:00
|
|
|
/*!
|
|
|
|
|
\since 6.8
|
2024-04-15 11:01:07 +00:00
|
|
|
Reads a message from a raw byte array which is stored within this
|
|
|
|
|
QGrpcOperation instance.
|
2024-01-14 18:12:17 +00:00
|
|
|
|
2024-04-15 11:01:07 +00:00
|
|
|
The function writes the deserialized value to the \a message pointer.
|
2024-01-14 18:12:17 +00:00
|
|
|
|
2024-04-15 11:01:07 +00:00
|
|
|
If the deserialization is successful, this function returns \c true.
|
|
|
|
|
Otherwise, it returns \c false, and the error can be retrieved with \l
|
|
|
|
|
deserializationError.
|
2024-01-14 18:12:17 +00:00
|
|
|
|
2024-04-15 11:01:07 +00:00
|
|
|
\sa read, deserializationError, deserializationErrorString
|
2024-01-14 18:12:17 +00:00
|
|
|
*/
|
2024-04-15 11:01:07 +00:00
|
|
|
bool QGrpcOperation::read(QProtobufMessage *message) const
|
2024-01-14 18:12:17 +00:00
|
|
|
{
|
|
|
|
|
Q_ASSERT_X(message != nullptr, "QGrpcOperation::read",
|
|
|
|
|
"Can't read to nullptr QProtobufMessage");
|
2024-06-21 09:29:21 +00:00
|
|
|
Q_D(const QGrpcOperation);
|
|
|
|
|
const auto ser = d->operationContext->serializer();
|
2024-08-24 12:19:06 +00:00
|
|
|
Q_ASSERT_X(ser, "QGrpcOperation", "The serializer is null");
|
|
|
|
|
return ser->deserialize(message, d->data);
|
2024-01-14 18:12:17 +00:00
|
|
|
}
|
|
|
|
|
|
2024-06-24 10:32:34 +00:00
|
|
|
/*!
|
|
|
|
|
T.B.A
|
|
|
|
|
*/
|
|
|
|
|
void QGrpcOperation::cancel()
|
|
|
|
|
{
|
|
|
|
|
if (!isFinished()) {
|
|
|
|
|
Q_D(QGrpcOperation);
|
|
|
|
|
d->isFinished.storeRelaxed(true);
|
|
|
|
|
emit d->operationContext->cancelRequested();
|
2024-07-10 16:20:30 +00:00
|
|
|
Q_EMIT finished(QGrpcStatus{ QtGrpc::StatusCode::Cancelled,
|
2024-06-24 10:32:34 +00:00
|
|
|
tr("Operation is cancelled by client") });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-11 12:28:31 +00:00
|
|
|
/*!
|
|
|
|
|
\since 6.8
|
|
|
|
|
|
|
|
|
|
Returns the last deserialization error.
|
|
|
|
|
|
|
|
|
|
\sa QAbstractProtobufSerializer::deserializationError
|
|
|
|
|
*/
|
|
|
|
|
QAbstractProtobufSerializer::DeserializationError QGrpcOperation::deserializationError() const
|
|
|
|
|
{
|
2024-06-21 09:29:21 +00:00
|
|
|
Q_D(const QGrpcOperation);
|
|
|
|
|
const auto ser = d->operationContext->serializer();
|
2024-08-24 12:19:06 +00:00
|
|
|
Q_ASSERT_X(ser, "QGrpcOperation", "The serializer is null");
|
2024-04-11 12:28:31 +00:00
|
|
|
return ser->deserializationError();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\since 6.8
|
|
|
|
|
|
|
|
|
|
Returns the last deserialization error string.
|
|
|
|
|
|
|
|
|
|
\sa QAbstractProtobufSerializer::deserializationErrorString
|
|
|
|
|
*/
|
|
|
|
|
QString QGrpcOperation::deserializationErrorString() const
|
|
|
|
|
{
|
2024-06-21 09:29:21 +00:00
|
|
|
Q_D(const QGrpcOperation);
|
|
|
|
|
const auto ser = d->operationContext->serializer();
|
2024-08-24 12:19:06 +00:00
|
|
|
Q_ASSERT_X(ser, "QGrpcOperation", "The serializer is null");
|
2024-04-11 12:28:31 +00:00
|
|
|
return ser->deserializationErrorString();
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-17 14:39:05 +00:00
|
|
|
/*!
|
2023-08-06 20:07:05 +00:00
|
|
|
Getter of the metadata received from the channel. For the HTTP2 channels it
|
|
|
|
|
usually contains the HTTP headers received from the server.
|
2023-05-17 14:39:05 +00:00
|
|
|
*/
|
2024-07-23 16:10:49 +00:00
|
|
|
const QHash<QByteArray, QByteArray> &QGrpcOperation::metadata() const & noexcept
|
2023-05-17 14:39:05 +00:00
|
|
|
{
|
2024-06-21 09:29:21 +00:00
|
|
|
Q_D(const QGrpcOperation);
|
|
|
|
|
return d->operationContext->serverMetadata();
|
2023-05-17 14:39:05 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-13 16:07:11 +00:00
|
|
|
/*!
|
2024-04-09 11:01:28 +00:00
|
|
|
Getter of the method that this operation was initialized with.
|
2023-08-13 16:07:11 +00:00
|
|
|
*/
|
2024-03-26 13:08:51 +00:00
|
|
|
QLatin1StringView QGrpcOperation::method() const noexcept
|
2023-08-13 16:07:11 +00:00
|
|
|
{
|
2024-06-21 09:29:21 +00:00
|
|
|
Q_D(const QGrpcOperation);
|
|
|
|
|
return d->operationContext->method();
|
2023-08-13 16:07:11 +00:00
|
|
|
}
|
|
|
|
|
|
2023-09-05 10:39:18 +00:00
|
|
|
/*!
|
|
|
|
|
Returns true when QGrpcOperation finished its workflow,
|
|
|
|
|
meaning it was finished, canceled, or error occurred, otherwise returns false.
|
|
|
|
|
*/
|
2024-03-26 13:08:51 +00:00
|
|
|
bool QGrpcOperation::isFinished() const noexcept
|
2023-09-05 10:39:18 +00:00
|
|
|
{
|
2024-06-21 11:13:40 +00:00
|
|
|
Q_D(const QGrpcOperation);
|
|
|
|
|
return d->isFinished.loadRelaxed();
|
2023-09-05 10:39:18 +00:00
|
|
|
}
|
|
|
|
|
|
2024-06-20 13:44:12 +00:00
|
|
|
/*!
|
|
|
|
|
\internal
|
2024-07-31 07:55:53 +00:00
|
|
|
\fn const QGrpcOperationContext &QGrpcOperation::context() const &
|
|
|
|
|
\fn QGrpcOperationContext &QGrpcOperation::context() &
|
|
|
|
|
|
|
|
|
|
Returns a reference to the internal operation context.
|
2024-06-20 13:44:12 +00:00
|
|
|
*/
|
2024-07-31 07:55:53 +00:00
|
|
|
const QGrpcOperationContext &QGrpcOperation::context() const & noexcept
|
2024-06-20 13:44:12 +00:00
|
|
|
{
|
2024-06-21 09:29:21 +00:00
|
|
|
Q_D(const QGrpcOperation);
|
2024-07-31 07:55:53 +00:00
|
|
|
return *d->operationContext;
|
2024-06-20 13:44:12 +00:00
|
|
|
}
|
|
|
|
|
|
2024-07-10 16:42:57 +00:00
|
|
|
bool QGrpcOperation::event(QEvent *event)
|
|
|
|
|
{
|
|
|
|
|
return QObject::event(event);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-20 11:49:27 +00:00
|
|
|
QT_END_NAMESPACE
|
2022-12-09 12:03:04 +00:00
|
|
|
|
|
|
|
|
#include "moc_qgrpcoperation.cpp"
|