bimawa / AMQProtocol

AMQProtocol wrapper on libRabbitMQ-C
5 stars 0 forks source link

Queue bindToExchange Throwing Error #1

Open CMoebius opened 11 years ago

CMoebius commented 11 years ago

I am getting the following error when the Queue's bindToExchange is executed:

2013-02-28 09:24:06.782 RabbitMQTest[9819:c07] AMQPException: Failed to bind queue to exchange: No such file or directory

I have an example application that runs perfectly that uses the straight C API and appears to call the same methods with the same parameters as AMQP classes. As you can see by the code, I am using a durable queue & exchange that does not get autodeleted.

Here's my code fragment:

NSError *error;
AMQPConnection *connection = [[AMQPConnection alloc] init];

[connection connectToHost:_host.text onPort:[_port.text integerValue] error:&error];
if (error.code != 0)
{
    _output.text = [NSString stringWithFormat:@"%@\n%@", _output.text, error.localizedDescription];
    return;
}

[connection loginAsUser:@"guest" withPasswort:@"guest" onVHost:VIRTUAL_HOST error:&error];

AMQPChannel *channel = [connection openChannel];

if (channel)
{
    AMQPExchange *exchange = [[AMQPExchange alloc] initDirectExchangeWithName:EXCHANGE_NAME onChannel:channel isPassive:NO isDurable:YES getsAutoDeleted:NO error:&error];
    AMQPQueue *queue = [[AMQPQueue alloc] initWithName:QUEUE_NAME onChannel:channel isPassive:NO isExclusive:NO isDurable:YES getsAutoDeleted:NO error:&error];

    [queue bindToExchange:exchange withKey:BINDING_KEY error:&error];
CMoebius commented 11 years ago

I have tracked this issue down to this method in AMQPQueue.m:

- (id)initWithName:(NSString*)theName onChannel:(AMQPChannel*)theChannel isPassive:(BOOL)passive isExclusive:(BOOL)exclusive isDurable:(BOOL)durable getsAutoDeleted:(BOOL)autoDelete error:(NSError **)error
{
if(self = [super init])
{
    __block int isReadyData=0;
    __block amqp_queue_declare_ok_t *declaration;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        declaration = amqp_queue_declare((theChannel).connection.internalConnection, (theChannel).internalChannel, amqp_cstring_bytes([theName UTF8String]), passive, durable, exclusive, autoDelete, AMQP_EMPTY_TABLE);
        if([channel.connection checkLastOperation:@"Failed to declare queue"]||declaration==nil){
            NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
            [errorDetail setValue:@"Failed to declare queue" forKey:NSLocalizedDescriptionKey];
            *error = [NSError errorWithDomain:NSStringFromClass([self class]) code:-8 userInfo:errorDetail];

        }

    });

    queueName = amqp_bytes_malloc_dup(declaration->queue);
    channel = theChannel;
}

return self;
}

The queueName ivar is being set before the block executes when it should be set in the block where the queue is declared. When I moved this line

    queueName = amqp_bytes_malloc_dup(declaration->queue);

inside the block, it started working.

CMoebius commented 11 years ago

There is also a problem with the queue declare in a separate thread. If I am creating a queue, an exchange, then trying to bind them before the thread executes, there is an error generated.

bimawa commented 11 years ago

Yes, it is not compliete code. Use it carefully. I now think about multitreading. its needs for unblocking idea. in this month i solve this trouble, it think :)

bimawa commented 11 years ago

And more, i think about realisation this protocol on CFSocket... i don't know mb its bad idea?