@reproapp/node-sdk 0.0.54 → 0.0.55
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
CHANGED
|
@@ -7870,7 +7870,7 @@ function scheduleAmqpPublishCapture(params) {
|
|
|
7870
7870
|
url: params.path,
|
|
7871
7871
|
path: params.path,
|
|
7872
7872
|
status: params.status,
|
|
7873
|
-
durMs:
|
|
7873
|
+
durMs: params.durationMs,
|
|
7874
7874
|
key: params.key,
|
|
7875
7875
|
headers: {
|
|
7876
7876
|
transport: 'amqp',
|
|
@@ -7890,7 +7890,7 @@ function scheduleAmqpPublishCapture(params) {
|
|
|
7890
7890
|
entries: [{
|
|
7891
7891
|
actionId: params.aid ?? null,
|
|
7892
7892
|
request: requestPayload,
|
|
7893
|
-
t:
|
|
7893
|
+
t: params.completedAt,
|
|
7894
7894
|
}],
|
|
7895
7895
|
});
|
|
7896
7896
|
post(params.cfg, params.sid, {
|
|
@@ -7952,6 +7952,9 @@ function patchAmqplibPublishMethod(channel, cfg, methodName) {
|
|
|
7952
7952
|
if (finished)
|
|
7953
7953
|
return;
|
|
7954
7954
|
finished = true;
|
|
7955
|
+
// Capture queue and privacy processing time are not broker latency.
|
|
7956
|
+
const durationMs = Math.max(0, Date.now() - t0);
|
|
7957
|
+
const completedAt = alignedNow();
|
|
7955
7958
|
scheduleAmqpPublishCapture({
|
|
7956
7959
|
cfg,
|
|
7957
7960
|
sid,
|
|
@@ -7967,7 +7970,8 @@ function patchAmqplibPublishMethod(channel, cfg, methodName) {
|
|
|
7967
7970
|
content,
|
|
7968
7971
|
options: nextOptions,
|
|
7969
7972
|
span,
|
|
7970
|
-
|
|
7973
|
+
durationMs,
|
|
7974
|
+
completedAt,
|
|
7971
7975
|
status,
|
|
7972
7976
|
error,
|
|
7973
7977
|
result,
|
|
@@ -8100,6 +8104,8 @@ function wrapAmqplibConsumeHandler(onMessage, cfg, queue) {
|
|
|
8100
8104
|
finished = true;
|
|
8101
8105
|
if (!sid)
|
|
8102
8106
|
return;
|
|
8107
|
+
const durationMs = Math.max(0, Date.now() - t0);
|
|
8108
|
+
const completedAt = alignedNow();
|
|
8103
8109
|
const fields = message?.fields ?? {};
|
|
8104
8110
|
const messagePayload = buildAmqpMessagePayload(message?.content, properties);
|
|
8105
8111
|
const body = {
|
|
@@ -8129,7 +8135,7 @@ function wrapAmqplibConsumeHandler(onMessage, cfg, queue) {
|
|
|
8129
8135
|
url: `amqp://queue/${queueName}`,
|
|
8130
8136
|
path: `amqp://queue/${queueName}`,
|
|
8131
8137
|
status: threw ? 500 : 200,
|
|
8132
|
-
durMs:
|
|
8138
|
+
durMs: durationMs,
|
|
8133
8139
|
key: `AMQP_CONSUME ${queueName}`,
|
|
8134
8140
|
headers: normalizeAmqpHeadersForPayload(headers),
|
|
8135
8141
|
body: bodyMaterialization.value,
|
|
@@ -8140,7 +8146,7 @@ function wrapAmqplibConsumeHandler(onMessage, cfg, queue) {
|
|
|
8140
8146
|
entries: [{
|
|
8141
8147
|
actionId: aid ?? null,
|
|
8142
8148
|
request: requestPayload,
|
|
8143
|
-
t:
|
|
8149
|
+
t: completedAt,
|
|
8144
8150
|
}],
|
|
8145
8151
|
});
|
|
8146
8152
|
scheduleAmqpTraceFlush(cfg, amqpCtx, aid, consumeRid, rawTraceEvents, maskReq, captureScope);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reproapp/node-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.55",
|
|
4
4
|
"description": "Repro Nest SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"test:latency": "npm run build && node test/privacy-fetch-timeout.test.js && node test/capture-latency.testcontainers.test.js",
|
|
14
14
|
"test:live-capture": "npm run build && node test/twelve-element-capture.testcontainers.test.js && node test/live-capture-limits.test.js && node test/ingest-throttle-retention.test.js && node test/live-capture-limits.testcontainers.test.js",
|
|
15
15
|
"test:live-brokers": "npm run build && node test/live-broker-limits.testcontainers.test.js",
|
|
16
|
+
"test:amqp-timing": "npm run build && node test/amqplib-integration.test.js && node test/amqplib-timing.testcontainers.test.js",
|
|
16
17
|
"build": "tsc -p tsconfig.json",
|
|
17
18
|
"dev": "tsc -p tsconfig.json --watch --preserveWatchOutput",
|
|
18
19
|
"prepublishOnly": "npm run build",
|
package/src/index.ts
CHANGED
|
@@ -9498,7 +9498,8 @@ function scheduleAmqpPublishCapture(params: {
|
|
|
9498
9498
|
content: any;
|
|
9499
9499
|
options: any;
|
|
9500
9500
|
span: SpanContext | null;
|
|
9501
|
-
|
|
9501
|
+
durationMs: number;
|
|
9502
|
+
completedAt: number;
|
|
9502
9503
|
status: number;
|
|
9503
9504
|
error?: any;
|
|
9504
9505
|
result?: any;
|
|
@@ -9540,7 +9541,7 @@ function scheduleAmqpPublishCapture(params: {
|
|
|
9540
9541
|
url: params.path,
|
|
9541
9542
|
path: params.path,
|
|
9542
9543
|
status: params.status,
|
|
9543
|
-
durMs:
|
|
9544
|
+
durMs: params.durationMs,
|
|
9544
9545
|
key: params.key,
|
|
9545
9546
|
headers: {
|
|
9546
9547
|
transport: 'amqp',
|
|
@@ -9561,7 +9562,7 @@ function scheduleAmqpPublishCapture(params: {
|
|
|
9561
9562
|
entries: [{
|
|
9562
9563
|
actionId: params.aid ?? null,
|
|
9563
9564
|
request: requestPayload,
|
|
9564
|
-
t:
|
|
9565
|
+
t: params.completedAt,
|
|
9565
9566
|
}],
|
|
9566
9567
|
});
|
|
9567
9568
|
post(params.cfg, params.sid!, {
|
|
@@ -9634,6 +9635,9 @@ function patchAmqplibPublishMethod(
|
|
|
9634
9635
|
const finish = (status: number, error?: any, result?: any) => {
|
|
9635
9636
|
if (finished) return;
|
|
9636
9637
|
finished = true;
|
|
9638
|
+
// Capture queue and privacy processing time are not broker latency.
|
|
9639
|
+
const durationMs = Math.max(0, Date.now() - t0);
|
|
9640
|
+
const completedAt = alignedNow();
|
|
9637
9641
|
scheduleAmqpPublishCapture({
|
|
9638
9642
|
cfg,
|
|
9639
9643
|
sid,
|
|
@@ -9649,7 +9653,8 @@ function patchAmqplibPublishMethod(
|
|
|
9649
9653
|
content,
|
|
9650
9654
|
options: nextOptions,
|
|
9651
9655
|
span,
|
|
9652
|
-
|
|
9656
|
+
durationMs,
|
|
9657
|
+
completedAt,
|
|
9653
9658
|
status,
|
|
9654
9659
|
error,
|
|
9655
9660
|
result,
|
|
@@ -9779,6 +9784,8 @@ function wrapAmqplibConsumeHandler(onMessage: any, cfg: AmqplibPatchConfig, queu
|
|
|
9779
9784
|
if (finished) return;
|
|
9780
9785
|
finished = true;
|
|
9781
9786
|
if (!sid) return;
|
|
9787
|
+
const durationMs = Math.max(0, Date.now() - t0);
|
|
9788
|
+
const completedAt = alignedNow();
|
|
9782
9789
|
const fields = message?.fields ?? {};
|
|
9783
9790
|
const messagePayload = buildAmqpMessagePayload(message?.content, properties);
|
|
9784
9791
|
const body = {
|
|
@@ -9814,7 +9821,7 @@ function wrapAmqplibConsumeHandler(onMessage: any, cfg: AmqplibPatchConfig, queu
|
|
|
9814
9821
|
url: `amqp://queue/${queueName}`,
|
|
9815
9822
|
path: `amqp://queue/${queueName}`,
|
|
9816
9823
|
status: threw ? 500 : 200,
|
|
9817
|
-
durMs:
|
|
9824
|
+
durMs: durationMs,
|
|
9818
9825
|
key: `AMQP_CONSUME ${queueName}`,
|
|
9819
9826
|
headers: normalizeAmqpHeadersForPayload(headers),
|
|
9820
9827
|
body: bodyMaterialization.value,
|
|
@@ -9826,7 +9833,7 @@ function wrapAmqplibConsumeHandler(onMessage: any, cfg: AmqplibPatchConfig, queu
|
|
|
9826
9833
|
entries: [{
|
|
9827
9834
|
actionId: aid ?? null,
|
|
9828
9835
|
request: requestPayload,
|
|
9829
|
-
t:
|
|
9836
|
+
t: completedAt,
|
|
9830
9837
|
}],
|
|
9831
9838
|
});
|
|
9832
9839
|
scheduleAmqpTraceFlush(cfg, amqpCtx, aid, consumeRid, rawTraceEvents, maskReq, captureScope);
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
process.env.REPRO_SDK_BACKGROUND_MAX_DEFER_MS = '0';
|
|
2
|
+
process.env.REPRO_SDK_BACKGROUND_IDLE_DELAY_MS = '0';
|
|
3
|
+
process.env.REPRO_SDK_BACKGROUND_BUSY_IDLE_DELAY_MS = '0';
|
|
4
|
+
process.env.TRACE_IDLE_FLUSH_MS = '0';
|
|
5
|
+
process.env.TRACE_LINGER_AFTER_FINISH_MS = '0';
|
|
6
|
+
|
|
7
|
+
const assert = require('node:assert/strict');
|
|
8
|
+
const http = require('node:http');
|
|
9
|
+
const { once } = require('node:events');
|
|
10
|
+
const { GenericContainer, Wait } = require('testcontainers');
|
|
11
|
+
const amqp = require('amqplib');
|
|
12
|
+
const { __reproTestHooks: hooks } = require('../dist');
|
|
13
|
+
const { flushIngestQueue } = require('../dist/ingest/client');
|
|
14
|
+
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
15
|
+
const deferred = () => {
|
|
16
|
+
let resolve;
|
|
17
|
+
const promise = new Promise(done => { resolve = done; });
|
|
18
|
+
return { promise, resolve };
|
|
19
|
+
};
|
|
20
|
+
async function within(promise, label) {
|
|
21
|
+
let timer;
|
|
22
|
+
try {
|
|
23
|
+
return await Promise.race([promise, new Promise((_, reject) => {
|
|
24
|
+
timer = setTimeout(() => reject(new Error(`Timed out: ${label}`)), 10000);
|
|
25
|
+
})]);
|
|
26
|
+
} finally { clearTimeout(timer); }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function main() {
|
|
30
|
+
const events = [], channels = [];
|
|
31
|
+
let rabbit, connection, release;
|
|
32
|
+
const sink = http.createServer(async (req, res) => {
|
|
33
|
+
const buffers = [];
|
|
34
|
+
for await (const chunk of req) buffers.push(chunk);
|
|
35
|
+
events.push(...(JSON.parse(Buffer.concat(buffers)).events || []));
|
|
36
|
+
res.writeHead(202); res.end('{}');
|
|
37
|
+
});
|
|
38
|
+
sink.listen(0, '127.0.0.1'); await once(sink, 'listening');
|
|
39
|
+
try {
|
|
40
|
+
rabbit = await new GenericContainer('rabbitmq:3.13-alpine')
|
|
41
|
+
.withEnvironment({ RABBITMQ_DEFAULT_USER: 'repro', RABBITMQ_DEFAULT_PASS: 'test' })
|
|
42
|
+
.withExposedPorts(5672).withWaitStrategy(Wait.forLogMessage('Server startup complete')).start();
|
|
43
|
+
connection = await amqp.connect(`amqp://repro:test@${rabbit.getHost()}:${rabbit.getMappedPort(5672)}`);
|
|
44
|
+
for (const mode of ['live', 'staging']) {
|
|
45
|
+
const sid = `S_amqp_timing_${mode}`;
|
|
46
|
+
const cfg = { tenantId: 'TENANT_timing', appId: 'APP_timing', appSecret: 'test',
|
|
47
|
+
privacy: { captureRaw: true, environment: 'dev' },
|
|
48
|
+
ingestBase: `http://127.0.0.1:${sink.address().port}`,
|
|
49
|
+
resolveContext: () => ({ sid, aid: `A_${mode}` }) };
|
|
50
|
+
const channel = await connection.createConfirmChannel(); channels.push(channel);
|
|
51
|
+
hooks.patchAmqplibChannelForTest(channel, cfg);
|
|
52
|
+
const queue = `timing-${mode}`;
|
|
53
|
+
await channel.assertQueue(queue, { durable: false });
|
|
54
|
+
const handled = deferred(), acknowledged = deferred(), gate = deferred(), started = deferred();
|
|
55
|
+
release = gate.resolve;
|
|
56
|
+
// Hold the real capture queue, not the broker or application callback.
|
|
57
|
+
hooks.scheduleSdkBackgroundWorkForTest(async () => {
|
|
58
|
+
started.resolve(); await gate.promise;
|
|
59
|
+
}, { priority: 'high' });
|
|
60
|
+
await within(started.promise, 'capture queue blocker');
|
|
61
|
+
let handlerStart, handlerEnd, publishEnd;
|
|
62
|
+
const input = { orderId: `order-${mode}`, lines: [{ sku: 'item', quantity: 3 }] };
|
|
63
|
+
const consumer = await channel.consume(queue, async message => {
|
|
64
|
+
handlerStart = Date.now();
|
|
65
|
+
assert.deepEqual(JSON.parse(message.content.toString()), input);
|
|
66
|
+
assert.equal(message.properties.headers['x-bug-session-id'], sid);
|
|
67
|
+
assert.equal(message.properties.headers['x-repro-capture-mode'], mode);
|
|
68
|
+
await sleep(60);
|
|
69
|
+
channel.ack(message);
|
|
70
|
+
handlerEnd = Date.now(); handled.resolve();
|
|
71
|
+
});
|
|
72
|
+
const publishStart = Date.now();
|
|
73
|
+
const options = { headers: { 'x-repro-capture-mode': mode }, persistent: false };
|
|
74
|
+
const result = hooks.runWithRequestContextForTest({ sid, aid: `A_${mode}`, captureScope: { liveCapture: mode === 'live' } },
|
|
75
|
+
() => channel.sendToQueue(queue, Buffer.from(JSON.stringify(input)), options, error => {
|
|
76
|
+
assert.ifError(error); publishEnd = Date.now(); acknowledged.resolve();
|
|
77
|
+
}));
|
|
78
|
+
assert.equal(typeof result, 'boolean', 'publish must preserve amqplib backpressure contract');
|
|
79
|
+
await within(Promise.all([handled.promise, acknowledged.promise]), 'broker confirm and consumer acknowledgement');
|
|
80
|
+
assert.equal(options.headers['x-bug-session-id'], undefined, 'caller options stay unchanged');
|
|
81
|
+
assert.equal(events.filter(e => e.session_id === sid && e.event_type === 'backend_request').length, 0);
|
|
82
|
+
await sleep(450);
|
|
83
|
+
const releasedAt = Date.now(); gate.resolve(); release = null;
|
|
84
|
+
const deadline = Date.now() + 10000;
|
|
85
|
+
let requests;
|
|
86
|
+
do {
|
|
87
|
+
await hooks.drainSdkBackgroundQueueForTest(); await flushIngestQueue();
|
|
88
|
+
requests = events.filter(e => e.session_id === sid && e.event_type === 'backend_request');
|
|
89
|
+
if (requests.length === 2) break;
|
|
90
|
+
await sleep(20);
|
|
91
|
+
} while (Date.now() < deadline);
|
|
92
|
+
assert.equal(requests.length, 2, 'exactly one publish and one consume, despite sendToQueue delegating to publish');
|
|
93
|
+
for (const [method, start, end] of [
|
|
94
|
+
['AMQP_SEND_TO_QUEUE', publishStart, publishEnd],
|
|
95
|
+
['AMQP_CONSUME', handlerStart, handlerEnd],
|
|
96
|
+
]) {
|
|
97
|
+
const event = requests.find(e => e.payload.request.method === method);
|
|
98
|
+
assert(event, `${mode}: missing ${method}`);
|
|
99
|
+
const request = event.payload.request;
|
|
100
|
+
assert(request.durMs <= end - start + 30,
|
|
101
|
+
`${mode} ${method}: ${request.durMs}ms includes capture queue time; business took ${end - start}ms`);
|
|
102
|
+
assert(request.durMs >= end - start - 10, 'duration must still include the async business handler');
|
|
103
|
+
const timestamp = Date.parse(event.event_ts);
|
|
104
|
+
assert(timestamp <= end + 30 && timestamp >= start,
|
|
105
|
+
`event time must be operation completion, not background delivery: ${timestamp}, ${end}`);
|
|
106
|
+
assert(timestamp < releasedAt - 400);
|
|
107
|
+
assert.deepEqual(request.body.value, input, 'timing correction must not lose payload');
|
|
108
|
+
}
|
|
109
|
+
await channel.cancel(consumer.consumerTag);
|
|
110
|
+
console.log(`${mode}: broker confirms and async handler finish before capture drain; timings and payload exact`);
|
|
111
|
+
}
|
|
112
|
+
// Exercise failure/return contracts with real delivered envelopes. The
|
|
113
|
+
// adapter catches deliberate handler failures just as an application would.
|
|
114
|
+
const sid = 'S_amqp_failures';
|
|
115
|
+
const cfg = { tenantId: 'TENANT_timing', appId: 'APP_timing', appSecret: 'test',
|
|
116
|
+
privacy: { captureRaw: true, environment: 'dev' },
|
|
117
|
+
ingestBase: `http://127.0.0.1:${sink.address().port}`,
|
|
118
|
+
resolveContext: () => ({ sid, aid: 'A_failures' }) };
|
|
119
|
+
const raw = await connection.createChannel(); channels.push(raw);
|
|
120
|
+
await raw.assertQueue('timing-contracts', { durable: false });
|
|
121
|
+
const gate = deferred(), started = deferred(); release = gate.resolve;
|
|
122
|
+
hooks.scheduleSdkBackgroundWorkForTest(async () => { started.resolve(); await gate.promise; }, { priority: 'high' });
|
|
123
|
+
await within(started.promise, 'failure capture queue blocker');
|
|
124
|
+
const observations = new Map(), completed = deferred();
|
|
125
|
+
const identity = { result: 'unchanged' }, failure = new Error('application failure');
|
|
126
|
+
const wrapped = hooks.wrapAmqplibConsumeHandlerForTest(message => {
|
|
127
|
+
const { scenario } = JSON.parse(message.content.toString());
|
|
128
|
+
const observation = { start: Date.now(), calls: 1, scenario };
|
|
129
|
+
observations.set(scenario, observation);
|
|
130
|
+
const finish = () => {
|
|
131
|
+
observation.end = Date.now();
|
|
132
|
+
if (scenario.endsWith('error')) throw failure;
|
|
133
|
+
return identity;
|
|
134
|
+
};
|
|
135
|
+
return scenario.startsWith('async') ? sleep(60).then(finish) : finish();
|
|
136
|
+
}, cfg, 'timing-contracts');
|
|
137
|
+
let handled = 0;
|
|
138
|
+
const consumer = await raw.consume('timing-contracts', message => {
|
|
139
|
+
const { scenario } = JSON.parse(message.content.toString());
|
|
140
|
+
const complete = () => { raw.ack(message); if (++handled === 4) completed.resolve(); };
|
|
141
|
+
try {
|
|
142
|
+
const value = wrapped(message);
|
|
143
|
+
if (scenario.startsWith('async')) {
|
|
144
|
+
assert.equal(typeof value.then, 'function');
|
|
145
|
+
value.then(result => {
|
|
146
|
+
assert.strictEqual(result, identity); complete();
|
|
147
|
+
}, error => { assert.strictEqual(error, failure); complete(); });
|
|
148
|
+
} else { assert.strictEqual(value, identity); complete(); }
|
|
149
|
+
} catch (error) { assert.strictEqual(error, failure); complete(); }
|
|
150
|
+
});
|
|
151
|
+
for (const scenario of ['sync-success', 'async-success', 'sync-error', 'async-error']) {
|
|
152
|
+
raw.sendToQueue('timing-contracts', Buffer.from(JSON.stringify({ scenario })), { headers: {
|
|
153
|
+
'x-bug-session-id': sid, 'x-bug-action-id': 'A_failures', 'x-repro-capture-mode': 'live',
|
|
154
|
+
} });
|
|
155
|
+
}
|
|
156
|
+
await within(completed.promise, 'handler return and error contracts');
|
|
157
|
+
const invalid = await connection.createConfirmChannel(); channels.push(invalid);
|
|
158
|
+
invalid.on('error', () => {});
|
|
159
|
+
hooks.patchAmqplibChannelForTest(invalid, cfg);
|
|
160
|
+
const rejected = deferred();
|
|
161
|
+
const rejectStart = Date.now(); let rejectEnd;
|
|
162
|
+
invalid.publish('missing-exchange-timing', 'route', Buffer.from('message'), {}, error => {
|
|
163
|
+
assert(error, 'broker must reject the nonexistent exchange');
|
|
164
|
+
rejectEnd = Date.now(); rejected.resolve();
|
|
165
|
+
});
|
|
166
|
+
await within(rejected.promise, 'broker rejection');
|
|
167
|
+
await sleep(450); gate.resolve(); release = null;
|
|
168
|
+
const deadline = Date.now() + 10000;
|
|
169
|
+
let requests;
|
|
170
|
+
do {
|
|
171
|
+
await hooks.drainSdkBackgroundQueueForTest(); await flushIngestQueue();
|
|
172
|
+
requests = events.filter(e => e.session_id === sid && e.event_type === 'backend_request');
|
|
173
|
+
if (requests.length === 5) break;
|
|
174
|
+
await sleep(20);
|
|
175
|
+
} while (Date.now() < deadline);
|
|
176
|
+
assert.equal(requests.length, 5, 'no retries/double captures on exceptions or broker channel close');
|
|
177
|
+
for (const event of requests) {
|
|
178
|
+
const request = event.payload.request;
|
|
179
|
+
const observation = request.method === 'AMQP_PUBLISH'
|
|
180
|
+
? { start: rejectStart, end: rejectEnd, scenario: 'broker-error' }
|
|
181
|
+
: observations.get(request.body.value.scenario);
|
|
182
|
+
assert(observation);
|
|
183
|
+
assert.equal(request.status, observation.scenario.endsWith('error') ? 500 : 200);
|
|
184
|
+
assert(request.durMs <= observation.end - observation.start + 30);
|
|
185
|
+
assert(Date.parse(event.event_ts) <= observation.end + 30);
|
|
186
|
+
}
|
|
187
|
+
await raw.cancel(consumer.consumerTag);
|
|
188
|
+
console.log('sync/async return and error identity preserved; broker rejection and failure timestamps exclude capture drain');
|
|
189
|
+
} finally {
|
|
190
|
+
release?.();
|
|
191
|
+
for (const channel of channels) await channel.close().catch(() => {});
|
|
192
|
+
if (connection) await connection.close();
|
|
193
|
+
await hooks.drainSdkBackgroundQueueForTest(); await flushIngestQueue();
|
|
194
|
+
sink.closeAllConnections(); await new Promise(resolve => sink.close(resolve));
|
|
195
|
+
if (rabbit) await rabbit.stop();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
main().catch(error => { console.error(error); process.exitCode = 1; });
|
|
@@ -25,7 +25,9 @@ async function main() {
|
|
|
25
25
|
const results = [];
|
|
26
26
|
try {
|
|
27
27
|
mongo = await new GenericContainer('mongo:7').withExposedPorts(27017).withWaitStrategy(Wait.forListeningPorts()).start();
|
|
28
|
-
|
|
28
|
+
const variants = ['off', 'live-raw', 'staging-raw', 'live-policy', 'staging-policy', 'live-policy-fallback', 'staging-policy-fallback', 'staging-policy-fault']
|
|
29
|
+
.filter(variant => !process.argv.includes('--raw-only') || !variant.includes('policy'));
|
|
30
|
+
for (const variant of variants) {
|
|
29
31
|
const mode = variant.split('-')[0];
|
|
30
32
|
child = fork(require.resolve('./fixtures/capture-latency-server'), [], {
|
|
31
33
|
env: { ...process.env, CAPTURE_TEST_MODE: mode,
|