amqplib 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/test.yml +38 -0
- package/CHANGELOG.md +57 -0
- package/Makefile +6 -7
- package/README.md +66 -64
- package/bin/generate-defs.js +0 -1
- package/channel_api.js +3 -3
- package/examples/tutorials/README.md +6 -6
- package/examples/tutorials/receive_logs_direct.js +1 -2
- package/examples/tutorials/receive_logs_topic.js +1 -2
- package/examples/tutorials/rpc_client.js +0 -1
- package/lib/bitset.js +99 -72
- package/lib/callback_model.js +0 -1
- package/lib/channel.js +7 -6
- package/lib/channel_model.js +271 -287
- package/lib/connect.js +5 -1
- package/lib/connection.js +14 -6
- package/lib/credentials.js +0 -1
- package/lib/defs.js +1 -1
- package/lib/frame.js +0 -1
- package/lib/mux.js +1 -3
- package/package.json +6 -9
- package/test/bitset.js +22 -21
- package/test/callback_api.js +0 -1
- package/test/channel.js +6 -9
- package/test/channel_api.js +36 -37
- package/test/codec.js +0 -1
- package/test/connect.js +47 -2
- package/test/connection.js +0 -1
- package/test/data.js +0 -1
- package/test/frame.js +2 -3
- package/test/util.js +0 -1
- package/.npmignore +0 -8
- package/package-lock.json +0 -1623
package/lib/channel_model.js
CHANGED
|
@@ -4,264 +4,255 @@
|
|
|
4
4
|
|
|
5
5
|
'use strict';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
7
|
+
const EventEmitter = require('events');
|
|
8
|
+
const promisify = require('util').promisify;
|
|
9
|
+
const defs = require('./defs');
|
|
10
|
+
const {BaseChannel} = require('./channel');
|
|
11
|
+
const {acceptMessage} = require('./channel');
|
|
12
|
+
const Args = require('./api_args');
|
|
13
|
+
const {inspect} = require('./format');
|
|
14
|
+
|
|
15
|
+
class ChannelModel extends EventEmitter {
|
|
16
|
+
constructor(connection) {
|
|
17
|
+
super();
|
|
18
|
+
this.connection = connection;
|
|
19
|
+
|
|
20
|
+
['error', 'close', 'blocked', 'unblocked'].forEach(ev => {
|
|
21
|
+
connection.on(ev, this.emit.bind(this, ev));
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
close() {
|
|
26
|
+
return promisify(this.connection.close.bind(this.connection))();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async createChannel() {
|
|
30
|
+
const channel = new Channel(this.connection);
|
|
31
|
+
await channel.open();
|
|
32
|
+
return channel;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async createConfirmChannel() {
|
|
36
|
+
const channel = new ConfirmChannel(this.connection);
|
|
37
|
+
await channel.open();
|
|
38
|
+
await channel.rpc(defs.ConfirmSelect, {nowait: false}, defs.ConfirmSelectOk);
|
|
39
|
+
return channel;
|
|
40
|
+
}
|
|
24
41
|
}
|
|
25
|
-
inherits(ChannelModel, EventEmitter);
|
|
26
|
-
|
|
27
|
-
module.exports.ChannelModel = ChannelModel;
|
|
28
|
-
|
|
29
|
-
var CM = ChannelModel.prototype;
|
|
30
|
-
|
|
31
|
-
CM.close = function() {
|
|
32
|
-
return Promise.fromCallback(this.connection.close.bind(this.connection));
|
|
33
|
-
};
|
|
34
42
|
|
|
35
43
|
// Channels
|
|
36
44
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
class Channel extends BaseChannel {
|
|
46
|
+
constructor(connection) {
|
|
47
|
+
super(connection);
|
|
48
|
+
this.on('delivery', this.handleDelivery.bind(this));
|
|
49
|
+
this.on('cancel', this.handleCancel.bind(this));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// An RPC that returns a 'proper' promise, which resolves to just the
|
|
53
|
+
// response's fields; this is intended to be suitable for implementing
|
|
54
|
+
// API procedures.
|
|
55
|
+
async rpc(method, fields, expect) {
|
|
56
|
+
const f = await promisify(cb => {
|
|
57
|
+
return this._rpc(method, fields, expect, cb);
|
|
58
|
+
})();
|
|
45
59
|
|
|
46
|
-
CM.createChannel = function() {
|
|
47
|
-
var c = new Channel(this.connection);
|
|
48
|
-
return c.open().then(function(openOk) { return c; });
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
var C = Channel.prototype;
|
|
52
|
-
|
|
53
|
-
// An RPC that returns a 'proper' promise, which resolves to just the
|
|
54
|
-
// response's fields; this is intended to be suitable for implementing
|
|
55
|
-
// API procedures.
|
|
56
|
-
C.rpc = function(method, fields, expect) {
|
|
57
|
-
var self = this;
|
|
58
|
-
return Promise.fromCallback(function(cb) {
|
|
59
|
-
return self._rpc(method, fields, expect, cb);
|
|
60
|
-
})
|
|
61
|
-
.then(function(f) {
|
|
62
60
|
return f.fields;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Do the remarkably simple channel open handshake
|
|
64
|
+
async open() {
|
|
65
|
+
const ch = await this.allocate.bind(this)();
|
|
66
|
+
return ch.rpc(defs.ChannelOpen, {outOfBand: ""},
|
|
67
|
+
defs.ChannelOpenOk);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
close() {
|
|
71
|
+
return promisify(cb => {
|
|
72
|
+
return this.closeBecause("Goodbye", defs.constants.REPLY_SUCCESS,
|
|
73
|
+
cb);
|
|
74
|
+
})();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// === Public API, declaring queues and stuff ===
|
|
78
|
+
|
|
79
|
+
assertQueue(queue, options) {
|
|
80
|
+
return this.rpc(defs.QueueDeclare,
|
|
81
|
+
Args.assertQueue(queue, options),
|
|
82
|
+
defs.QueueDeclareOk);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
checkQueue(queue) {
|
|
86
|
+
return this.rpc(defs.QueueDeclare,
|
|
87
|
+
Args.checkQueue(queue),
|
|
88
|
+
defs.QueueDeclareOk);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
deleteQueue(queue, options) {
|
|
92
|
+
return this.rpc(defs.QueueDelete,
|
|
93
|
+
Args.deleteQueue(queue, options),
|
|
94
|
+
defs.QueueDeleteOk);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
purgeQueue(queue) {
|
|
98
|
+
return this.rpc(defs.QueuePurge,
|
|
99
|
+
Args.purgeQueue(queue),
|
|
100
|
+
defs.QueuePurgeOk);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
bindQueue(queue, source, pattern, argt) {
|
|
104
|
+
return this.rpc(defs.QueueBind,
|
|
105
|
+
Args.bindQueue(queue, source, pattern, argt),
|
|
106
|
+
defs.QueueBindOk);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
unbindQueue(queue, source, pattern, argt) {
|
|
110
|
+
return this.rpc(defs.QueueUnbind,
|
|
111
|
+
Args.unbindQueue(queue, source, pattern, argt),
|
|
112
|
+
defs.QueueUnbindOk);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
assertExchange(exchange, type, options) {
|
|
116
|
+
// The server reply is an empty set of fields, but it's convenient
|
|
117
|
+
// to have the exchange name handed to the continuation.
|
|
118
|
+
return this.rpc(defs.ExchangeDeclare,
|
|
119
|
+
Args.assertExchange(exchange, type, options),
|
|
120
|
+
defs.ExchangeDeclareOk)
|
|
121
|
+
.then(_ok => { return { exchange }; });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
checkExchange(exchange) {
|
|
125
|
+
return this.rpc(defs.ExchangeDeclare,
|
|
126
|
+
Args.checkExchange(exchange),
|
|
127
|
+
defs.ExchangeDeclareOk);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
deleteExchange(name, options) {
|
|
131
|
+
return this.rpc(defs.ExchangeDelete,
|
|
132
|
+
Args.deleteExchange(name, options),
|
|
133
|
+
defs.ExchangeDeleteOk);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
bindExchange(dest, source, pattern, argt) {
|
|
137
|
+
return this.rpc(defs.ExchangeBind,
|
|
138
|
+
Args.bindExchange(dest, source, pattern, argt),
|
|
139
|
+
defs.ExchangeBindOk);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
unbindExchange(dest, source, pattern, argt) {
|
|
143
|
+
return this.rpc(defs.ExchangeUnbind,
|
|
144
|
+
Args.unbindExchange(dest, source, pattern, argt),
|
|
145
|
+
defs.ExchangeUnbindOk);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Working with messages
|
|
149
|
+
|
|
150
|
+
publish(exchange, routingKey, content, options) {
|
|
151
|
+
const fieldsAndProps = Args.publish(exchange, routingKey, options);
|
|
152
|
+
return this.sendMessage(fieldsAndProps, fieldsAndProps, content);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
sendToQueue(queue, content, options) {
|
|
156
|
+
return this.publish('', queue, content, options);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
consume(queue, callback, options) {
|
|
160
|
+
// NB we want the callback to be run synchronously, so that we've
|
|
161
|
+
// registered the consumerTag before any messages can arrive.
|
|
162
|
+
const fields = Args.consume(queue, options);
|
|
163
|
+
return new Promise((resolve, reject) => {
|
|
164
|
+
this._rpc(defs.BasicConsume, fields, defs.BasicConsumeOk, (err, ok) => {
|
|
165
|
+
if (err) return reject(err);
|
|
166
|
+
this.registerConsumer(ok.fields.consumerTag, callback);
|
|
167
|
+
resolve(ok.fields);
|
|
168
|
+
});
|
|
72
169
|
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
Args.purgeQueue(queue),
|
|
106
|
-
defs.QueuePurgeOk);
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
C.bindQueue = function(queue, source, pattern, argt) {
|
|
110
|
-
return this.rpc(defs.QueueBind,
|
|
111
|
-
Args.bindQueue(queue, source, pattern, argt),
|
|
112
|
-
defs.QueueBindOk);
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
C.unbindQueue = function(queue, source, pattern, argt) {
|
|
116
|
-
return this.rpc(defs.QueueUnbind,
|
|
117
|
-
Args.unbindQueue(queue, source, pattern, argt),
|
|
118
|
-
defs.QueueUnbindOk);
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
C.assertExchange = function(exchange, type, options) {
|
|
122
|
-
// The server reply is an empty set of fields, but it's convenient
|
|
123
|
-
// to have the exchange name handed to the continuation.
|
|
124
|
-
return this.rpc(defs.ExchangeDeclare,
|
|
125
|
-
Args.assertExchange(exchange, type, options),
|
|
126
|
-
defs.ExchangeDeclareOk)
|
|
127
|
-
.then(function(_ok) { return { exchange: exchange }; });
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
C.checkExchange = function(exchange) {
|
|
131
|
-
return this.rpc(defs.ExchangeDeclare,
|
|
132
|
-
Args.checkExchange(exchange),
|
|
133
|
-
defs.ExchangeDeclareOk);
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
C.deleteExchange = function(name, options) {
|
|
137
|
-
return this.rpc(defs.ExchangeDelete,
|
|
138
|
-
Args.deleteExchange(name, options),
|
|
139
|
-
defs.ExchangeDeleteOk);
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
C.bindExchange = function(dest, source, pattern, argt) {
|
|
143
|
-
return this.rpc(defs.ExchangeBind,
|
|
144
|
-
Args.bindExchange(dest, source, pattern, argt),
|
|
145
|
-
defs.ExchangeBindOk);
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
C.unbindExchange = function(dest, source, pattern, argt) {
|
|
149
|
-
return this.rpc(defs.ExchangeUnbind,
|
|
150
|
-
Args.unbindExchange(dest, source, pattern, argt),
|
|
151
|
-
defs.ExchangeUnbindOk);
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
// Working with messages
|
|
155
|
-
|
|
156
|
-
C.publish = function(exchange, routingKey, content, options) {
|
|
157
|
-
var fieldsAndProps = Args.publish(exchange, routingKey, options);
|
|
158
|
-
return this.sendMessage(fieldsAndProps, fieldsAndProps, content);
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
C.sendToQueue = function(queue, content, options) {
|
|
162
|
-
return this.publish('', queue, content, options);
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
C.consume = function(queue, callback, options) {
|
|
166
|
-
var self = this;
|
|
167
|
-
// NB we want the callback to be run synchronously, so that we've
|
|
168
|
-
// registered the consumerTag before any messages can arrive.
|
|
169
|
-
var fields = Args.consume(queue, options);
|
|
170
|
-
return Promise.fromCallback(function(cb) {
|
|
171
|
-
self._rpc(defs.BasicConsume, fields, defs.BasicConsumeOk, cb);
|
|
172
|
-
})
|
|
173
|
-
.then(function(ok) {
|
|
174
|
-
self.registerConsumer(ok.fields.consumerTag, callback);
|
|
175
|
-
return ok.fields;
|
|
176
|
-
});
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
C.cancel = function(consumerTag) {
|
|
180
|
-
var self = this;
|
|
181
|
-
return Promise.fromCallback(function(cb) {
|
|
182
|
-
self._rpc(defs.BasicCancel, Args.cancel(consumerTag),
|
|
183
|
-
defs.BasicCancelOk,
|
|
184
|
-
cb);
|
|
185
|
-
})
|
|
186
|
-
.then(function(ok) {
|
|
187
|
-
self.unregisterConsumer(consumerTag);
|
|
188
|
-
return ok.fields;
|
|
189
|
-
});
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
C.get = function(queue, options) {
|
|
193
|
-
var self = this;
|
|
194
|
-
var fields = Args.get(queue, options);
|
|
195
|
-
return Promise.fromCallback(function(cb) {
|
|
196
|
-
return self.sendOrEnqueue(defs.BasicGet, fields, cb);
|
|
197
|
-
})
|
|
198
|
-
.then(function(f) {
|
|
199
|
-
if (f.id === defs.BasicGetEmpty) {
|
|
200
|
-
return false;
|
|
201
|
-
}
|
|
202
|
-
else if (f.id === defs.BasicGetOk) {
|
|
203
|
-
var fields = f.fields;
|
|
204
|
-
return new Promise(function(resolve) {
|
|
205
|
-
self.handleMessage = acceptMessage(function(m) {
|
|
206
|
-
m.fields = fields;
|
|
207
|
-
resolve(m);
|
|
208
|
-
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async cancel(consumerTag) {
|
|
173
|
+
const ok = await promisify(cb => {
|
|
174
|
+
this._rpc(defs.BasicCancel, Args.cancel(consumerTag),
|
|
175
|
+
defs.BasicCancelOk,
|
|
176
|
+
cb);
|
|
177
|
+
})()
|
|
178
|
+
.then(ok => {
|
|
179
|
+
this.unregisterConsumer(consumerTag);
|
|
180
|
+
return ok.fields;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
get(queue, options) {
|
|
185
|
+
const fields = Args.get(queue, options);
|
|
186
|
+
return new Promise((resolve, reject) => {
|
|
187
|
+
this.sendOrEnqueue(defs.BasicGet, fields, (err, f) => {
|
|
188
|
+
if (err) return reject(err);
|
|
189
|
+
if (f.id === defs.BasicGetEmpty) {
|
|
190
|
+
return resolve(false);
|
|
191
|
+
}
|
|
192
|
+
else if (f.id === defs.BasicGetOk) {
|
|
193
|
+
const fields = f.fields;
|
|
194
|
+
this.handleMessage = acceptMessage(m => {
|
|
195
|
+
m.fields = fields;
|
|
196
|
+
resolve(m);
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
reject(new Error(`Unexpected response to BasicGet: ${inspect(f)}`));
|
|
201
|
+
}
|
|
209
202
|
});
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
defs.BasicAck,
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
defs.BasicNack,
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
defs.
|
|
246
|
-
|
|
247
|
-
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
ack(message, allUpTo) {
|
|
207
|
+
this.sendImmediately(
|
|
208
|
+
defs.BasicAck,
|
|
209
|
+
Args.ack(message.fields.deliveryTag, allUpTo));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
ackAll() {
|
|
213
|
+
this.sendImmediately(defs.BasicAck, Args.ack(0, true));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
nack(message, allUpTo, requeue) {
|
|
217
|
+
this.sendImmediately(
|
|
218
|
+
defs.BasicNack,
|
|
219
|
+
Args.nack(message.fields.deliveryTag, allUpTo, requeue));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
nackAll(requeue) {
|
|
223
|
+
this.sendImmediately(defs.BasicNack,
|
|
224
|
+
Args.nack(0, true, requeue));
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// `Basic.Nack` is not available in older RabbitMQ versions (or in the
|
|
228
|
+
// AMQP specification), so you have to use the one-at-a-time
|
|
229
|
+
// `Basic.Reject`. This is otherwise synonymous with
|
|
230
|
+
// `#nack(message, false, requeue)`.
|
|
231
|
+
reject(message, requeue) {
|
|
232
|
+
this.sendImmediately(
|
|
233
|
+
defs.BasicReject,
|
|
234
|
+
Args.reject(message.fields.deliveryTag, requeue));
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
recover() {
|
|
238
|
+
return this.rpc(defs.BasicRecover,
|
|
239
|
+
Args.recover(),
|
|
240
|
+
defs.BasicRecoverOk);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
qos(count, global) {
|
|
244
|
+
return this.rpc(defs.BasicQos,
|
|
245
|
+
Args.prefetch(count, global),
|
|
246
|
+
defs.BasicQosOk);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
248
249
|
|
|
249
250
|
// There are more options in AMQP than exposed here; RabbitMQ only
|
|
250
251
|
// implements prefetch based on message count, and only for individual
|
|
251
252
|
// channels or consumers. RabbitMQ v3.3.0 and after treat prefetch
|
|
252
253
|
// (without `global` set) as per-consumer (for consumers following),
|
|
253
254
|
// and prefetch with `global` set as per-channel.
|
|
254
|
-
|
|
255
|
-
return this.rpc(defs.BasicQos,
|
|
256
|
-
Args.prefetch(count, global),
|
|
257
|
-
defs.BasicQosOk);
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
C.recover = function() {
|
|
261
|
-
return this.rpc(defs.BasicRecover,
|
|
262
|
-
Args.recover(),
|
|
263
|
-
defs.BasicRecoverOk);
|
|
264
|
-
};
|
|
255
|
+
Channel.prototype.prefetch = Channel.prototype.qos
|
|
265
256
|
|
|
266
257
|
// Confirm channel. This is a channel with confirms 'switched on',
|
|
267
258
|
// meaning sent messages will provoke a responding 'ack' or 'nack'
|
|
@@ -270,49 +261,42 @@ C.recover = function() {
|
|
|
270
261
|
// with `null` as its argument to signify 'ack', or an exception as
|
|
271
262
|
// its argument to signify 'nack'.
|
|
272
263
|
|
|
273
|
-
|
|
274
|
-
|
|
264
|
+
class ConfirmChannel extends Channel {
|
|
265
|
+
publish(exchange, routingKey, content, options, cb) {
|
|
266
|
+
this.pushConfirmCallback(cb);
|
|
267
|
+
return Channel.prototype.publish.call(this, exchange, routingKey, content, options);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
sendToQueue(queue, content, options, cb) {
|
|
271
|
+
return this.publish('', queue, content, options, cb);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
waitForConfirms() {
|
|
275
|
+
const awaiting = [];
|
|
276
|
+
const unconfirmed = this.unconfirmed;
|
|
277
|
+
unconfirmed.forEach((val, index) => {
|
|
278
|
+
if (val !== null) {
|
|
279
|
+
const confirmed = new Promise((resolve, reject) => {
|
|
280
|
+
unconfirmed[index] = err => {
|
|
281
|
+
if (val) val(err);
|
|
282
|
+
if (err === null) resolve();
|
|
283
|
+
else reject(err);
|
|
284
|
+
};
|
|
285
|
+
});
|
|
286
|
+
awaiting.push(confirmed);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
// Channel closed
|
|
290
|
+
if (!this.pending) {
|
|
291
|
+
var cb;
|
|
292
|
+
while (cb = this.unconfirmed.shift()) {
|
|
293
|
+
if (cb) cb(new Error('channel closed'));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return Promise.all(awaiting);
|
|
297
|
+
}
|
|
275
298
|
}
|
|
276
|
-
inherits(ConfirmChannel, Channel);
|
|
277
299
|
|
|
278
300
|
module.exports.ConfirmChannel = ConfirmChannel;
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
var c = new ConfirmChannel(this.connection);
|
|
282
|
-
return c.open()
|
|
283
|
-
.then(function(openOk) {
|
|
284
|
-
return c.rpc(defs.ConfirmSelect, {nowait: false},
|
|
285
|
-
defs.ConfirmSelectOk)
|
|
286
|
-
})
|
|
287
|
-
.then(function() { return c; });
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
var CC = ConfirmChannel.prototype;
|
|
291
|
-
|
|
292
|
-
CC.publish = function(exchange, routingKey, content, options, cb) {
|
|
293
|
-
this.pushConfirmCallback(cb);
|
|
294
|
-
return C.publish.call(this, exchange, routingKey, content, options);
|
|
295
|
-
};
|
|
296
|
-
|
|
297
|
-
CC.sendToQueue = function(queue, content, options, cb) {
|
|
298
|
-
return this.publish('', queue, content, options, cb);
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
CC.waitForConfirms = function() {
|
|
302
|
-
var awaiting = [];
|
|
303
|
-
var unconfirmed = this.unconfirmed;
|
|
304
|
-
unconfirmed.forEach(function(val, index) {
|
|
305
|
-
if (val === null); // already confirmed
|
|
306
|
-
else {
|
|
307
|
-
var confirmed = new Promise(function(resolve, reject) {
|
|
308
|
-
unconfirmed[index] = function(err) {
|
|
309
|
-
if (val) val(err);
|
|
310
|
-
if (err === null) resolve();
|
|
311
|
-
else reject(err);
|
|
312
|
-
};
|
|
313
|
-
});
|
|
314
|
-
awaiting.push(confirmed);
|
|
315
|
-
}
|
|
316
|
-
});
|
|
317
|
-
return Promise.all(awaiting);
|
|
318
|
-
};
|
|
301
|
+
module.exports.Channel = Channel;
|
|
302
|
+
module.exports.ChannelModel = ChannelModel;
|
package/lib/connect.js
CHANGED
|
@@ -152,8 +152,12 @@ function connect(url, socketOptions, openCallback) {
|
|
|
152
152
|
if (timeout) sock.setTimeout(0);
|
|
153
153
|
if (err === null) {
|
|
154
154
|
openCallback(null, c);
|
|
155
|
+
} else {
|
|
156
|
+
// The connection isn't closed by the server on e.g. wrong password
|
|
157
|
+
sock.end();
|
|
158
|
+
sock.destroy();
|
|
159
|
+
openCallback(err);
|
|
155
160
|
}
|
|
156
|
-
else openCallback(err);
|
|
157
161
|
});
|
|
158
162
|
}
|
|
159
163
|
|
package/lib/connection.js
CHANGED
|
@@ -9,7 +9,6 @@ var constants = defs.constants;
|
|
|
9
9
|
var frame = require('./frame');
|
|
10
10
|
var HEARTBEAT = frame.HEARTBEAT;
|
|
11
11
|
var Mux = require('./mux').Mux;
|
|
12
|
-
var Buffer = require('safe-buffer').Buffer
|
|
13
12
|
|
|
14
13
|
var Duplex =
|
|
15
14
|
require('stream').Duplex ||
|
|
@@ -179,8 +178,7 @@ C.open = function(allFields, openCallback0) {
|
|
|
179
178
|
function send(Method) {
|
|
180
179
|
// This can throw an exception if there's some problem with the
|
|
181
180
|
// options; e.g., something is a string instead of a number.
|
|
182
|
-
|
|
183
|
-
catch (err) { bail(err); }
|
|
181
|
+
self.sendMethod(0, Method, tunedOptions);
|
|
184
182
|
}
|
|
185
183
|
|
|
186
184
|
function negotiate(server, desired) {
|
|
@@ -206,7 +204,12 @@ C.open = function(allFields, openCallback0) {
|
|
|
206
204
|
return;
|
|
207
205
|
}
|
|
208
206
|
self.serverProperties = start.fields.serverProperties;
|
|
209
|
-
|
|
207
|
+
try {
|
|
208
|
+
send(defs.ConnectionStartOk);
|
|
209
|
+
} catch (err) {
|
|
210
|
+
bail(err);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
210
213
|
wait(afterStartOk);
|
|
211
214
|
}
|
|
212
215
|
|
|
@@ -228,8 +231,13 @@ C.open = function(allFields, openCallback0) {
|
|
|
228
231
|
negotiate(fields.channelMax, allFields.channelMax);
|
|
229
232
|
tunedOptions.heartbeat =
|
|
230
233
|
negotiate(fields.heartbeat, allFields.heartbeat);
|
|
231
|
-
|
|
232
|
-
|
|
234
|
+
try {
|
|
235
|
+
send(defs.ConnectionTuneOk);
|
|
236
|
+
send(defs.ConnectionOpen);
|
|
237
|
+
} catch (err) {
|
|
238
|
+
bail(err);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
233
241
|
expect(defs.ConnectionOpenOk, onOpenOk);
|
|
234
242
|
break;
|
|
235
243
|
default:
|
package/lib/credentials.js
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
// * PLAIN (send username and password in the plain)
|
|
9
9
|
// * EXTERNAL (assume the server will figure out who you are from
|
|
10
10
|
// context, i.e., your SSL certificate)
|
|
11
|
-
var Buffer = require('safe-buffer').Buffer
|
|
12
11
|
var codec = require('./codec')
|
|
13
12
|
|
|
14
13
|
module.exports.plain = function(user, passwd) {
|
package/lib/defs.js
CHANGED
|
@@ -3059,7 +3059,7 @@ function decodeBasicProperties(buffer) {
|
|
|
3059
3059
|
return fields;
|
|
3060
3060
|
}
|
|
3061
3061
|
|
|
3062
|
-
var
|
|
3062
|
+
var codec = require("./codec"), ints = require("buffer-more-ints"), encodeTable = codec.encodeTable, decodeFields = codec.decodeFields, SCRATCH = Buffer.alloc(65536), EMPTY_OBJECT = Object.freeze({});
|
|
3063
3063
|
|
|
3064
3064
|
module.exports.constants = {
|
|
3065
3065
|
FRAME_METHOD: 1,
|