0

I want to use RabbitMq in my c++ program. I desided to use AMQP-CPP for this.

When I used class MyConnectionHandler : public AMQP::ConnectionHandler from README file my messages weren't sent. Here is that class

#include <amqpcpp.h>

/** You'll need to extend the ConnectionHandler class and make your own, like this*/
class MyConnectionHandler : public AMQP::ConnectionHandler
{
/**
 *  Method that is called by the AMQP library every time it has data
 *  available that should be sent to RabbitMQ.
 *  @param  connection  pointer to the main connection object
 *  @param  data        memory buffer with the data that should be sent to RabbitMQ
 *  @param  size        size of the buffer
 */
virtual void onData(AMQP::Connection *connection, const char *data, size_t size)
{
    // @todo
    //  Add your own implementation, for example by doing a call to the
    //  send() system call. But be aware that the send() call may not
    //  send all data at once, so you also need to take care of buffering
    //  the bytes that could not immediately be sent, and try to send
    //  them again when the socket becomes writable again
}

/**
 *  Method that is called by the AMQP library when the login attempt
 *  succeeded. After this method has been called, the connection is ready
 *  to use.
 *  @param  connection      The connection that can now be used
 */
virtual void onReady(AMQP::Connection *connection)
{
    // @todo
    //  add your own implementation, for example by creating a channel
    //  instance, and start publishing or consuming
}

/**
 *  Method that is called by the AMQP library when a fatal error occurs
 *  on the connection, for example because data received from RabbitMQ
 *  could not be recognized.
 *  @param  connection      The connection on which the error occurred
 *  @param  message         A human readable error message
 */
virtual void onError(AMQP::Connection *connection, const char *message)
{
    // @todo
    //  add your own implementation, for example by reporting the error
    //  to the user of your program, log the error, and destruct the
    //  connection object because it is no longer in a usable state
}

/**
 *  Method that is called when the connection was closed. This is the
 *  counter part of a call to Connection::close() and it confirms that the
 *  AMQP connection was correctly closed.
 *
 *  @param  connection      The connection that was closed and that is now unusable
 */
virtual void onClosed(AMQP::Connection *connection) 
{
    // @todo
    //  add your own implementation, for example by closing down the
    //  underlying TCP connection too
}
};

In each method I wrote only std::cout with name of methods.

Then I found class MyHandler : public AMQP::LibEvHandler in examples that used libev Example with libev and my message was sent. But I didn't understand how to put my own text of message in that publisher into loop. I found an example look at void Client::publish(std::string message) method I think this is wrong becouse every time connection and channel are created and queue and exchange are declared. I think my code will send messages every 1-5 seconds. And this method is bad. I made my methods

class MessageWatcher {
public:
    ev_idle evIdle;
    std::string message;
    std::string exchanger;
    std::string routingKey;
    AMQP::TcpChannel * channel;

    MessageWatcher(const std::string &exchanger, const std::string &routingKey)
    : exchanger(exchanger), routingKey(routingKey) {}
};

static void publishEvent (EV_P_ ev_idle * watcher, int revents) {
    auto * self = (class MessageWatcher *)watcher;

    std::cout << self->message << '\n';
    self->channel->publish(self->exchanger, self->routingKey, self->message);
    ev_idle_stop (EV_A_ watcher);

    ev_break (EV_A_ EVBREAK_ALL);
}

void rabbitWorker(MessageWatcher & messageWatcher, struct ev_loop * loop) {
    static RabbitMqConnectionHandler handler(loop);

    static AMQP::TcpConnection connection(&handler, 
        AMQP::Address("amqp://guest:guest@localhost/my-vhost"));

    static AMQP::TcpChannel channel(&connection);
//    channel.publish("betweenIslands", "migrationToNewIsland", "my first message");
    messageWatcher.channel = &channel;
    ev_idle_init (&messageWatcher.evIdle, publishEvent);
    ev_idle_start (loop, &messageWatcher.evIdle);

    ev_run(loop, 0);
}

int main() {
    struct ev_loop * loop{EV_DEFAULT};

    MessageWatcher messageWatcher{"exchangeName", "routingKeyName"};
    messageWatcher.message = "start message";
    rabbitWorker(messageWatcher, loop);

    short counter1{10};
    while (--counter1) {
    sleep(3);
    std::cout << "3 seconds is over" << '\n';
    messageWatcher.message = "message after 3 seconds number is " + 
    std::to_string(counter1);
    ev_invoke(loop, &messageWatcher.evIdle, 0);
}

Queue and exchange is declared already. But my code writes self->message only and don't publishes it in queue. When I uncomment channel.publish("betweenIslands", "migrationToNewIsland", "my first message"); and comment 3 further strings than "my first message" is sent. But how to put my own message instead "my first message" in this case?

Deadpool
  • 33
  • 7

1 Answers1

1

Finnaly I found mistake in my code! In main function in first row instead struct ev_loop * loop{EV_DEFAULT}; I should have written struct ev_loop * loop{ev_loop_new()}; And in while loop instead ev_invoke(loop, &messageWatcher.getEvIdle(), 0); I should have written rabbitWorker(messageWatcher, loop); In this case connection is created one time only. Maybe it will save time for somebody ))

Deadpool
  • 33
  • 7