Why can't I defer sending a message for a one-way client - rebus

What is the rationale behind the following exception when trying to Defer the sending of a message on a one-way client:
System.InvalidOperationException "Cannot use ourselves as timeout manager because we're a one-way client"

A one-way client is a Rebus client that is not capable of receiving messages, so it has no input queue.
The way await bus.Defer(...) works, is by sending a message with some special headers to a "timeout manager", which by default is the endpoint that defers the message.
But since a one-way client has no input queue, it has no place to send the deferred message to.
You can make a one-way client defer messages by configuring an external timeout manager like this:
Configure.With(...)
.(...)
.Options(o => o.UseExternalTimeoutManager(anotherQueue))
.Start();
which will then cause the client to send the deferred message to that queue.
Moreover, you would have to manually set the rbs2-defer-recipient header to some other input queue, so that the timeout manager knows where to send the message when it is time to be consumed(*).
I hope that explains it :) please let me know if it is not clear.
*) This is actually not the case with Rebus 4, because bus.Defer uses the normal endpoint mappings to route messages.

If Rebus.AzureServiceBus is used there is more simple (or hacky) way to send delayed messages.
You have to specify 2 headers: rbs2-deferred-until and rbs2-defer-recipient and call Publish method like in the example.
var deferredUntil = DateTimeOffset.UtcNow.AddDays(1);
var headers = new Dictionary<string, string>();
headers.Add(Headers.DeferredUntil, deferredUntil.ToString("O", CultureInfo.InvariantCulture));
headers.Add(Headers.DeferredRecipient, #"Rebus requires this ¯\_(ツ)_/¯");
await bus.Publish(new SomeMessage(), headers);
Note: rbs2-defer-recipient is required by Rebus so any dummy values are okay.
Be careful, it looks like a workaround so it may not work after Rebus.AzureServiceBus update. It works for me in 5.0.1.

Related

httr authentication login/password in "xtb" API

I need to authenticate and get prices using this api
I have no experience with api so my attempt to login gives an error
login <- "vikov98261#jesdoit.com"
pass <- "QazQaz123"
library(httr)
resp <- POST("xapi.xtb.com",
body=list(userId = login,
password = pass) )
Error in curl::curl_fetch_memory(url, handle = handle) :
Failed to connect to xapi.xtb.com port 80: Timed out
Can someone show me how to do it right.
I would like an example of how the login request works.
And also I would like an example of how to get the prices of any currency
Their API documentation uses WebSocket syntax, so I assume xapi.xtb.com may only be used by the clients. I, for once, only managed to get WebSocket to work.
In order to make this work in r you would need a WebSocket client library for r, such as websocket. Once you have that:
1. Define connection
ws <- WebSocket$new("wss://ws.xtb.com/demo")
2. Log in
WebSocket clients work with events. The 'open' event is generated once the connection is established and the 'message' events are generated when messages are received. You need to write handlers for them to orchestrate the way you want to use the XTB API.
The first event will be 'open', so use that to send the login command.
ws$onOpen(function(event) {
ws$send({
"command":"login",
"arguments": {
"userId":"1000",
"password":"PASSWORD",
"appId":"test",
"appName":"test"
}
})
})
3. Your logic
The response to your login command will trigger a 'message' event, the output of which you will need to handle in your code.
ws$onMessage( <your-code-goes-here> )
The easiest way would probably be to send new commands based on what is the structure of the received message, although it can get really complicated with many commands.
4. Connect
After all handles have been defined, don't forget to connect.
ws$connect()

Firebase push notifications always arrive as an empty message

I have been trying to get push notifications working using firebase. So far I have got as far as successfully sending an empty message "tickle". The problem is adding the message payload seems to have no affect on what the client receives. That is the service worker just sees it as another empty message.
I started by going through googles guide here - https://developers.google.com/web/ilt/pwa/introduction-to-push-notifications
After going through how to send an empty message it says the message payload must be encrypted and suggests using an existing library to do it. To quote - "As with anything related to encryption, it's usually easier to use an actively maintained library than to write your own code".
I tried to use web-push-php which is one of the libraries recommended by googles guide. After having trouble with that i discovered web-php-push doesn't actually support firebase.
Looking on here i find examples that look really simple and don't event encrypt the message payload. It is simply sent in plain json. Doing this has no affect and the receiving end still thinks it's an empty message. See my code below.
I am at a complete loss with this and i'm confused why googles guide says the message data must be encrypted but there are countless examples on SO where it is just send in plain json text.
This is what i am posting from my server to the end point.
POST https://fcm.googleapis.com/fcm/send Authorization: key=[my server
key] Content-Type: application/json {"priority":10,"to":"[subscriber
id]","notification":{"body":"test body","title":"test title"}}
Here is my event listener in my service-worker.js
self.addEventListener('push', function(e) {
var body;
if (e.data) {
body = e.data.text();
} else {
body = "No message "+JSON.stringify(e);
}
var options = {
body: body
};
e.waitUntil(
self.registration.showNotification('Launtel Residential', options)
);
});
When i run the post request above the push notification occurs and triggers the service worker 'push' event as expected but no message data is present. e.data returns null. The 'e' object always just contains a flag set to true. e.isTrusted==true

Not able to send data on reply channel using tcp-outbound-gateway with ActiveMQ

My Requirement is to get data from TCP, after getting the data from TCP convert into java object and send on ActiveMQ. Post that after doing some processing need to send the acknowledgement/response code on same channel on TCP.
To fulfill this requirement I am using tcp-outbound-gateway as bidirectional communication is required.
Problem is I am not able to send acknowledgement with ActiveMQ. If I comment out ActiveMQ part and write a dummy string on replyChannel it is visible, but the moment I send the object on Active MQ queue it is giving me a message "null reply received for nothing to send".
I am using a new queue to get the acknowledgement and trying to put the response on reply channel of tcp-outbound-gate, but error message is no output-channel or replyChannel header available.
I got the MessageHeaders details via Incoming message and sending it via queue to use copyHeader. I am able to set the headers and see paylod in Message object, verified the same by applying Interceptos on reply channel, but still getting the same error no output-channel or replyChannel header available.
Code is :
<int:gateway id="gw" default-reply-channel="replyChannel" default-reply-timeout="10000" service-interface= "com.telnet.core.integration.connection.ParseTcpConfiguration$SimpleGateway"
default-request-channel="${server.inboundChannel}"/>
<int:channel id="telnetLandingChannel" />
<ip:tcp-connection-factory id="serverFactory" type="server" host="${server.host}" port="${server.port}" single-use="false"
serializer="${server.serializer}" deserializer="${server.serializer}" task-executor="serverFactoryTaskExecutor"/>
<ip:tcp-inbound-gateway id="serverInboundAdpater" request-channel="telnetLandingChannel" reply-channel="replyChannel"
connection-factory="serverFactory" error-channel="errorChannel" reply-timeout="1000000" auto-startup="false"/>
<int:channel id="replyChannel"></int:channel>
<beans:bean id="acknowledgementHandler" class= "com.telnet.core.integration.AcknowledgementHandler">
</beans:bean>
<int:channel id="incidentDispatchMessageChannel" datatype="${incident.interaction.dispatch.response.datatype}"></int:channel>
<int-jms:message-driven-channel-adapter id="incidentDispatchMessageChannelAdapter" error-channel="errorChannel"
connection-factory="mqConnectionFactory"
destination-name="${incident.processing.tcp.dispatch.response.queues}"
channel="incidentDispatchMessageChannel"/>
<int:transformer id="incidentMessageActivator"
input-channel="incidentDispatchMessageChannel"
output-channel="replyChannel"
ref="acknowledgementHandler" method="incidentAck">
</int:transformer>
public Message incidentAck(final DefaultIncidentAcknowledgeMessage defaultIncidentAcknowledgeMessage){
MessageHeaders ms = (MessageHeaders)defaultIncidentAcknowledgeMessage.getProperties().get("MessageHeader");
Message<String> message = MessageBuilder.withPayload("1").copyHeaders(ms).build();
return message;
}
Need to see your Integration configuration though, but let me guess that you are loosing TemporaryReplyChannel object in the replyChannel header because it isn't Serializable. Consider to use:
<int:header-enricher>
<int:header-channels-to-string/>
</int:header-enricher>
somewhere before sending to the ActveMQ.
See Reference Manual for more information.
UPDATE
Looks like this is a continuation of Receive the acknowledgement from TCP server to our application using spring Integration. And I see you still use the same replyChannel for many places. That isn't going to work properly. The replyChannel header from the gateway can accept only one reply. Even if we figure out what to do with the reply from ActiveMQ, the TemporaryReplyChannel will be fulfilled with the reply from the TCP Outbound Gateway.
If I understand you correctly, alongside with the reply from the TCP you need also get some message from ActiveMQ. And send everything as a reply to the gateway call. For this purpose I suggest you to consider to use Aggregator and figure out some custom correlation strategy to match the reply from TCP to that acknowledge from the ActiveMQ. After aggregation you really can just use the existing replyChannel header to reply to the gateway.

Asynchronous WebSockets in Winhttp Windows 8

I want just to add WebSockets to my app that uses WinHTTP in async mode.
When I need a WebSocket I call the following.
Before sending request:
WinHttpSetOption(context->hRequest, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET, NULL, 0);
In WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE:
appContext->pIoRequest->hWebSocketHandle = WinHttpWebSocketCompleteUpgrade(appContext->hRequest, NULL);
WinHttpWebSocketReceive(appContext->pIoRequest->hWebSocketHandle, appContext->pszOutBuffer,RESPONSE_BUFFER_SIZE, NULL, NULL);
all without errors.
Now I see in Fiddler that the server sends some data to my WebSocket but there is no WINHTTP_CALLBACK_STATUS_READ_COMPLETE triggered.
Any ideas why this is? How can I read asynchronously from my WebSocket? Sending data to the WebSocket works well.
Omg! I found how its work!
You MUST call additional WinHttpSetStatusCallback to set WebSocket callback for WebSocketHandle returned in WinHttpWebSocketCompleteUpgrade and this callback MUST differ then that from call WinHttpWebSocketCompleteUpgrade was made!
It is no possible to set a context pointer by WinHttpSetOption with WINHTTP_OPTION_CONTEXT_VALUE flag! Its not work. dwContext In WebSocketCallback has wrong data. Call to WinHttpQueryOption in WebSocketCallback return wrong context data. I think that is a BUG in Windows 8.1. I write my own handler to connect my context with WebSocketHandle.
All of this is NOT documented in MSDN! Most of all, I did not google any info about async winhttp websocket usage... So, I am the first=) I will be very glad if my research will help you!
It seems websockets do not get PING and PONG messages to the callback!

External use of Meteor method? (to receive SMS from Nexmo)

In my Meteor application I want to receive text messages through Nexmo. How do I create the callback function? I'm thinking of something like
Meteor.methods
'receive_sms': (values) ->
console.log values
But http://hitchticker.meteor.com/receive_sms doesn't really work of course. I can see my method is working when I do Meteor.call('receive_sms', 'test') in my browser, but the network debugger is not really giving me a lot of useful information. The Meteor docs aren't very helpful either.
How do I access the method from elsewhere?
Iron Router and then server side routes. Something like:
Router.route('/download/:file', function () {
// NodeJS request object
var request = this.request;
// NodeJS response object
var response = this.response;
this.response.end('file download content\n');
}, {where: 'server'});
In order to receive sms from nexmo you should make the callback (incoming url) available over the internet. Nexmo won’t be able to call localhost to send the incoming sms messages.
Here are some resources to tunnel request over the internet to localhost.
https://ngrok.com/
http://localtunnel.me/
https://pagekite.net/

Resources