Outgoing connection stream closed - akka-http

I have an actor with the behaviour:
def receive: Receive = {
case Info(message) =>
val res = send("INFO:" + message)
installAckHook(res)
case Warning(message) =>
val res = send("WARNING:" + message)
installAckHook(res)
case Error(message) =>
val res = send("ERROR:" + message)
installAckHook(res)
}
private def installAckHook[T](fut: Future[T]): Unit = {
val answerTo = sender()
fut.onComplete {
case Success(_) => answerTo ! "OK"
case Failure(ex) => answerTo ! ex
}
}
private def send(message: String): Future[HttpResponse] = {
import context.system
val payload: Payload = Payload(text = message,
username = slackConfig.username, icon_url = slackConfig.iconUrl,
icon_emoji = slackConfig.iconEmoji, channel = slackConfig.channel)
.validate
Http().singleRequest(RequestBuilding.Post(slackConfig.hookAddress, payload))
}
And a test
val actorRef = system.actorOf(SlackHookActor.props(SlackEndpointConfig(WebHookUrl,iconEmoji = Some(":ghost:"))))
actorRef ! Error("Some error message")
actorRef ! Warning("Some warning message")
actorRef ! Info("Some info message")
receiveN(3)
and in the afterAll() method I do a shutdown on the actor system using TestKit.
It works, the request makes it to the server, but there are errors from the akka streams part:
[ERROR] [06/26/2015 11:34:55.118] [SlackHookTestingSystem-akka.actor.default-dispatcher-10] [ActorSystem(SlackHookTestingSystem)] Outgoing request stream error (akka.stream.AbruptTerminationException)
[ERROR] [06/26/2015 11:34:55.120] [SlackHookTestingSystem-akka.actor.default-dispatcher-13] [ActorSystem(SlackHookTestingSystem)] Outgoing request stream error (akka.stream.AbruptTerminationException)
[ERROR] [06/26/2015 11:34:55.121] [SlackHookTestingSystem-akka.actor.default-dispatcher-8] [ActorSystem(SlackHookTestingSystem)] Outgoing request stream error (akka.stream.AbruptTerminationException)
Seems like since I have a Future completed the outgoing connection should be already closed, so is this a bug or am I missing sth?

You need to also shut down the http connection pools, something like
Http().shutdownAllConnectionPools().onComplete{ _ =>
system.shutdown()
}
Maybe the akka http testkit provides some helpers

Related

Failed to send message using MQ

On my server side I deployed RabbitMq message middleware using docker and it works perfectly. But I combine it with asp.net core, it can't send the message successfully.
package:https://www.nuget.org/packages/RabbitMQ.Client/
I goole some answers:
RabbitMQ adopts the message response mechanism, that is, after the
consumer receives a message, it needs to send a response, and then
RabbitMQ will delete the message from the queue. If the consumer has
an exception during the consumption process, the connection is
disconnected and no response is sent. Then RabbitMQ will redeliver the
message
So I modified my code
//message received event
consumer.Received += (ch, ea) =>
{
var message = Encoding.UTF8.GetString(ea.Body);
Console.WriteLine($"Received the news: {message}");
Console.WriteLine($"received the message[{ea.DeliveryTag}] delay 10s to send receipt");
Thread.Sleep(10000);
//Confirm that the message has been consumed
channel.BasicAck(ea.DeliveryTag, false);
Console.WriteLine($"Receipt sent[{ea.DeliveryTag}]");
};
Still failed to send and no response, please help me, thank you!
I have a demo of sending a message, you may refer to it, it may be helpful.
Controller:
[Route("test")]
public void Index()
{
try
{
var factory = new ConnectionFactory();
factory.VirtualHost = "/";
factory.HostName = "localhost";
factory.Port = 5672;
factory.UserName = "guest";//Default username guest
factory.Password = "guest";//Default password guest
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "test",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);
string message = "Hello World!";
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "",
routingKey: "test",
basicProperties: null,
body: body);
Console.WriteLine(" [x] Sent {0}", message);
}
Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
}
catch (Exception ex)
{
Console.Write(string.Format("RabbitMQ connection error :{0}\n", ex.ToString()));
}
}
For the sake of convenience, I did not configure the connection information of rabbitmq here. I wrote it directly into the method, you can do it yourself.
Resullt:

NServiceBus MSMQ, How to Stop message transfer to Error Queue

I am using NServiceBus for a proof of concept. I am using it with MSMQ. I Have a Web Application which send a message. This message will be handled by a subscriber or message handler. When i shutdown the message handler, message will be send to Error Queue after few retries.
I don't want to send it to error queue, i want to keep message in Input queue as long as Handler is again online and process this message automatically from input queue. If message can not be processed from handler due to any error, it must transfer message to error queue.
Here is my configuration in MVC application Global.asax
private void ConfigureServiceBus()
{
var endpointConfiguration = new EndpointConfiguration("Samples.Mvc.Endpoint");
endpointConfiguration.UseSerialization<JsonSerializer>();
endpointConfiguration.UsePersistence<InMemoryPersistence>();
endpointConfiguration.UseTransport<MsmqTransport>();
endpointConfiguration.SendFailedMessagesTo("error");
endpointConfiguration.AuditProcessedMessagesTo("audit");
var recoverability = endpointConfiguration.Recoverability();
recoverability.Delayed(
delayed =>
{
delayed.NumberOfRetries(2);
delayed.TimeIncrease(TimeSpan.FromSeconds(2));
});
endpointConfiguration.EnableInstallers();
endpoint = Endpoint.Start(endpointConfiguration).GetAwaiter().GetResult();
//var endpointInstance = Endpoint.Start(endpointConfiguration).ConfigureAwait(false);
var mvcContainerBuilder = new ContainerBuilder();
mvcContainerBuilder.RegisterInstance(endpoint);
// Register MVC controllers.
mvcContainerBuilder.RegisterControllers(typeof(MvcApplication).Assembly);
var mvcContainer = mvcContainerBuilder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(mvcContainer));
}
This is the part in Controller where i send message to endpoint.
[HttpPost]
public async Task<ActionResult> Contact(ContactModel c)
{
if (ModelState.IsValid)
{
try
{
var message = new ContactMessage()
{
Comment = c.Comment,
Email = c.Email,
FirstName = c.FirstName,
LastName = c.LastName,
TransectionId = Guid.NewGuid()
};
await endpoint.Send("Samples.Mvc.Endpoint", message).ConfigureAwait(false);
return View("Success");
}
catch (Exception ex)
{
return View("Error");
}
}
return View();
}
My goal is to keep unhandled messages in input queue as long as message handler is not back on work. currently if message handler is down, it send messages after retries to Error Queue.
I am using NServiceBus 6.x
thanks in advance

Disassociated exception in Akka.Remoting

Using Akka.net I am trying to implement simple scenario.
I have created 2 servers and 1 client, where Servers receives the messages sent from client and processes it.
Setup works fine sometimes and sometimes it gives following error, I am not able to figure out the cause:
**
No response from remote. Handshake timed out or transport failure detector triggered.
Cause: Unknown
Association with remote system akka.tcp://RemoteFSharp#172.27.**.94:8777 has
failed; address is now gated for 5000 ms. Reason is: [Akka.Remote.EndpointDisass
ociatedException: Disassociated
at Akka.Remote.EndpointWriter.PublishAndThrow(Exception reason, LogLevel leve
l)
at Akka.Remote.EndpointWriter.Unhandled(Object message)
at Akka.Actor.ActorCell.<>c__DisplayClass109_0.<Akka.Actor.IUntypedActorConte
xt.Become>b__0(Object m)
at Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
at Akka.Actor.ActorCell.ReceiveMessage(Object message)
at Akka.Actor.ActorCell.AutoReceiveMessage(Envelope envelope)
at Akka.Actor.ActorCell.Invoke(Envelope envelope)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Akka.Actor.ActorCell.HandleFailed(Failed f)
at Akka.Actor.ActorCell.SystemInvoke(Envelope envelope)]
**
Client Config:
akka {
log-dead-letters-during-shutdown = off
actor {
handshake-timeout = 600 s
serializers {
wire = "Akka.Serialization.WireSerializer, Akka.Serialization.Wire"
}
serialization-bindings {
"System.Object" = wire
}
provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
}
remote {
helios.tcp {
maximum-frame-size = 20000000b
tcp-keepalive = on
transport-class =
"Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote"
transport-protocol = tcp
port = 8760
hostname = 172.27.**.94
}
}
log-remote-lifecycle-events = INFO
}
Server Config :
akka {
log-dead-letters-during-shutdown = off
actor {
handshake-timeout = 600 s
serializers {
wire = "Akka.Serialization.WireSerializer, Akka.Serialization.Wire"
}
serialization-bindings {
"System.Object" = wire
}
provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
}
remote {
helios.tcp {
maximum-frame-size = 20000000b
tcp-keepalive = on
transport-class =
"Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote"
transport-protocol = tcp
port = 8777
hostname = 172.27.**.94
}
}
log-remote-lifecycle-events = INFO
}
Also I am using Newtonsoft.Json for serialization as follows:
let CreateEmployeeActor (system: ActorSystem) actorName =
(spawn system actorName
(fun mailbox ->
let rec loop (count: int)=
actor {
let! message = mailbox.Receive()
let sender = mailbox.Sender()
let deserializedEmailData = JsonConvert.DeserializeObject<EmployeeActorMsgs> (message)
match deserializedEmailData with
| InItEmployee ->
//Some Logic
}
loop (0)
))

How to consume an object from azure service bus topic subscription

I got this error upon receving an object from a subscription in azure service bus.
An exception of type 'System.Runtime.Serialization.SerializationException' occurred in System.Runtime.Serialization.dll but was not handled in user code
I've tried some deserialization code but nothing works.
This is how I send a message. Please tell me how to receive it.
public void SendMessage()
{
BrokeredMessage message = new BrokeredMessage(new TestMessage() {
MsgNumber = 1, MsgContent = "testing message" }, new DataContractSerializer(typeof(TestMessage)));
// Send message to the topic
TopicClient topicClient = TopicClient.CreateFromConnectionString(cn, topicNamespace);
topicClient.Send(message);
}
public string ReceiveMessage(){
//??????
}
To receive a single message, you need to get the SubscriptionClient :
public void ReceiveMessage(string connectionString, string topicPath, string subscriptionName)
{
var subscriptionClient = SubscriptionClient.CreateFromConnectionString(connectionString, topicPath, subscriptionName);
var brokeredMessage = subscriptionClient.Receive();
var message = brokeredMessage.GetBody<TestMessage>();
}

creating GCM client app, asynctask fails

While creating a GCM client application, asynctask is giving compilation errors.
OnCreate we are calling registerBackgrouod which will check whether gcm instance is running or not, if not create one.
But asyntask is giving error : "Asynctask cannot be resolved to a type"
private void registerBackground() {
new AsyncTask() {
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
msg = "Device registered, registration id=" + regid;
// You should send the registration ID to your server over HTTP,
// so it can use GCM/HTTP or CCS to send messages to your app.
// For this demo: we don't need to send it because the device
// will send upstream messages to a server that echo back the message
// using the 'from' address in the message.
// Save the regid - no need to register again.
setRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
}
return msg;
}
protected void onPostExecute(String msg) {
mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
As already observed by the AlexBcn, and according to the documentation of AsyncTask, you would pass to the AsyncTask three types as param. Because you want to return the payload of the GCM push notification as a String, you would invoke AsyncTask<Void, Void, String>
So the correct code snippet of GCM client is:
private void registerInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regid;
// You should send the registration ID to your server over HTTP, so it
// can use GCM/HTTP or CCS to send messages to your app.
// For this demo: we don't need to send it because the device will send
// upstream messages to a server that echo back the message using the
// 'from' address in the message.
// Persist the regID - no need to register again.
storeRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
// Require the user to click a button again, or perform
// exponential back-off.
}
return msg;
}.execute(null, null, null);
}
This is because of the params you pass in to Async task.
For further help:
I recently uploaded the fully functional GCM java client to my Github Account:
GCM Android Client
It has got both server and client implementation.