@reproapp/node-sdk 0.0.25 → 0.0.26
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/dist/index.js +20 -0
- package/package.json +1 -1
- package/src/index.ts +19 -0
- package/test/amqplib-integration.test.js +50 -0
package/dist/index.js
CHANGED
|
@@ -6325,6 +6325,7 @@ function patchKafkaJs(cfg) {
|
|
|
6325
6325
|
}
|
|
6326
6326
|
}
|
|
6327
6327
|
exports.patchKafkaJs = patchKafkaJs;
|
|
6328
|
+
const AMQP_INTERNAL_PUBLISH_DEPTH = Symbol.for('repro.amqplib.internalPublishDepth');
|
|
6328
6329
|
function decodeAmqpHeaderValue(value) {
|
|
6329
6330
|
if (value === null || value === undefined)
|
|
6330
6331
|
return null;
|
|
@@ -6726,6 +6727,9 @@ function patchAmqplibPublishMethod(channel, cfg, methodName) {
|
|
|
6726
6727
|
const optionsIndex = methodName === 'publish' ? 3 : 2;
|
|
6727
6728
|
const method = methodName === 'publish' ? 'AMQP_PUBLISH' : 'AMQP_SEND_TO_QUEUE';
|
|
6728
6729
|
const wrapped = function reproPatchedAmqplibPublish(...args) {
|
|
6730
|
+
if (methodName === 'publish' && Number(this?.[AMQP_INTERNAL_PUBLISH_DEPTH] ?? 0) > 0) {
|
|
6731
|
+
return orig.apply(this, args);
|
|
6732
|
+
}
|
|
6729
6733
|
const ctx = getCtx();
|
|
6730
6734
|
const fallback = cfg.resolveContext?.() ?? {};
|
|
6731
6735
|
const sid = ctx.sid ?? fallback.sid ?? null;
|
|
@@ -6797,7 +6801,12 @@ function patchAmqplibPublishMethod(channel, cfg, methodName) {
|
|
|
6797
6801
|
: (wrappedCallback
|
|
6798
6802
|
? setAmqpPublishOptionsArg(args, optionsIndex, nextOptions, callbackIndex, wrappedCallback)
|
|
6799
6803
|
: args);
|
|
6804
|
+
let bumpedInternalPublishDepth = false;
|
|
6800
6805
|
try {
|
|
6806
|
+
if (methodName === 'sendToQueue' && this && typeof this === 'object') {
|
|
6807
|
+
this[AMQP_INTERNAL_PUBLISH_DEPTH] = Number(this?.[AMQP_INTERNAL_PUBLISH_DEPTH] ?? 0) + 1;
|
|
6808
|
+
bumpedInternalPublishDepth = true;
|
|
6809
|
+
}
|
|
6801
6810
|
const result = orig.apply(this, nextArgs);
|
|
6802
6811
|
if (!wrappedCallback) {
|
|
6803
6812
|
finish(200, undefined, result);
|
|
@@ -6808,6 +6817,17 @@ function patchAmqplibPublishMethod(channel, cfg, methodName) {
|
|
|
6808
6817
|
finish(500, error);
|
|
6809
6818
|
throw error;
|
|
6810
6819
|
}
|
|
6820
|
+
finally {
|
|
6821
|
+
if (bumpedInternalPublishDepth) {
|
|
6822
|
+
const nextDepth = Number(this?.[AMQP_INTERNAL_PUBLISH_DEPTH] ?? 0) - 1;
|
|
6823
|
+
if (nextDepth > 0) {
|
|
6824
|
+
this[AMQP_INTERNAL_PUBLISH_DEPTH] = nextDepth;
|
|
6825
|
+
}
|
|
6826
|
+
else if (this && typeof this === 'object') {
|
|
6827
|
+
delete this[AMQP_INTERNAL_PUBLISH_DEPTH];
|
|
6828
|
+
}
|
|
6829
|
+
}
|
|
6830
|
+
}
|
|
6811
6831
|
};
|
|
6812
6832
|
wrapped.__repro_amqplib_patched = true;
|
|
6813
6833
|
channel[methodName] = wrapped;
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -7389,6 +7389,7 @@ type AmqpPropagationContext = {
|
|
|
7389
7389
|
parentSpanId: string | null;
|
|
7390
7390
|
requestRid: string | null;
|
|
7391
7391
|
};
|
|
7392
|
+
const AMQP_INTERNAL_PUBLISH_DEPTH = Symbol.for('repro.amqplib.internalPublishDepth');
|
|
7392
7393
|
|
|
7393
7394
|
export type AmqplibPatchConfig = ReproMiddlewareConfig & {
|
|
7394
7395
|
resolveContext?: AmqpContextResolver;
|
|
@@ -7859,6 +7860,10 @@ function patchAmqplibPublishMethod(
|
|
|
7859
7860
|
const method = methodName === 'publish' ? 'AMQP_PUBLISH' : 'AMQP_SEND_TO_QUEUE';
|
|
7860
7861
|
|
|
7861
7862
|
const wrapped = function reproPatchedAmqplibPublish(this: any, ...args: any[]) {
|
|
7863
|
+
if (methodName === 'publish' && Number(this?.[AMQP_INTERNAL_PUBLISH_DEPTH] ?? 0) > 0) {
|
|
7864
|
+
return orig.apply(this, args);
|
|
7865
|
+
}
|
|
7866
|
+
|
|
7862
7867
|
const ctx = getCtx();
|
|
7863
7868
|
const fallback = cfg.resolveContext?.() ?? {};
|
|
7864
7869
|
const sid = ctx.sid ?? fallback.sid ?? null;
|
|
@@ -7933,8 +7938,13 @@ function patchAmqplibPublishMethod(
|
|
|
7933
7938
|
: (wrappedCallback
|
|
7934
7939
|
? setAmqpPublishOptionsArg(args, optionsIndex, nextOptions, callbackIndex, wrappedCallback)
|
|
7935
7940
|
: args);
|
|
7941
|
+
let bumpedInternalPublishDepth = false;
|
|
7936
7942
|
|
|
7937
7943
|
try {
|
|
7944
|
+
if (methodName === 'sendToQueue' && this && typeof this === 'object') {
|
|
7945
|
+
this[AMQP_INTERNAL_PUBLISH_DEPTH] = Number(this?.[AMQP_INTERNAL_PUBLISH_DEPTH] ?? 0) + 1;
|
|
7946
|
+
bumpedInternalPublishDepth = true;
|
|
7947
|
+
}
|
|
7938
7948
|
const result = orig.apply(this, nextArgs);
|
|
7939
7949
|
if (!wrappedCallback) {
|
|
7940
7950
|
finish(200, undefined, result);
|
|
@@ -7943,6 +7953,15 @@ function patchAmqplibPublishMethod(
|
|
|
7943
7953
|
} catch (error) {
|
|
7944
7954
|
finish(500, error);
|
|
7945
7955
|
throw error;
|
|
7956
|
+
} finally {
|
|
7957
|
+
if (bumpedInternalPublishDepth) {
|
|
7958
|
+
const nextDepth = Number(this?.[AMQP_INTERNAL_PUBLISH_DEPTH] ?? 0) - 1;
|
|
7959
|
+
if (nextDepth > 0) {
|
|
7960
|
+
this[AMQP_INTERNAL_PUBLISH_DEPTH] = nextDepth;
|
|
7961
|
+
} else if (this && typeof this === 'object') {
|
|
7962
|
+
delete this[AMQP_INTERNAL_PUBLISH_DEPTH];
|
|
7963
|
+
}
|
|
7964
|
+
}
|
|
7946
7965
|
}
|
|
7947
7966
|
};
|
|
7948
7967
|
|
|
@@ -286,6 +286,55 @@ async function testCallbackApiConnectAndConfirmChannelArePatched() {
|
|
|
286
286
|
});
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
+
async function testSendToQueueDoesNotDoubleCaptureInternalPublish() {
|
|
290
|
+
await withCapturedFetch(async (capturedBodies) => {
|
|
291
|
+
__reproTestHooks.resetSdkBackgroundQueuesForTest();
|
|
292
|
+
const internalPublishes = [];
|
|
293
|
+
const channel = {
|
|
294
|
+
publish(exchange, routingKey, content, options) {
|
|
295
|
+
internalPublishes.push({ exchange, routingKey, content, options });
|
|
296
|
+
return true;
|
|
297
|
+
},
|
|
298
|
+
sendToQueue(queue, content, options) {
|
|
299
|
+
return this.publish('', queue, content, options);
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
const cfg = makeConfig('S_amqp_send', 'A_amqp_send');
|
|
303
|
+
__reproTestHooks.patchAmqplibChannelForTest(channel, cfg);
|
|
304
|
+
|
|
305
|
+
const result = channel.sendToQueue(
|
|
306
|
+
'outbound-email',
|
|
307
|
+
Buffer.from(JSON.stringify({ subject: 'hello', html: '<p>full html</p>' })),
|
|
308
|
+
{ contentType: 'application/json', headers: { existing: 'yes' } },
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
assert.strictEqual(result, true);
|
|
312
|
+
assert.strictEqual(internalPublishes.length, 1);
|
|
313
|
+
assert.strictEqual(internalPublishes[0].exchange, '');
|
|
314
|
+
assert.strictEqual(internalPublishes[0].routingKey, 'outbound-email');
|
|
315
|
+
assert.strictEqual(internalPublishes[0].options.headers.existing, 'yes');
|
|
316
|
+
assert.strictEqual(internalPublishes[0].options.headers['x-bug-session-id'], 'S_amqp_send');
|
|
317
|
+
assert.strictEqual(internalPublishes[0].options.headers['x-bug-action-id'], 'A_amqp_send');
|
|
318
|
+
assert(internalPublishes[0].options.headers['x-repro-request-rid']);
|
|
319
|
+
|
|
320
|
+
await waitFor(() => flattenEvents(capturedBodies)
|
|
321
|
+
.some((event) => event?.event_type === 'backend_request'));
|
|
322
|
+
await drainSdk();
|
|
323
|
+
|
|
324
|
+
const backendRequests = flattenEvents(capturedBodies)
|
|
325
|
+
.filter((event) => event?.event_type === 'backend_request');
|
|
326
|
+
assert.strictEqual(
|
|
327
|
+
backendRequests.length,
|
|
328
|
+
1,
|
|
329
|
+
JSON.stringify(backendRequests.map((event) => event.payload?.request?.method)),
|
|
330
|
+
);
|
|
331
|
+
assert.strictEqual(backendRequests[0].payload.request.method, 'AMQP_SEND_TO_QUEUE');
|
|
332
|
+
assert.strictEqual(backendRequests[0].payload.request.path, 'amqp://queue/outbound-email');
|
|
333
|
+
assert.strictEqual(backendRequests[0].payload.request.body.message.value.subject, 'hello');
|
|
334
|
+
assert.strictEqual(backendRequests[0].payload.request.body.message.value.html, '<p>full html</p>');
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
289
338
|
async function testNullConsumeMessagePassesThrough() {
|
|
290
339
|
let received = 'not-called';
|
|
291
340
|
const wrapped = __reproTestHooks.wrapAmqplibConsumeHandlerForTest((message) => {
|
|
@@ -329,6 +378,7 @@ async function main() {
|
|
|
329
378
|
await testPublishInjectsHeadersWithoutMutatingOptions();
|
|
330
379
|
await testConsumeCapturesRequestTraceAndManifest();
|
|
331
380
|
await testCallbackApiConnectAndConfirmChannelArePatched();
|
|
381
|
+
await testSendToQueueDoesNotDoubleCaptureInternalPublish();
|
|
332
382
|
await testNullConsumeMessagePassesThrough();
|
|
333
383
|
await testSyncConsumeThrowIsNotRetried();
|
|
334
384
|
console.log('amqplib integration OK');
|