bakkerthehacker / bramqp Goto Github PK
View Code? Open in Web Editor NEWA radical, raw, robust, remarkable, rapid AMQP library for node.js
License: MIT License
A radical, raw, robust, remarkable, rapid AMQP library for node.js
License: MIT License
The message is not published when I add headers. Callback is triggered (which prints "Published message") but the message is not routed to the queue. Am I doing something wrong?
var message = [
'UserUpdate',
{
'id': pbx_user_id,
'pbx_profile_id': new_pbx_schedule_id,
'pbx_profile_type': 'schedule'
}
];
msg = JSON.stringify( message );
var table = {
'headers': {
'company': {
type: 'Unsigned 64-bit',
data: 4
}
}
};
app.amqpHandle.content( 1, 'basic', table, msg, function() {
console.log( 'Published message' );
} );
Considering that the 'handle' is an instance of Socket, which is a instance of events.EventEmitter, shouldn't the removeListener work within the library?
I am trying to remove some listeners after a time (handle.on(event)). Is it possible to do in any other way?
Hello, I've been trying out this lib and liking it a lot so far - keeping to the low level stuff seems to be avoiding many of the problems node-amqp has with it's high/low mix.
There does seem to be a bit of an issue however, in both some internal code and documentation.
The incoming method events are fired on the handle
object, and pass the channel as their first argument - however none of the examples or code actually check that this channel param actually matches the expected one!
While the examples could be updated to always have if (channel != 1) return;
, I think this is a common enough use-case that it would make sense to provide some sugar for this.
Perhaps one of these?
handle.channelOn(1, 'close', fn);
handle.channel(1).on('close');
// In both cases the idea would just be to desugar into:
handle.on('close', function(ch) {
if (ch != expected) return;
handler.apply(this, arguments);
});
need to add
method
eventThe frame parser and serializer were designed to work only on valid data. The user data should be validated. Some of the validation requirements for method arguments may need to be read from the spec.
looking into error handling, I was looking at possibly using the error handle.emit event to also emit the AMQP errors instead of having to:
// handle any AMQP errors that cause the connection to close
handle.on('connection.close', function(reply_code, reply_text, class_id, method_id){
console.log("error code connection");
console.log(reply_code);
});
// handle any AMQP errors that cause the channel to close
handle.on('channel.close', function(reply_code, reply_text, class_id, method_id){
console.log("error code channel");
console.log(reply_code);
});
I was writing some test code for this and I got an error code of 0 when I tried to open a queue on channel 2. Now channel 2 isn't open, but I thought I would get
channel-error 504. Furthermore I can't find documentation of this error code 0
here is code to reproduce
var bramqp = require('bramqp');
var net = require('net');
var async = require('async');
bramqp.selectSpecification('rabbitmq/full/amqp0-9-1.stripped.extended', function(error) {
if (error) {
console.log("spec error");
throw error;
}
var socket = net.connect({
port : 5672
}, function() {
bramqp.initializeSocket(socket, function(error, handle) {
if (error){
console.log("socket init error");
throw error;
}
handle.on("error", function(error){
console.log("handle Error");
throw error;
});
// handle any AMQP errors that cause the connection to close
handle.on('connection.close', function(reply_code, reply_text, class_id, method_id){
console.log("error code connection");
console.log(reply_code);
console.log(reply_text);
});
// handle any AMQP errors that cause the channel to close
handle.on('channel.close', function(reply_code, reply_text, class_id, method_id){
console.log("error code channel");
console.log(reply_code);
});
async.series([ function(seriesCallback) {
handle.openAMQPCommunication('guest', 'guest', true, seriesCallback);
}, function(seriesCallback){
handle.queue.declare(2, null, false, true, true, true, false, {});
handle.once('queue.declare-ok', function(channel, method, data) {
console.log('queue declared');
seriesCallback();
});
}]);
});
});
});
and the output
error code connection
0
{ chassis:
[ { name: 'client', implement: 'MUST' },
{ name: 'server', implement: 'MUST' } ],
response: [ { name: 'close-ok' } ],
field:
[ { name: 'reply-code', domain: 'reply-code' },
{ name: 'reply-text', domain: 'reply-text' },
{ name: 'class-id', domain: 'class-id' },
{ name: 'method-id', domain: 'method-id' } ],
name: 'close',
synchronous: '1',
index: '50' }
vows 0.8.1 exposed an issue with some tests that were not cleaning up their connections and the testing framework would simply hang
connectionHandle.js is far too large and should be split into multiple files to be more easy to manage
I am having a hard time figuring out how to implement multi-channels and have specific queues listening on specific channels. All the examples in the tutorials seem to be single channel.
The idea is to have a task system where there are priorities. Workers need to work on tasks with high priorities and go to lower priority tasks as the other queues empty out.
For the discussion let's say we have 3 priorities: 1 - really important, 2 - medium importance, 3 - low importance.
Each worker can do up to 5 things at once.
So, I'm thinking about doing this via 3 queues and then have 3 channels each consume from 1 queue setting the channel qos to 5. This should throttle things across cluster workers, although not optimally since I may end up with 15 messages at the worker at any time.
Any examples on how to do that? (or maybe some other way of accomplishing the same thing)
Thanks,
Alberto
May be add a "vhost" parameter to the openAMQPCommunication function and pass it to the AMQP connection.open function.
hi :)
If the rmsOpts.username
contains an unknown to RabbitMQ name nothing happens. I would expect an error to be thrown.
handle.openAMQPCommunication(
rmsOpts.username,
rmsOpts.password,
rmsOpts.heartbeat,
rmsOpts.vhost,
(error, results) => {
if (error) {
fail(error);
} else {
ok(handle);
}
},
);
the question: is there a proper way of handling bramqp errors?
PS: the flow terminates abruptly in connectionHandle.js on line 208.
After some debugging I found that the format for arguments (eg. for handle.queue.declare) is
{'x-message-ttl': { type: 'Signed 32-bit', data: 30000 } }
I couldn't find this in the documentation, and it may save others some time if this were included.
Hi.
This is just an architecture question. Suppose I do publishing and consuming messages from the same node.js module. As soon as I start basic.consume the whole application seems to wait for it to complete.
Should this be, say, mono, I would have put the basic.consume in a separate thread. But what approach should I take in node.js?
Thank you.
I believe line 57 of
bramqp / tutorial / 3 Publish Subscribe / consumer.js
should contain a consumerTag as the 3rd parameter.
Following the example no.2 (work queues) I understand is declaring a durable queue:
handle.queue.declare(1, 'task_queue', false, true, false, false, false, {});
handle.once('queue.declare-ok', function(channel, method, data) {
console.log('queue declared');
seriesCallback();
});
And publishing persistent messages with:
handle.basic.publish(1, '', 'task_queue', false, false, function() {
handle.content(1, 'basic', {
delivery_mode : 2
}, message, seriesCallback);
});
But looking in the web-ide of rabbitmq the persistent messages counter inside the queue stays in 0. When I manually publish the message thorught the webide works weell and the counter changes..
Im missing something? How can I publish true a pesistent message with your library?? Thanks so much, I really like the library
basic.publish
must be followed by content without any other messages inbetween. The current implementation fails to provide a software lock bewteen these two. Other messages can fall between due to multiplexing on the event loop.
The original implementation should remain to retain the ability to multiplex between channels. The new implementation should take the content with the message and perform one write on the entire frame set.
Hi.
After opening a channel I cannot close it. Please, have a look at the code, and the console output below.
Thank you!
THE CODE
require("babel-polyfill");
const series = require('async').series;
const nextTick = require('async').nextTick;
class Infra {
constructor(connection, settings) {
this.connection = connection;
this.settings = settings;
this.handle = this.connection.handle;
this.channel_num = 2;
};
* channel_number() {
yield this.channel_num++;
};
open_channel() {
return new Promise((resolve, reject) => {
const cn = this.channel_number().next().value;
this.handle.channel.open(cn);
this.handle.once(`${cn}:channel.close`, () => {
console.log(`channel.close: ${cn}`);
this.handle.channel['close-ok'](cn, () => {
console.log(`[${cn}]close-ok:`);
});
});
this.handle.once(`${cn}:channel.flow`, (channel, method, data) => {
console.log(`${cn}:channel.flow:`, channel, method, data);
this.handle.channel['flow-ok'](cn, data.active, () => {
console.log(`[${cn}]flow-ok:`, data);
});
});
this.handle.once(`${cn}:channel.open-ok`, () => {
console.log(`${cn}:channel.open-ok`);
resolve(cn);
});
});
};
* object_names(className) {
for(let object_name of this.settings[className]) {
yield object_name;
};
};
declare_exchange(channel_number, object_config) {
return new Promise((resolve, reject) => {
const nowait = false;
this.handle.exchange.declare(
channel_number,
object_config.name,
object_config.exchange_type,
object_config.passive,
object_config.durable,
object_config.auto_delete,
object_config.internal,
nowait,
object_config.arguments,
(error) => {
if(error) {
console.error(error);
reject(error);
};
}
);
this.handle.on(
`${channel_number}:exchange.declare-ok`, (channel, method, data) => {
console.log(`${channel_number}:exchange.declare-ok: ${object_config.name}`);
resolve();
}
);
});
};
create_exchanges() {
return new Promise((resolve, reject) => {
const obj_names_gen = this.object_names('exchanges');
for(let next_name of obj_names_gen) {
const object_config = this.settings[next_name];
this.open_channel()
.then((channel_number) => {
this.declare_exchange(channel_number, object_config)
.then(() => {
console.log(`BEFORE: this.handle.channel.close(${channel_number})`);
this.handle.channel.close(channel_number, 200, 'object declared OK');
})
.catch((error) => {
reject(error);
});
})
.catch((error) => {
reject(error);
});
};
});
};
create_queues() {
return new Promise((resolve, reject) => {
resolve();
});
};
create_bindings() {
return new Promise((resolve, reject) => {
resolve();
});
};
create() {
return new Promise((resolve, reject) => {
series([
(callback) => {
this.create_exchanges()
.then(() => {
nextTick(callback);
})
.catch((error) => {
callback(error);
});
},
(callback) => {
this.create_queues()
.then(() => {
nextTick(callback);
})
.catch((error) => {
callback(error);
});
},
(callback) => {
this.create_bindings()
.then(() => {
nextTick(callback);
})
.catch((error) => {
callback(error);
});
},
], (error, result) => {
if(error) {
console.error(error);
reject(error);
}
resolve();
});
});
};
};
module.exports = Infra;
THE CONSOLE OUTPUT
2:channel.open-ok
3:channel.open-ok
4:channel.open-ok
5:channel.open-ok
6:channel.open-ok
3:exchange.declare-ok: x-dlx
7:channel.open-ok
2:exchange.declare-ok: x-ae
4:exchange.declare-ok: x-fci
5:exchange.declare-ok: x-rci
BEFORE: this.handle.channel.close(3)
BEFORE: this.handle.channel.close(2)
BEFORE: this.handle.channel.close(4)
BEFORE: this.handle.channel.close(5)
6:exchange.declare-ok: x-idx
7:exchange.declare-ok: x-cmd
BEFORE: this.handle.channel.close(6)
BEFORE: this.handle.channel.close(7)
I'm not 100% on whether this is a problem, or how best to fix it.
The two options I can think of are making the callback in parseFrameEnd use nextTick, or calling resetFrameState before that callback is fired. The second option here probably leaves you needing to handle continuing to read the buffer in the case where there are unread bytes - although you could just trust that more bytes will be along later and will consume parsing.
Anyway here's the code to trigger the error:
'use strict';
var bramqp = require('./');
var net = require('net');
var async = require('async');
process.on('uncaughtException', function(ex) {
if (ex.message == 'handleable application error') {
console.warn("Got an app error, but it's ok!");
return;
}
console.warn("Error: %s", ex.stack);
});
var socket = net.connect({
port : 5672
});
bramqp.initialize(socket, 'rabbitmq/full/amqp0-9-1.stripped.extended', function(error, handle) {
handle.openAMQPCommunication('guest', 'guest', true, onConnected);
function onConnected(err) {
if (err) throw (err);
handle.queue.declare(1, 'hello');
handle.once('queue.declare-ok', function(channel, method, data) {
handle.queue.declare(1, 'world');
throw new Error('handleable application error');
});
}
});
Hi,
I am using the library on node to create some jobs to external machines. I am using version 0.3.2.
The problem I am having is, whenever, at the same request, I do multiple publishes using the same handle, they fail. This is how I am doing this:
var bramqp = require('bramqp')
, net = require('net')
, async = require('async')
module.exports = new function () {
var handle
, socket = net.connect(socketConfig)
function openConnection() {
bramqp.initialize(socket, 'rabbitmq/full/amqp0-9-1.stripped.extended', function(err, _handle) {
handle = _handle
async.series([function(seriesCallback) {
handle.openAMQPCommunication('user', 'pass', true, host, seriesCallback);
}, function(seriesCallback) {
handle.on('queue.declare-ok', queueReady);
handle.queue.declare(1, 'q1', false, true, false, false, false, {})
handle.queue.declare(1, 'q2', false, true, false, false, false, {})
}],
function (err) {})
})
}
openConnection()
this.send = function (message, queue) {
handle.basic.publish(1, '', queue, true, true, function() {
handle.content(1, 'basic', {
'content-type' : 'application/json',
'delivery-mode' : 2
}, JSON.stringify(message), function (err) {
});
});
}
}
I have tried to implement the basic return method to see if there is anything wrong with rabbit, but I wasn't able to see anything, and I don't think I did it correctly.
As I tried to explain, within the request I can call the send only one time, and it does publish correctly. Consecutive calls fails silently. Other calls to my API do work, and the first send works too.
Do you have any idea on what I am doing wrong here?
I'm unsure whether this is a problem in practice as the content always follows delivery, which is scoped. Is this guaranteed on the socket?
It does lead to a slightly inconsistent API, where I can subscribe to "1:basic.deliver"
, but then have to follow it up with a plain "content"
handler.
Actually all methods that take arbitrary properties require them to be of "table" type. Example is content properties.headers
This means you can't pass in a plain js object, but actually have to type the values, e.g. turn it to a key value map where the value is {type: "$oneOfValueTypes", data: "$theValue"}
I guess putting it in one of the examples would help people understand (I thought this is not obvious)
Cheers,
Arne
Currently there are no tests. I did test most of the code while writing it, but there still may be issues, especially in the FrameParser and FrameSerializer.
I was using the 3rd tutorial (3 Publish Subscribe) as a starting point to do a basic connection and consume test on a remote broker. I copied the code from consumer.js into my node app and adjusted the socket values, username, password, and vhost to connect to my remote host. The connection worked, but when I would publish a message, nothing was being received in node via the console from line 40 on in consumer.js.
I noticed on a stackoverflow post similar example code but I noticed on the equivalent to line 36 in consumer.js:
handle.basic.consume(1, queueName, false, true, true, false, {});
...had an extra argument after queueName, a 'null' value. Once I figured out these methods were being declared by the specification XML document, I poked into the specification declared on line 12, 'rabbitmq/full/amqp0-9-1.stripped.extended'.
It declares 8 fields, not 7 like in line 36 listed above. As soon as I added an 8th argument, a 'null' right after the queueName field, I was able to start consuming published messages ok.
Basically, this example doesn't work as-is in my testing, I think it's the wrong number of arguments on line 36 for the declared specification file. This was really confusing to track down as my first experience trying to use the library.
What worked for me was:
handle.basic.consume(1, queueName, null, false, true, true, false, {});
Thanks!
Calling queue.declare()
with null
as the value of the queue
parameter causes bramqp
to fail the assertion tests. The specification says "The queue name MAY be empty". And (apparently) this used to work in bramqp
as the the RPC example (rpc_client.js) has this line:
self.handle.queue.declare(1, null, false, false, true, false, false, {});
Which throws the following error:
TypeError: Cannot read property 'length' of null
at Object.length (C:\XXX\node_modules\bramqp\lib\assertion.js:6:16)
at module.exports.checkAssertion (C:\XXX\node_modules\bramqp\lib\assertion.js:31:39)
at FrameSerializer.serializeFields (C:\XXX\node_modules\bramqp\lib\frameSerializer.js:275:4)
at FrameSerializer.serializeFrameMethod (C:\XXX\node_modules\bramqp\lib\frameSerializer.js:305:7)
at ConnectionHandle.methodBuffer (C:\XXX\node_modules\bramqp\lib\connectionHandle.js:333:23)
at ConnectionHandle.method (C:\XXX\node_modules\bramqp\lib\connectionHandle.js:299:25)
at Object.declare (C:\XXX\node_modules\bramqp\lib\connectionHandle.js:91:12)
Replacing null
with an empty string passes the assertion.
self.handle.queue.declare(1, '', false, false, true, false, false, {});
I think the assertion should accept null
or undefined
as a valid empty value. Or, at least, the examples should be updated.
.../node_modules/bramqp/lib/frameParser.js:436
throw parseError;
^
TypeError: Object # has no method 'serializeLong'
at Object.FrameSerializer.serializeLongString as Long string
at FrameSerializer.serializeValue (/Users/vvolle/workspaces/me/nodejs/code/sample/node_modules/bramqp/lib/frameSerializer.js:279:34)
at FrameSerializer.serializeTable (/Users/vvolle/workspaces/me/nodejs/code/sample/node_modules/bramqp/lib/frameSerializer.js:269:9)
at FrameSerializer.serializeLongString (/Users/vvolle/workspaces/me/nodejs/code/sample/node_modules/bramqp/lib/frameSerializer.js:228:8)
at FrameSerializer.serializeFields (/Users/vvolle/workspaces/me/nodejs/code/sample/node_modules/bramqp/lib/frameSerializer.js:293:34)
at FrameSerializer.serializeFrameMethod (/Users/vvolle/workspaces/me/nodejs/code/sample/node_modules/bramqp/lib/frameSerializer.js:325:7)
at ConnectionHandle.method (/Users/vvolle/workspaces/me/nodejs/code/sample/node_modules/bramqp/lib/connectionHandle.js:241:23)
at Object.start-ok (/Users/vvolle/workspaces/me/nodejs/code/sample/node_modules/bramqp/lib/connectionHandle.js:95:11)
at ConnectionHandle. (/Users/vvolle/workspaces/me/nodejs/code/sample/node_modules/bramqp/lib/connectionHandle.js:142:33)
at ConnectionHandle.g (events.js:175:14)
I have 5kB and 10kB messages. 30,000 x 10kB messages fail to publish, while only 60,000 x 5kB messages fail to publish. I can consistently reproduce this problem... I suspect this is some sort of a socket limitation, I am unsure.. Could this be checked please.
Hi,
I'm running into an issue when publishing with the library.
I consume a queue [on channel 1], process messages, and publish results back to the same RMQ cluster [on channel 2]. I have thousands of messages per second, and publish isn't working (actually the content callback is called, but no message is really published).
_handle.basic.publish(2, exchange, routingKey, false, false, function (publishError) {
if (publishError) {
console.log(publishError);
return f(publishError);
}
console.log("content for message " + message.generic.id);
_handle.content(2, 'basic', {
'content-type': 'application/json'
}, JSON.stringify(message), function () {
console.log('message published: ' + message.generic.id);
});
});
I wanted to know if it could be relative to the following statement :
"The basic.publish has an issue where it must be followed by content without any other messages on that channel inbetween. I will be updating the API to fix this."
Because before "content for message" is printed, I have several calls to _handle.basic.publish on channel 2
Hello,
I tried various ways, but I cannot figure out how to get an exception/error when a bind operation cannot complete (e.g., when the queue or exchange name does not correspond to an existing queue/exchange on the rabbitmq server).
If I add a callback after the parameters for the queue.bind, I am called no matter if the bind performs ok or not, and I get no error.
Is there a way to do this ?
Thanks
pg
...this would be very handy for modern NodeJS
Running the example code for Tutorial 1 shows the following output
queue declared
channel closed
connection closed
all done
Socket error:
{ [Error: read ECONNRESET] code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }
Hi. With Node v10.1.0:
$ NODE_OPTIONS='--throw-deprecation' npm test
> [email protected] test /Users/dexter/src/js/bramqp
> vows --spec
♢ concurrent connections
events.js:167
throw er; // Unhandled 'error' event
^
DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
at showFlaggedDeprecation (buffer.js:159:11)
at new Buffer (buffer.js:174:3)
at FrameParser.resetFrameState (/Users/dexter/src/js/bramqp/lib/frameParser.js:285:26)
at new FrameParser (/Users/dexter/src/js/bramqp/lib/frameParser.js:25:7)
at /Users/dexter/src/js/bramqp/lib/connectionHandle.js:17:22
at /Users/dexter/src/js/bramqp/lib/specification.js:57:5
at Parser.<anonymous> (/Users/dexter/src/js/bramqp/node_modules/xml2js/lib/parser.js:303:18)
at Parser.emit (events.js:182:13)
at Parser.options.Emitter.emit (/Users/dexter/src/js/bramqp/node_modules/vows/lib/vows.js:241:24)
at SAXParser.onclosetag (/Users/dexter/src/js/bramqp/node_modules/xml2js/lib/parser.js:261:26)
Emitted 'error' event at:
at Parser.exports.Parser.Parser.parseString (/Users/dexter/src/js/bramqp/node_modules/xml2js/lib/parser.js:326:16)
at Parser.parseString (/Users/dexter/src/js/bramqp/node_modules/xml2js/lib/parser.js:5:59)
at /Users/dexter/src/js/bramqp/lib/specification.js:43:17
at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:422:3)
npm ERR! Test failed. See above for more details.
Hello,
I need help :(
this is my code :
'use strict';
var bramqp = require('bramqp');
var tls = require('tls');
var fs = require('fs');
var socket = tls.connect({
host : 'Hostname',
port : port,
key : fs.readFileSync('cert/cert.pem'),
ca : [ fs.readFileSync('cert/cacert.pem') ],
passphrase :'passephrase',
secureProtocol :'TLSv1_method'
});
Result :
vents.js:72
throw er; // Unhandled 'error' event
^
Error: 3074393856:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:../deps/openssl/openssl/ssl/s3_pkt.c:1293:SSL alert number 40
at SlabBuffer.use (tls.js:235:18)
at CleartextStream.read [as _read] (tls.js:455:29)
at CleartextStream.Readable.read (_stream_readable.js:341:10)
at EncryptedStream.write [as _write] (tls.js:369:25)
at doWrite (_stream_writable.js:226:10)
at writeOrBuffer (_stream_writable.js:216:5)
at EncryptedStream.Writable.write (_stream_writable.js:183:11)
at write (_stream_readable.js:602:24)
at flow (_stream_readable.js:611:7)
at Socket.pipeOnReadable (_stream_readable.js:643:5)
Note : I tried to connect in Php with the same configurations(certif, port, hostname ...) and I managed to connect
Thank you for your help
Hi!
I would like to ask you to give an example of the channel.open function.
I have the following workflow of re-creating the RMQ infrastructure:
In Python I would establish a separate channel to create each single binding. Now I am curious how to properly create a new channel on the handler.
I've error (Invalid Date
) with timestamp field from RabbitMQ. It looks like here should be a division instead multiplication (at least for me it helps).
When a certain VHOST does not exist, the openAMQPCommunication should call the callback with the error as response. Right now it never actually calls the callback.
If the VHOST is set up correctly, the callback is executed.
I added the following to my code:
this.socket.on('data', (data) => {
console.log('\n' + data.toString());
});
And I notice the following output:
NOT_ALLOWED - access to vhost '/random' refused for user 'guest'
Hi.
I have run into trouble sharing a handle between two javascript objects. Is it at all possible to share it?
What I have:
Note: I have copy-pasted most of the code from bramqp documentation, except for disconnect function call.
What is the problem: when only a single object uses the handle it all runs OK. But, as soon as there are two objects sharing the same handle the ECONNRESET happens.
I guess, I just do not understand something very basic about the bramqp. Please, help me dig it.
Kudos for an interesting, no-frills approach to an AMQP library.
I think it would be helpful to me and others if you published examples of using your library to implement RabbitMQ's classic tutorials. This seems to be done by many AMQP libs and provides a helpful way to see what the code looks like in real scenarios, and to even try it out!
below code is from rabbit mq tutorial 6 converted to bramqp
var bramqp = require('bramqp');
var net = require('net');
var async = require('async');
function Rpc_client(callback){
var self = this;
bramqp.selectSpecification('rabbitmq/full/amqp0-9-1.stripped.extended', function(error) {
if (error) {
console.log(error);
}
var socket = net.connect({
port : 5672
}, function() {
self.socket = socket;
bramqp.initializeSocket(socket, function(error, handle) {
self.handle = handle;
async.series([ function(seriesCallback) {
self.handle.openAMQPCommunication('guest', 'guest', true, seriesCallback);
}, function(seriesCallback){
self.handle.queue.declare(1, null, false, true, true, true, false, {});
self.handle.once('queue.declare-ok', function(channel, method, data) {
console.log('queue declared');
self.callbackQueueName = data.queue;
seriesCallback();
});
}, function(seriesCallback){
handle.basic.consume(1, self.callbackQueueName, null, false, true, false, false, {});
handle.once('basic.consume-ok', function(channel, method, data) {
console.log('consuming from queue');
console.log(data);
seriesCallback();
});
}, function(seriesCallback){
handle.on('basic.deliver', function(channel, method, data) {
console.log('incoming message');
console.log(data);
});
console.log("a");
seriesCallback();
}, function(seriesCallback){
handle.once('content', function(channel, className, properties, content) {
console.log('got a message:');
console.log(content.toString());
console.log('with properties:');
console.log(properties);
if (self.correlation_id == properties.correlation_id){
self.response = content;
}
});
console.log("b");
seriesCallback();
}, function(error){
if (error){
console.log(error);
}
callback();
}]);
});
});
});
}
Rpc_client.prototype.call = function(n, callback){
var self = this;
self.response = null;
require('crypto').randomBytes(1, function(ex, buf) {
self.correlation_id = buf.toString('hex');
self.handle.basic.publish(1, '', 'rpc_queue', false, false, function() {
var properties = {
'reply-to' : "a",
'correlation-id' :"a"
};
self.handle.content(1, 'basic', properties, n, function(contentError){
if (contentError){
console.log(contentError);
}
while (self.response == null){
}
callback(self.response);
});
});
});
};
fibonacci_rpc = new Rpc_client(function(){
console.log(" [x] Requesting fib(30)");
fibonacci_rpc.call("30", function(response){
console.log(response);
});
});
There is a problem with rabbitmq:
Then server start block new messages, client emits TypeError.
To reproduce this:
shell: rabbitmqctl set_vm_memory_high_watermark 0
node.js code:
var bramqp = require('bramqp');
var net = require('net');
var socket = net.connect({
port : 5672
});
bramqp.initialize(socket, 'rabbitmq/full/amqp0-9-1.stripped.extended', function(error, handle) {
handle.openAMQPCommunication('guest', 'guest', true, function(seriesCallback) {
handle.basic.publish(1, '', 'hello', false, false, function() {
handle.content(1, 'basic', {}, 'Hello World!', function(){});
});
});
});
stack trace:
eventsevents.js:154
throw er; // Unhandled 'error' event
^
TypeError: Cannot read property 'field' of undefined
at FrameParser.parseFrameMethod (/home/numminorihsf/Projects/iojs/rabbit/node_modules/bramqp/lib/frameParser.js:268:49)
at FrameParser.parseFrameEnd (/home/numminorihsf/Projects/iojs/rabbit/node_modules/bramqp/lib/frameParser.js:413:63)
at FrameParser.parseFramePayload (/home/numminorihsf/Projects/iojs/rabbit/node_modules/bramqp/lib/frameParser.js:390:16)
at FrameParser.parseFrameStart (/home/numminorihsf/Projects/iojs/rabbit/node_modules/bramqp/lib/frameParser.js:372:16)
at FrameParser.parse (/home/numminorihsf/Projects/iojs/rabbit/node_modules/bramqp/lib/frameParser.js:431:57)
at Socket.<anonymous> (/home/numminorihsf/Projects/iojs/rabbit/node_modules/bramqp/lib/connectionHandle.js:45:22)
at emitOne (events.js:90:13)
at Socket.emit (events.js:182:7)
at readableAddChunk (_stream_readable.js:147:16)
at Socket.Readable.push (_stream_readable.js:111:10).js:154
The reason is that in spec there are no methods ("blocked", "undlocked") with ids (60, 61). So there is an error with it.
Please, update spec for rabbitmq.
https://www.rabbitmq.com/resources/specs/amqp0-9-1.extended.xml
RabbitMQ server supports numerous extensions to AMQP. In order for some of the extensions to function the client must specify one or more capabilities while establishing the connection.
The capabilities
field is supplied inside the client-properties
parameter to the connection.start-ok
method.
Recommend that a capabilities parameter be added to openAMQPCommunication()
with a default value consistent with that of the RabbitMQ Java Client (and as shown in the capabilities link above).
The added positive side effect is that the standard AMQP client connection info can be supplied inside the client-properties
parameter as well, as described in the spec:
Client properties.
The properties SHOULD contain at least these fields: "product", giving the name of the
client product, "version", giving the name of the client version, "platform", giving the
name of the operating system, "copyright", if appropriate, and "information", giving
other general information.
This allows bramqp to be identified by the admin functions of the server, for example:
Most easily reproduced when starting multiple concurrent connections to a local rabbitmq server: Only a subset (usually one) connection will succeed, all others get "stuck" waiting for the 'connection.tune' event, which, has already passed before the listener is established. (Local instance of rabbitmq is specified because otherwise network latency may contributing to hiding the issue.)
Discovered after upgrading bramqp from 0.1.17 to current master branch. The calling application starts a pool of concurrent workers each binding to a single queue for load sharing.
Tested on OS X 10.9.5 with node v0.10.24 and Debian Wheezy with node 0.10.33.
Hi folks - I'm getting an error when connecting to a vanilla ActiveMQ docker container. It looks like an issue in bramqp
Your Hello World example, which works fine on RabbitMQ, but fails on ActiveMQ:
docker run --name data-activemq -p 1883:1883 -p 5672:5672 -p 8161:8161 -p 61613:61613 -p 61614:61614 -p 61616:61616 -e 'ACTIVEMQ_MIN_MEMORY=512' -e 'ACTIVEMQ_MAX_MEMORY=2048' -v $DATA_PATH/activemq:/data/activemq -h data-activemq -d webcenter/activemq:5.12.0
With connection modified to
var socket = net.connect({
host : "192.168.69.100",
port : 9672
});
I get this error
$ node ActiveMQ-bramqp-send.js
events.js:85
throw er; // Unhandled 'error' event
^
RangeError: Attempt to allocate Buffer larger than maximum size: 0x3fffffff bytes
at new Buffer (buffer.js:71:11)
at FrameParser.parseFrameStart (C:\git\queue-demos\node_modules\bramqp\lib\frameParser.js:367:29)
at FrameParser.parse (C:\git\queue-demos\node_modules\bramqp\lib\frameParser.js:433:57)
at Socket.<anonymous> (C:\git\queue-demos\node_modules\bramqp\lib\connectionHandle.js:54:22)
at Socket.g (events.js:199:16)
at Socket.emit (events.js:107:17)
at readableAddChunk (_stream_readable.js:163:16)
at Socket.Readable.push (_stream_readable.js:126:10)
at TCP.onread (net.js:538:20)
As above
Please help!
Hello! I'm new to this library and just want to ask if it is possible to reuse the initialize anywhere in the nodejs code?
I understand that when setting up bramqp
the minimum is this
var bramqp = require('bramqp');
var net = require('net');
var socket = net.connect({
port: 5672
})
bramqp.initialize(socket, 'rabbitmq/full/amqp0-9-1.stripped.extended', function(initError, handle) {
if (initError) {
console.log(initError);
}
});
My goal is to reuse the instance of bramqp
and just use handle
to allow me execute handle.basic.consume
anywhere.
Thanks for the help!
The assertions from the specification in this commit dbf94bd introduced breaking changes. In our case we were using whitespaces in the queue names as our Rabbitmq server doesn't validate it and this assertion is failing:
https://github.com/bakkerthehacker/bramqp/blob/master/specification/rabbitmq/full/amqp0-9-1.stripped.extended.xml#L87
I understand that strictly following the specification is the right way but any workaround without change the queue names would be very helpful.
Hi.
If the arguments is not empty (see JSON config below), the exchange.declare would return the "Cannot read property 'call' of undefined". If the arguments contains nothing then exchange.declare succeeds.
Please, advise.
{
"name": "x-ae",
"description": "Alternative Exchange",
"type": "direct",
"passive": false,
"durable": true,
"auto_delete": false,
"internal": false,
"no_wait": false,
"arguments": {
"x-dead-letter-exchange": "x-dl"
}
}
This is the trace:
at FrameSerializer.serializeValue (backend/node_modules/bramqp/lib/frameSerializer.js:284:35)
at FrameSerializer.serializeTable (backend/node_modules/bramqp/lib/frameSerializer.js:273:9)
at FrameSerializer.serializeFields (backend/node_modules/bramqp/lib/frameSerializer.js:304:34)
at FrameSerializer.serializeFrameMethod (backend/node_modules/bramqp/lib/frameSerializer.js:336:7)
at ConnectionHandle.methodBuffer (backend/node_modules/bramqp/lib/connectionHandle.js:378:23)
at ConnectionHandle.method (backend/node_modules/bramqp/lib/connectionHandle.js:347:25)
at Object.declare (backend/node_modules/bramqp/lib/connectionHandle.js:121:12)
at RMQInfra._mapper (rmqinfra.js:65:40)
at Array.map (native)
at RMQInfra._recreate_exchanges (rmqinfra.js:92:41)
at RMQInfra.recreate (rmqinfra.js:111:14)
at Object.on_initialized (rmqinfra_spec.js:32:27)
at RMQConnector.<anonymous> (rmqconnector.js:32:41)
at backend/node_modules/bramqp/node_modules/async/lib/async.js:697:13
at backend/node_modules/bramqp/node_modules/async/lib/async.js:52:16
at backend/node_modules/bramqp/node_modules/async/lib/async.js:272:32
at backend/node_modules/bramqp/node_modules/async/lib/async.js:44:16
at backend/node_modules/bramqp/node_modules/async/lib/async.js:694:17
at backend/node_modules/bramqp/node_modules/async/lib/async.js:173:37
at ConnectionHandle.<anonymous> (backend/node_modules/bramqp/lib/connectionHandle.js:315:6)
at FrameParser.<anonymous> (backend/node_modules/bramqp/lib/connectionHandle.js:141:8)
at FrameParser.parseFrameMethod (backend/node_modules/bramqp/lib/frameParser.js:273:7)
at FrameParser.parseFrameEnd (backend/node_modules/bramqp/lib/frameParser.js:415:63)
at FrameParser.parseFramePayload (backend/node_modules/bramqp/lib/frameParser.js:392:16)
at FrameParser.parseFrameStart (backend/node_modules/bramqp/lib/frameParser.js:374:16)
at FrameParser.parse (backend/node_modules/bramqp/lib/frameParser.js:433:57)
at Socket.<anonymous> (backend/node_modules/bramqp/lib/connectionHandle.js:40:22)
at readableAddChunk (_stream_readable.js:146:16)
at Socket.Readable.push (_stream_readable.js:110:10)
at TCP.onread (net.js:523:20)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.