Solace can't SEND while in WaitingForDNS - node.js

I'm trying send a message on a topic queue but the API returns
OperationError: Cannot perform operation SEND while in state WaitingForDNS
The URL can be pinged and it resolves to an IP address. I feel this message is misleading.
FWIW, I'm using Solace's Javascript API calling it from my Typescript code.
Below is code snippet. I've tried to remove irrelevant items such as the console logging. In short, it tests for a session already having been created, and if not, creates it using the Solace factory, then sets some event handlers which I think are irrelevant to this item
so I didn't include them. Because I don't catch any errors at connect() time, I presume it connected. Then when I try to send(), it suddenly is still waiting on the DNS. Or, at least, the error implies this.
class TopicPublisher {
private getSession() {
if (this.session == null) {
try {
this.log('Creating session for url=' + this.hosturl+' vpn='+this.vpn+' username='+this.username);
this.session = this.solace.SolclientFactory.createSession({
// solace.SessionProperties
url: this.hosturl,
vpnName: this.vpn,
userName: this.username,
password: this.pass,
});
// Set session event handlers
try {
this.session.connect();
} catch(error : any) {
this.log('Could not make connection to existing session. Error: '+error.toString());
this.session = null;
}
} catch (error: any) {
this.log(error.toString());
}
}
return this.session;
}
public publish(messageContent: any) {
var solaceMessage = this.getSolaceMessage(messageContent);
this.log('Publishing message "' + messageContent + '" to topic "' + this.topicName + '"...');
try {
// *************************
// This is where SEND fails
// *************************
this.getSession().send(solaceMessage);
this.log('Message published.');
} catch (error: any) {
this.log(error.toString());
}
};
}

An OperationError is thrown when you are attempting to execute a command on the session before it's actually up. What you can do here is only return this.session on session.on(solace.SessionEventCode.UP_NOTICE)
You can also see more info on this in the API docs and check out the note in the docs
Note: Before the session's state transitions to 'connected', a client
application cannot use the session; any attempt to call functions will
throw solace.OperationError.

Related

Exception in fetchPairData() : call revert exception in method getReserves()

I am trying to call the "fetchPairData" function (https://uniswap.org/docs/v2/SDK/fetcher/) but I am getting the following error.
Error: call revert exception (method="getReserves()", errorSignature=null, errorArgs=[null], reason=null, code=CALL_EXCEPTION, version=abi/5.1.2)
at Logger.makeError (C:\Users\*\Desktop\ProyectoTransaccion\v2\node_modules\#ethersproject\logger\lib\index.js:180:21)
at Logger.throwError (C:\Users\*\Desktop\ProyectoTransaccion\v2\node_modules\#ethersproject\logger\lib\index.js:189:20)
at Interface.decodeFunctionResult (C:\Users\*\Desktop\ProyectoTransaccion\v2\node_modules\#ethersproject\abi\lib\interface.js:289:23)
at Contract.<anonymous> (C:\Users\*\Desktop\ProyectoTransaccion\v2\node_modules\#ethersproject\contracts\lib\index.js:329:56)
at step (C:\Users\*\Desktop\ProyectoTransaccion\v2\node_modules\#ethersproject\contracts\lib\index.js:48:23)
at Object.next (C:\Users\*\Desktop\ProyectoTransaccion\v2\node_modules\#ethersproject\contracts\lib\index.js:29:53)
at fulfilled (C:\Users\*\Desktop\ProyectoTransaccion\v2\node_modules\#ethersproject\contracts\lib\index.js:20:58)
at processTicksAndRejections (internal/process/task_queues.js:93:5) {
reason: null,
code: 'CALL_EXCEPTION',
method: 'getReserves()',
errorSignature: null,
errorArgs: [ null ],
address: '0x80f836E71a6C92acebf6A49ad39038609c780070',
args: [],
transaction: {
data: '0x0902f1ac',
to: '0x80f836E71a6C92acebf6A49ad39038609c780070'
}
}
Relevant code:
const {ChainId, Token, TokenAmount, Fetcher, Pair, Route, Trade, TradeType, Percent} = require('#pancakeswap-libs/sdk');
const INPUT_TOKEN = new Token(ChainId.MAINNET,InputTokenAddr, 18);
const OUTPUT_TOKEN = new Token(ChainId.MAINNET, OutputTokenAddr, 18);
try {
pair = await Fetcher.fetchPairData(INPUT_TOKEN, OUTPUT_TOKEN, provider);
} catch (ex)
{
console.log("Debug.INPUT_TOKEN: " + JSON.stringify(INPUT_TOKEN));
console.log("Debug.OUTPUT_TOKEN: " + JSON.stringify(OUTPUT_TOKEN));
console.log("Debug.provider: " + JSON.stringify(provider));
console.log(ex)
pair = null;
}
Debug:
Debug.INPUT_TOKEN: {"decimals":18,"chainId":56,"address":"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"}
Debug.OUTPUT_TOKEN: {"decimals":18,"chainId":56,"address":"0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"}
Debug.provider: {"_isProvider":true,"_events":[],"_emitted":{"block":-2},"formatter":{"formats":{"transaction":{},"transactionRequest":{},"receiptLog":{},"receipt":{},"block":{},"blockWithTransactions":{},"filter":{},"filterLog":{}}},"anyNetwork":false,"_networkPromise":{},"_maxInternalBlockNumber":-1024,"_lastBlockNumber":-2,"_pollingInterval":4000,"_fastQueryDate":0,"connection":{"url":"https://bsc-dataseed.binance.org/"},"_nextId":45,"_eventLoopCache":{"detectNetwork":null,"eth_chainId":null},"_network":{"chainId":56,"name":"unknown"}}
I have verified that the swap works correctly in the pancakeswap web interface. It does not indicate route on the web, so it seems that it is a direct swap.
With other tokens the call returns what is expected. For example with the pair WBNB, BUSD.
I found for this error on another site with this comment
I faced the same issue and the problem was that I was trying to fetch
price for a pool that did not exist.
The pool exists. It has liquidity and it is also direct, it does not require a route.
The call revert exception happens when
the client doesn't receive a response
(no contract deployed on the address)
or when the contract code performs a revert.
pragma solidity ^0.8;
contract MyContract {
function foo() external view {
revert();
}
}
(Can also be when you're calling an undefined function and there's no fallback() in the contract)
Your question doesn't specify on which network you tried to perform the call, but there's no contract on the failing address on both mainnet and testnet.
So either your client app is trying to call this non-existing contract directly, or some contract in the chain of calls is trying to call it.
transaction: {
data: '0x0902f1ac',
to: '0x80f836E71a6C92acebf6A49ad39038609c780070'
}
me also facing the same issue for some tokens but i'm sure there is some issue in our end because some tokens have different routes for swapping. If token have different routes not direct swap that tokens will get same error.enter image description here

How can I catch exception from backend server using IMobileServiceSyncTable - InsertAsync?

I'm using IMobileServiceSyncTable from Azure Mobile App. In InsertAsync operation, on the backend server side, I had some validations for the data and, if that validations failure, I want throw Exception from the server side. I tried return InternalServerError(), throw HttpResponseException, but never worked on the client side. I debbuged the Post method in server side, the server throws the exception or return InternalServerError, but in the mobile client, don't occurs error.
Can anyone help me?
Here is my code on the client side:
public async Task<bool> AddPaciente(Paciente novoPaciente)
{
//other things
try
{
await _pacienteTable.InsertAsync(novoPaciente);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
Debug.WriteLine(e.StackTrace);
throw new WebException(AppResources.MensagemFalhaConexaoServidorAzure);
}
await SyncPaciente();
return true;
}
Here is my post method on the backend server side
// POST tables/Paciente
public async Task<IHttpActionResult> PostPaciente(Paciente novoPaciente)
{
//other things
if (paciente != null)
{
var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("Já existe um paciente com esse token cadastrado.")
};
//throw new HttpResponseException(responseMessage);
return InternalServerError(new Exception("Já existe um paciente com esse token cadastrado."));
}
}
You should listen to the response status code.
var response = await _pacienteTable.InsertAsync(novoPaciente);
if (response.IsSuccessStatusCode) {
var content = await response.Content.ReadAsStringAsync ();
}
else
{
//Here handle the error code
throw new WebException(AppResources.MensagemFalhaConexaoServidorAzure);
}
I'm using IMobileServiceSyncTable from Azure Mobile App. In InsertAsync operation, on the backend server side, I had some validations for the data and, if that validations failure, I want throw Exception from the server side.
For IMobileServiceSyncTable, you are dealing with An Offline Client which means that IMobileServiceSyncTable<T>.InsertAsync would directly insert data into the local SQLite store on your mobile client-side. Until you manually call MobileServiceClient.SyncContext.PushAsync(), then your local data store would be pushed to your mobile backend. For this approach, I would recommend you make sure that you need to validate the inputs before you saving them into the local data store, otherwise your push operations would fail, then you need to force your client user to adjust the existing inputs even after it has been successfully added before.
If you use An Online Client as follows, then both your approaches for throwing the exception would be immediately returned to your client.
var mobileClient= new MobileServiceClient("https://{your-mobile-app-name}.azurewebsites.net");
var _pacienteTable= mobileClient.GetTable<Paciente>();
await _pacienteTable.InsertAsync(novoPaciente);
Moreover, I used the following code line for catching the exception:
try
{
await table.InsertAsync(item);
}
catch (MobileServiceInvalidOperationException ex)
{
//TODO:
//await ex.Response.Content.ReadAsStringAsync(); //get detailed response content
}
catch (Exception e)
{
//TODO: other uncaught exception
}
Also, for the similar issue, you could leverage Fiddler to capture the network traces to narrow down this issue, make sure your client-side could correctly receive the relevant response.

Azure App Service Error 405 - The request could not be completed. (Method Not Allowed)

I'm working with Azure App Service .NET backend with a Xamarin.iOS app. I am able to successfully register a new user and I can see the user's details in the database. I have a custom ApiController, which handles the registration and the I'm able to save the details with a successful POST call.
However, when I try to log into the app, I get the following error:
{Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException: The request could not be completed. (Method Not Allowed)
Below is my code:
The RegistrationController in the backend which successfully makes a POST call
[MobileAppController]
[RoutePrefix("api/register")]
[AllowAnonymous]
public class RegisterController : ApiController
{
[HttpPost]
[Route("newuser")]
public HttpResponseMessage NewUser(RegistrationRequest request)
{
// Registration code in here
}
}
This is how I call this function on the client side:
public async Task<Result<UserProfile>> RegisterUser(RegistrationWrapper registrationrequest)
{
try
{
var registrationRequest = new JObject();
registrationRequest.Add("username", registrationrequest.username);
registrationRequest.Add("password", registrationrequest.password);
registrationRequest.Add("email", registrationrequest.email);
registrationRequest.Add("phone", registrationrequest.phone);
registrationRequest.Add("firstname", registrationrequest.firstname);
registrationRequest.Add("lastname", registrationrequest.lastname);
var result = await client.InvokeApiAsync("register/newuser", registrationRequest);
// Handle result here
}
catch (Exception ex)
{
return Result<UserProfile>.Failure(ex.Message + ex.StackTrace + ex.InnerException);
}
}
Custom AuthController which handles the login
This POST call fails with the error described above.
[MobileAppController]
[RoutePrefix("api/auth")]
public class AuthController : ApiController
{
public HttpResponseMessage Post(AuthenticationRequest credentials)
{
try
{
//Authentication code goes here
catch (Exception e)
{
Console.WriteLine("Ërror :" + e.Message);
Console.WriteLine(e.StackTrace);
return Request.CreateResponse(HttpStatusCode.InternalServerError, new
{
Stacktrace = e.StackTrace,
ErrorMessage = e.Message,
Credentials = credentials
});
}
}
How I invoke this function from the client side
async Task<Result<Account>> Login(string username, string password)
{
try
{
var credentials = new JObject();
credentials.Add("username", username);
credentials.Add("password", password);
var result = await client.InvokeApiAsync("auth", credentials);
//Handle result here
}
catch (Exception ex)
{
return Result<Account>.Failure(ex, ex.Message + ex.StackTrace);
}
}
}
I'm not sure why it's failing during the log in. Any ideas?
After trying tons of solutions found here on StackOverflow, the one that finally worked for me was this first answer found on a similar question.
It seems that the http POST call is redirected to https.
After enabling authentication on your App Service in the Azure portal, you need to change the url to https.
So I changed mine from this:
http//{my_site}.azurewebsites.net
To this:
https//{my_site}.azurewebsites.net
On the client side, and now used this new one to create my local sync tables.
Everything works as expected now.
The HTTP status code 405 is returned when an API endpoint is called with a wrong (Not Allowed) HTTP method. For example, if instead of a POST request the endpoint is called with a GET request.

Getting an error after trying to send notification through Firebase Cloud Functions (Android)

I am new to Firebase and to nodejs. I am trying to send a notification from one device to another using Firebase Cloud Functions.
This is the node.js code of sending the notification:
var functions = require('firebase-functions');
var admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/sendNotification/{notificationId}')
.onWrite(event => {
var regToken="fYRweeL8cic:APA91bH6Q_gyKKrLL...";
// Grab the current value of what was written to the Realtime Database.
var eventSnapshot = event.data;
var payload = {
data: {
title: eventSnapshot.child("title").val()
}
};
// Set the message as high priority and have it expire after 24 hours.
var options = {
priority: "high",
timeToLive: 60 * 60 * 24
};
admin.messaging().sendToDevice(regToken,payload,options)
.then(function(response){
console.log("Successfully sent message: ", response);
})
.catch(function(error){
console.log("Error sending message: ", error);
})
})
This is the code of adding the notification to the Realtime Database in order to trigger the function:
public void sendNotification(){
FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myRef = database.getReference("sendNotification");
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Toast.makeText(getApplicationContext(),
"sent", Toast.LENGTH_SHORT).show();
Map data = new HashMap();
data.put("title", "this is my title");
data.put("message", "this is the message");
myRef.push().setValue(data);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
I can see that the function was executed, but with the following error:
The notification appears in the database:
This is how the function appears in the console:
The problem is that the notification is not sent.
I'm getting this: {results:[{error: [Object]}] for some reason.
What can be the cause of this error?
EDIT: (Solution)
As suggested in the comments, I have used this: JSON.stringify(response) to get some more information. This was the response:
{"results":[{"error":{"code":"messaging/registration-token-not-registered","message":"The provided registration token is not registered. A previously valid registration token can be unregistered for a variety of reasons. See the error documentation for more details. Remove this registration token and stop using it to send messages."}}],"canonicalRegistrationTokenCount":0,"failureCount":1,"successCount":0,"multicastId":6051985890611026000}
The response was really clear, the token has changed. I have changed it to a valid token and it worked.
As suggested in the comments, I have used this: JSON.stringify(response) to get some more information. This was the response:
{"results":[{"error":{"code":"messaging/registration-token-not-registered","message":"The provided registration token is not registered. A previously valid registration token can be unregistered for a variety of reasons. See the error documentation for more details. Remove this registration token and stop using it to send messages."}}],"canonicalRegistrationTokenCount":0,"failureCount":1,"successCount":0,"multicastId":6051985890611026000}
The response was really clear, the token has changed. I have changed it to a valid token and it worked.

ServiceStack keep a long-live connection and send response asynchronously

I have a client app which monitors the changes in real-time by establishing a long-live HTTP connection to server.
In ASP.NET WebAPI, the server can take use PushStreamContent to keep the connection for a long time and send response once there is an update.
But in ServiceStack, seems there is no similar stuff.
I looked at the sample code of Different ways of returning an ImageStream
IStreamWriter.WriteTo method is only called once, and I can't use async IO operation to avoid blocking server thread.
Is there a way to send progressive response to client asynchronously?
here is sample code in WebAPI which does the job
public static async Task Monitor(Stream stream, HttpContent httpContent, TransportContext transportContext)
{
ConcurrentQueue<SessionChangeEvent> queue = new ConcurrentQueue<SessionChangeEvent>();
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
Action<SessionChangeEvent> callback = (evt) =>
{
queue.Enqueue(evt);
tcs.TrySetResult(null);
};
OnSessionChanged += callback;
try
{
using (StreamWriter sw = new StreamWriter(stream, new UTF8Encoding(false)))
{
await sw.WriteLineAsync(string.Empty);
await sw.FlushAsync();
await stream.FlushAsync();
for (; ; )
{
Task task = tcs.Task;
await Task.WhenAny(task, Task.Delay(15000));
if (task.Status == TaskStatus.RanToCompletion)
{
tcs = new TaskCompletionSource<object>();
SessionChangeEvent e;
while (queue.TryDequeue(out e))
{
string json = JsonConvert.SerializeObject(e);
await sw.WriteLineAsync(json);
}
task.Dispose();
}
else
{
// write an empty line to keep the connection alive
await sw.WriteLineAsync(string.Empty);
}
await sw.FlushAsync();
await stream.FlushAsync();
}
}
}
catch (CommunicationException ce)
{
}
finally
{
OnSessionChanged -= callback;
}
}
Writing to a long-running connection is exactly what Server Events does. You can look at the implementation for ServerEventsHandler or ServerEventsHeartbeatHandler to see it's implemented in ServiceStack.
Basically it just uses a custom ASP.NET IHttpAsyncHandler which can be registered at the start of ServiceStack's Request Pipeline with:
appHost.RawHttpHandlers.Add(req => req.PathInfo.EndsWith("/my-stream")
? new MyStreamHttpHandler()
: null);
Where MyStreamHttpHandler is a custom HttpAsyncTaskHandler, e.g:
public class MyStreamHttpHandler : HttpAsyncTaskHandler
{
public override bool RunAsAsync() { return true; }
public override Task ProcessRequestAsync(
IRequest req, IResponse res, string operationName)
{
//Write any custom request filters and registered headers
if (HostContext.ApplyCustomHandlerRequestFilters(req, res))
return EmptyTask;
res.ApplyGlobalResponseHeaders();
//Write to response output stream here, either by:
res.OuputStream.Write(...);
//or if need access to write to underlying ASP.NET Response
var aspRes = (HttpResponseBase)res.OriginalResponse;
aspRes.OutputStream...
//After you've finished end the request with
res.EndHttpHandlerRequest(skipHeaders: true);
return EmptyTask;
}
}
The ApplyCustomHandlerRequestFilters() and ApplyGlobalResponseHeaders() at the start gives other plugins a chance to validate/terminate the request or add any HTTP Headers (e.g. CorsFeature).
Have a look at ServerEvents. If I understood you right, this is what you are looking for.

Resources