use LogosObject instead of QObject

This commit is contained in:
Iuri Matias
2026-03-20 21:02:05 +00:00
committed by Logos Workspace
parent 3d712f8e07
commit d35653ec8a
18 changed files with 569 additions and 789 deletions
+23 -131
View File
@@ -1,4 +1,5 @@
#include "logos_api_consumer.h"
#include "logos_object.h"
#include "module_proxy.h"
#include "logos_api_client.h"
#include "token_manager.h"
@@ -6,10 +7,6 @@
#include "logos_instance.h"
#include "logos_transport.h"
#include "logos_transport_factory.h"
#include <QRemoteObjectPendingCall>
#include <QRemoteObjectPendingCallWatcher>
#include <QPointer>
#include <QTimer>
#include <QDebug>
#include <QUrl>
#include <QMetaObject>
@@ -26,14 +23,9 @@ LogosAPIConsumer::LogosAPIConsumer(const QString& module_to_talk_to, const QStri
LogosAPIConsumer::~LogosAPIConsumer()
{
for (auto it = m_connections.begin(); it != m_connections.end(); ++it) {
QObject::disconnect(it.value());
}
m_eventCallbacks.clear();
m_connections.clear();
}
QObject* LogosAPIConsumer::requestObject(const QString& objectName, Timeout timeout)
LogosObject* LogosAPIConsumer::requestObject(const QString& objectName, Timeout timeout)
{
qDebug() << "LogosAPIConsumer: Requesting object:" << objectName << "at" << QTime::currentTime().toString("hh:mm:ss.zzz");
@@ -47,9 +39,9 @@ QObject* LogosAPIConsumer::requestObject(const QString& objectName, Timeout time
return nullptr;
}
QObject* object = m_transport->requestObject(objectName, timeout.ms);
LogosObject* object = m_transport->requestObject(objectName, timeout.ms);
if (object) {
qDebug() << "LogosAPIConsumer: Successfully acquired object:" << objectName;
qDebug() << "[LogosObject] LogosAPIConsumer: acquired LogosObject for:" << objectName << "(id:" << object->id() << ")";
}
return object;
}
@@ -75,147 +67,46 @@ QVariant LogosAPIConsumer::invokeRemoteMethod(const QString& authToken, const QS
{
qDebug() << "LogosAPIConsumer: Calling invokeRemoteMethod:" << objectName << methodName << "args_count:" << args.size() << "timeout:" << timeout.ms;
QObject* plugin = m_transport->requestObject(objectName, timeout.ms);
LogosObject* plugin = m_transport->requestObject(objectName, timeout.ms);
if (!plugin) {
qWarning() << "LogosAPIConsumer: Failed to acquire plugin/replica for object:" << objectName;
return QVariant();
}
QVariant result = m_transport->callRemoteMethod(plugin, authToken, methodName, args, timeout.ms);
m_transport->releaseObject(plugin);
qDebug() << "[LogosObject] LogosAPIConsumer: calling via LogosObject::callMethod" << methodName;
QVariant result = plugin->callMethod(authToken, methodName, args, timeout.ms);
plugin->release();
return result;
}
void LogosAPIConsumer::invokeRemoteMethodAsync(const QString& authToken, const QString& objectName, const QString& methodName,
const QVariantList& args,
AsyncResultCallback callback,
Timeout timeout)
void LogosAPIConsumer::onEvent(LogosObject* originObject, const QString& eventName, std::function<void(const QString&, const QVariantList&)> callback)
{
if (!callback) {
qWarning() << "LogosAPIConsumer: invokeRemoteMethodAsync called with null callback";
qDebug() << "[LogosObject] LogosAPIConsumer::onEvent registering for:" << eventName << "on LogosObject id:" << originObject;
if (!originObject) {
qWarning() << "LogosAPIConsumer: Cannot register event on null object";
return;
}
QObject* plugin = requestObject(objectName, timeout);
if (!plugin) {
qWarning() << "LogosAPIConsumer: Failed to acquire plugin/replica for object:" << objectName;
QTimer::singleShot(0, this, [callback]() { callback(QVariant()); });
return;
}
originObject->onEvent(eventName, std::move(callback));
ModuleProxy* moduleProxy = qobject_cast<ModuleProxy*>(plugin);
if (moduleProxy) {
QVariant result = moduleProxy->callRemoteMethod(authToken, methodName, args);
if (!LogosModeConfig::isLocal()) {
delete plugin;
}
QTimer::singleShot(0, this, [callback, result]() { callback(result); });
return;
}
if (LogosModeConfig::isLocal()) {
qWarning() << "LogosAPIConsumer: Local mode requires ModuleProxy-wrapped objects";
QTimer::singleShot(0, this, [callback]() { callback(QVariant()); });
return;
}
QRemoteObjectPendingCall pendingCall;
bool success = QMetaObject::invokeMethod(
plugin,
"callRemoteMethod",
Qt::DirectConnection,
Q_RETURN_ARG(QRemoteObjectPendingCall, pendingCall),
Q_ARG(QString, authToken),
Q_ARG(QString, methodName),
Q_ARG(QVariantList, args)
);
if (!success) {
qWarning() << "LogosAPIConsumer: Failed to invoke callRemoteMethod on replica for object:" << objectName;
delete plugin;
QTimer::singleShot(0, this, [callback]() { callback(QVariant()); });
return;
}
QRemoteObjectPendingCallWatcher* watcher = new QRemoteObjectPendingCallWatcher(pendingCall, this);
QPointer<QRemoteObjectPendingCallWatcher> watcherRef(watcher);
QObject* pluginToDelete = plugin;
// Use QueuedConnection so the callback always runs on the consumer's (e.g. main) thread,
// even if the watcher emits finished() from an IO or worker thread. Otherwise the callback
// may never run or may run in a context where UI/consumer state is inaccessible.
connect(watcher, &QRemoteObjectPendingCallWatcher::finished, this, [watcherRef, callback, pluginToDelete]() {
QVariant result;
if (!watcherRef.isNull() && watcherRef->error() == QRemoteObjectPendingCall::NoError) {
result = watcherRef->returnValue();
}
if (callback) callback(result);
delete pluginToDelete;
if (!watcherRef.isNull()) watcherRef->deleteLater();
}, Qt::QueuedConnection);
QTimer::singleShot(timeout.ms, this, [watcherRef, callback, pluginToDelete]() {
if (!watcherRef.isNull() && !watcherRef->isFinished()) {
if (callback) callback(QVariant());
delete pluginToDelete;
watcherRef->deleteLater();
}
});
}
void LogosAPIConsumer::onEvent(QObject* originObject, QObject* destinationObject, const QString& eventName, std::function<void(const QString&, const QVariantList&)> callback)
{
qDebug() << "LogosAPIConsumer: Registering event listener for event:" << eventName;
m_eventCallbacks[eventName].append(callback);
if (!m_connections.contains(originObject)) {
auto connection = QObject::connect(originObject, SIGNAL(eventResponse(QString, QVariantList)),
this, SLOT(invokeCallback(QString, QVariantList)));
if (connection) {
m_connections[originObject] = connection;
qDebug() << "LogosAPIConsumer: Created new connection for origin object";
} else {
qWarning() << "LogosAPIConsumer: Failed to create connection for event:" << eventName;
}
} else {
qDebug() << "LogosAPIConsumer: Reusing existing connection for origin object";
}
qDebug() << "LogosAPIConsumer: Registered callback for event:" << eventName;
}
void LogosAPIConsumer::invokeCallback(const QString& eventName, const QVariantList& data)
{
for (const auto& callback : m_eventCallbacks[eventName]) {
try {
callback(eventName, data);
} catch (...) {
qWarning() << "LogosAPIConsumer: Exception in callback for event:" << eventName;
}
}
}
void LogosAPIConsumer::onEvent(QObject* originObject, QObject* destinationObject, const QString& eventName)
{
qDebug() << "LogosAPIConsumer: Registering event listener for event:" << eventName << "(connecting to destination slot)";
QObject::connect(originObject, SIGNAL(eventResponse(QString, QVariantList)),
destinationObject, SLOT(onEventResponse(QString, QVariantList)), Qt::AutoConnection);
qDebug() << "[LogosObject] LogosAPIConsumer: event callback registered for:" << eventName;
}
bool LogosAPIConsumer::informModuleToken(const QString& authToken, const QString& moduleName, const QString& token)
{
qDebug() << "LogosAPIConsumer: Informing module token for module:" << moduleName << "with token:" << token;
QObject* plugin = m_transport->requestObject("capability_module", 20000);
LogosObject* plugin = m_transport->requestObject("capability_module", 20000);
if (!plugin) {
qWarning() << "LogosAPIConsumer: Failed to acquire plugin/replica for object: capability_module";
return false;
}
bool result = m_transport->callInformModuleToken(plugin, authToken, moduleName, token, 20000);
qDebug() << "[LogosObject] LogosAPIConsumer: calling LogosObject::informModuleToken for" << moduleName;
bool result = plugin->informModuleToken(authToken, moduleName, token, 20000);
qDebug() << "LogosAPIConsumer: informModuleToken completed with result:" << result;
m_transport->releaseObject(plugin);
plugin->release();
return result;
}
@@ -223,14 +114,15 @@ bool LogosAPIConsumer::informModuleToken_module(const QString& authToken, const
{
qDebug() << "LogosAPIConsumer: Informing module token for module:" << moduleName << "with token:" << token;
QObject* plugin = m_transport->requestObject(originModule, 20000);
LogosObject* plugin = m_transport->requestObject(originModule, 20000);
if (!plugin) {
qWarning() << "LogosAPIConsumer: Failed to acquire plugin/replica for object:" << originModule;
return false;
}
bool result = m_transport->callInformModuleToken(plugin, authToken, moduleName, token, 20000);
qDebug() << "[LogosObject] LogosAPIConsumer: calling LogosObject::informModuleToken for" << moduleName << "on" << originModule;
bool result = plugin->informModuleToken(authToken, moduleName, token, 20000);
qDebug() << "LogosAPIConsumer: informModuleToken completed with result:" << result;
m_transport->releaseObject(plugin);
plugin->release();
return result;
}