fuCtor / QAMQP

AMQP implementation for Qt
Other
28 stars 3 forks source link

Simple Publish (No consume) #34

Closed bprinsloo closed 10 years ago

bprinsloo commented 10 years ago

I have been messing around for hours now. All I want is a simple send of a message (An XML) to rabbitmq. I have the receiver code written in Java, so that is irrelevant. I just want a simple send method.

This sample uses the timer with SLOTS. I modified it to only execute once for the send, but it seems the thread never closes since the app doesn't exit. If I add an event with my own signal to exit after the "publish", the message doesn't seem to be posted.

My Run has been changed as follow :
void run() { //Sends a single message m_myLongTimer = new QTimer(this); m_myLongTimer->setInterval(3000); m_myLongTimer->setSingleShot(true); connect(m_myLongTimer, SIGNAL(timeout()), SLOT(sendMessage())); m_myLongTimer->start(); }

and I added a slot on the constructor as follow : connect(this, SIGNAL(AppIsDone()),SLOT(QuitApp()));

And the code of QuitApp() is : void QuitApp() { qDebug() << "Still here!!!!!!!!!"; exit(-1); }

At the end of sendMessage I added : emit AppIsDone();

It work as expected, fire after the supposed publish, but unless the thread is left as is it just doesn't post. If I remove the exit(-1), it doesn't exit and the message is posted. If I put it back, it say it's done, but nothing is published.

Is there any signal I am missing out on here? Is there a reason why the thread need to stay active for the post to proceed?

fuCtor commented 10 years ago

Show full example. In this part I can't understand in which thread you try send message and don't see how you are working with this thread.

bprinsloo commented 10 years ago

Thank you for the extremely quick response! Really appreciate it :+1:

I basically used your Send.h as a template, and created "MySend.h" as below as a test. The part changed is under "Run". Basically this used to be a timer defined as :

    void run()
    {
        QTimer* timer = new QTimer(this);
        timer->setInterval(2468);
        connect(timer, SIGNAL(timeout()), SLOT(sendMessage()));
        timer->start();
    }

I changed to be a singleshot only, and added a method to exit.


#ifndef MYSEND_H
#define MYSEND_H

#include <QObject>
#include <QRunnable>
#include <QDebug>
#include <QList>
#include <QByteArray>
#include <QDateTime>
#include <QTimer>

#include "qamqp/amqp.h"
#include "qamqp/amqp_exchange.h"
#include "qamqp/amqp_queue.h"

namespace QAMQP
{

namespace dsmApps
{

class MySend : public QObject, public QRunnable
{
    Q_OBJECT

    typedef QObject super;

signals:
    void AppIsDone();
    void timeout();

public:
    explicit MySend(const QString& address, const QString& sendMsg, QObject *parent)
        : super(parent), sendMsg_(sendMsg)
    {
        connect(this, SIGNAL(AppIsDone()),SLOT(QuitApp()));  //<----------------------------------------------ADDED BY ME
        // Create AMQP client
        client = new QAMQP::Client(this);
        client->open(QUrl(address));

        // Retrieve the "Default" exchange
        // No need to declare (i.e. to create), nor to bind to a queue
        exchange_ =  client->createExchange();

        // Create the "ETEST" queue
        // This isn't mandatory but if it doesn't exist, the messages are lost
        client
            ->createQueue("ETEST", exchange_->channelNumber())
                ->declare();

       // client->close();
        client->disconnect();
    }

    void run()
    {
        //Sends a single message
        m_myLongTimer = new QTimer(this);
        m_myLongTimer->setInterval(3000);
        m_myLongTimer->setSingleShot(true); //<-------------------------------------------ADDED BY ME
        connect(m_myLongTimer, SIGNAL(timeout()), SLOT(sendMessage()));
        m_myLongTimer->start();
    }

protected slots:
    void QuitApp() {  //<----------------------------------------------ADDED BY ME
        qDebug() << "Still here!!!!!!!!!";
       exit(-1);
    }

    void sendMessage()
    {
        static quint64 counter = 0;
      /*  QAMQP::Exchange::MessageProperties properties;
        properties[QAMQP::Frame::Content::cpDeliveryMode] = 2; // Make message persistent
*/
        QString message(QString("[%1: %2] %3")
          .arg(++counter)
          .arg(QDateTime::currentDateTime().toString(Qt::ISODate))
          .arg(sendMsg_));
        qDebug() << "Send::sendMessage NOW " << message;

        exchange_->publish(message, "ETEST");
        emit AppIsDone();    //<----------------------------------------------ADDED BY ME
    }

private:
    QString sendMsg_;
    QTimer*   m_myLongTimer;

    QAMQP::Exchange* exchange_;
    QAMQP::Client* client;
};

}

}

#endif // MYSEND_H
fuCtor commented 10 years ago

exchange_->publish(message, "ETEST"); emit AppIsDone(); //<----------------------------------------------ADDED MY ME

Network methods is async, but SIGNAL\SLOT in one thream is sync. When your emit signal, app don't have time for message sending.

bprinsloo commented 10 years ago

Is there a way around this? Thread sleeps will obviously not work in this case.

fuCtor commented 10 years ago

Connect SIGNAL AppIsDone with Timer SIGNAL timeout and make singleshot timer.

bprinsloo commented 10 years ago

Thank you very much!! This work like a charm. This i added at the end after doing the publish :+1:

exchange_->publish(message, "ETEST");
        m_myEndTimer = new QTimer(this);
        m_myEndTimer->setInterval(3000);
        m_myEndTimer->setSingleShot(true);
        connect(m_myEndTimer, SIGNAL(timeout()), SLOT(QuitApp()));
        m_myEndTimer->start();

This might help someone else. The 3s should of course be adjusted just in case for latency etc, so a ping and a simple calc must still be performed rather than hardcode it, but overall it works. I consider this closed, thank you for help.