How to configure request timeout and/or message TTL separately in MassTransit? - masstransit

My goal is to make request-response from API Gateway to microservice. I want request to be durable (not expiring), but response should be expiring (if no consumer will receive response within let's say 30s then it should expire). I am using RequestClient in API GW request handler (request scope). By default timeout is set by MassTransit to 30s and after this time request is removed from the queue. It's here in MassTransit code: https://github.com/MassTransit/MassTransit/blob/5e2a416384f005c392ead139f5c4af34511c56db/src/MassTransit/RequestTimeout.cs#L7.
First of I tried to set timeout in my request client like that
(using RabbitMQ):
// on request client level
cfg.AddRequestClient<ICreateGroupPayload>(RequestTimeout.None);
// and/or
// on .GetResponse() level
var response = await _createGroupClient.GetResponse<ICreateGroupResult>(new
{
Name = payload.Name,
Description = payload.Description
}, new CancellationToken(), RequestTimeout.None);
But neither of those options work. Still message has default 30s TTL.
Why it does not work as expected? Is message TTL something different here than RequestTimeout? If yes then why its 30s?
Do I have to configure message TTL manually in my case?
I want request client to automatically timeout after 30s even when request message will never expire. Is this built in, or I have to write some custom code for timeout, or maybe it's enough if I will pass expiring CancellationToken to .getResponse()?

You can configure a default timeout when registering the request client:
cfg.AddRequestClient<ICreateGroupPayload>(RequestTimeout.After(s:20));
And then, when sending the request, you can override the TimeToLive using a header in the message initializer:
var response = await _createGroupClient.GetResponse<ICreateGroupResult>(new
{
Name = payload.Name,
Description = payload.Description,
__TimeToLive = TimeSpan.FromYears(1)
}, httpContext.CancellationToken);
That will replace the default value (which matches the request timeout, by default) with the new value.

Related

Jmeter Websocket socket.io request not received in Nestjs

I have a Nestjs server i am able to send connection request using the below code
const io = require('socket.io-client');
const socket = io("http://localhost:3000", {
transports: ["websocket"],
pingTimeout: 10000,
pingInterval: 25000,
});
const someDelay = 10;
socket.on('connect', function () {
console.log('connected...');
})
The request is received successfully. The issue is when sending the same request using JMETER it never reaches the server
after opening the connection i am sending a request with token and it never reaches server
It doesn't give any error but never reaches server
Following is the error on request-response-sampler
Because you're only opening a connection, you're not sending any "request", consider adding either a single-write sampler or request-response sampler and you should see the request "reaching" the server.
See Basic request-response sample.jmx example test plan and JMeter WebSocket Samplers - A Practical Guide for more information.

API Gateway Websockets not sending to all clients

I'm using websockets with API Gateway and dynamoDB to maintain all connection IDs.
What I'm trying to do is when a new message comes in, a message is sent to all connected clients.
For example, inside the $default route a message will be received from the client. I'm then querying dynamo to get all connected ids and sending that message.
Querying dynamo:
const params = {
TableName: process.env.CONNECTIONS_TABLE,
IndexName: process.env.CONNECTIONS_COMPANY_INDEX,
KeyConditionExpression: "company = :company",
ExpressionAttributeValues: {
":company": data.company,
},
};
const response = await dynamodb.query(params).promise();
response.Items.forEach(async (item) => {
try {
await apig
.postToConnection({
ConnectionId: item.connectionId,
Data: JSON.stringify(data),
})
.promise();
} catch (e) {
if (e.statusCode === 410) {
console.log(e)
}
}
});
The issue I'm having is that it's only received on the clients after the second attempt. So the client sends a message "123" (the above code is run successfully and I've verified it's getting all connections, no errors) but nothing is received by the client. The client sends another message - "456", now both clients will receive the "123" message.
Any ideas why this would happen? I'd expect that each message sent, would receive the same message to all connected clients, not delayed and always one behind.
Thank you!
i faced with exact same issue. Then i just Remove integration response from the API gateway and leave the function return {}
https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-routes-integrations.html#apigateway-websocket-api-overview-integrations-differences
In the HTTP protocol, in which requests and responses are sent
synchronously; communication is essentially one-way. In the WebSocket
protocol, communication is two-way. Responses are asynchronous and are
not necessarily received by the client in the same order as the
client's messages were sent. In addition, the backend can send
messages to the client.

Making a test fail if an HTTP request fails in Cypress

I'm testing an app with Cypress, and the tests go against real HTTP servers. I'm not stubbing the HTTP requests.
Is there a way to make my tests fail if any of the HTTP requests fail?
There is a solution that seems ok in this other SO post, but I wonder if there is a more proper solution. In my case, I'm not always converting all HTTP errors into invocations to console.error.
You can listen to the request using cy.intercept() & check the status code etc.
Ref : https://docs.cypress.io/api/commands/intercept.html#Intercepting-a-response
Example 1 :
// Wait for intercepted HTTP request
cy.intercept('POST', '/users').as('createUser')
// ...
cy.wait('#createUser')
.then(({ request, response }) => {
expect(response.statusCode).to.eq(200)
})
Example 2 :
// Listen to GET to comments/1
cy.intercept('GET', '**/comments/*').as('getComment')
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.network-btn').click()
// https://on.cypress.io/wait
cy.wait('#getComment').its('response.statusCode').should('be.oneOf', [200, 304])

Axios : put on hold requests

I have the following axios interceptor.
It checks the validity of the stored token. If not valid, a request is fired to retrieve and store the refreshed token.
axios.interceptors.request.use(async config =>
if(checkValidity(localStorage.getItem('token')) === false) {
const response = await axios.get('http://foobar.com/auth/refresh');
localStorage.setItem('token', response.headers['token']);
config = getConfigFromResponse(response);
}
return config;
});
It works great. The problem is that if I have many requests with invalid token then many requests to http://foobar.com/auth/refresh are done to refresh it.
Is it possible to put all the requests in an array and fire them after when the refresh is done ?
The idea is to avoid catching 401 errors and replaying the request : this is why I want to "save" the requests while the token is being retrieved and then fire them when the token is ready.

How to prioritize the reponse over request in ASP.NET Web Api

I have a code that looks something like this:
class SomeController {
HttpClient client = new HttpClient();
public Task<dynamic> SomeAction() {
Task.Run<dynamic>(() => {
var response = client.GetAsync(new Uri(someUrl));
return response.ReadAsAsync<dynamic>().Result;
});
}
}
Now, I call this api with many requests (around 300) and the 'someUrl' returns the response after about 200ms.
After adding some console logs I can see a behavior:
All the 200 requests arrive and request the someUrl resource
The first 2-3 requests to someUrl are handled and returned properly
Other responses are waiting for all the 300 requests to arrive and only then they are returned back...
I have heard that there is no prioritization of responses over incoming requests in situations like these but it seems weird to me. It seems like the requests coming to my server and the responses that are coming from the someUrl are on the same queue and until all the requests are sent no response can be handled.
Anyone else encountered this situation? Anyone knows how to handle it properly?
Thanks!

Resources