HTTP 502 bad gateway c# with wamp on poloniex - c#

I want to retrieve ticks from Poloniex in real time. They use wamp for that. I installed via nugget WampSharp and found this code :
static async void MainAsync(string[] args)
{
var channelFactory = new DefaultWampChannelFactory();
var channel = channelFactory.CreateMsgpackChannel("wss://api.poloniex.com", "realm1");
await channel.Open();
var realmProxy = channel.RealmProxy;
Console.WriteLine("Connection established");
int received = 0;
IDisposable subscription = null;
subscription =
realmProxy.Services.GetSubject("ticker")
.Subscribe(x =>
{
Console.WriteLine("Got Event: " + x);
received++;
if (received > 5)
{
Console.WriteLine("Closing ..");
subscription.Dispose();
}
});
Console.ReadLine();
}
but no matter at the await channel.open() I have the following error : HHTP 502 bad gateway
Do you have an idea where is the problem
thank you in advance

The Poloniex service seems not to be able to handle so many connections. That's why you get the HTTP 502 bad gateway error. You can try to use the reconnector mechanism in order to try connecting periodically.
static void Main(string[] args)
{
var channelFactory = new DefaultWampChannelFactory();
var channel = channelFactory.CreateJsonChannel("wss://api.poloniex.com", "realm1");
Func<Task> connect = async () =>
{
await Task.Delay(30000);
await channel.Open();
var tickerSubject = channel.RealmProxy.Services.GetSubject("ticker");
var subscription = tickerSubject.Subscribe(evt =>
{
var currencyPair = evt.Arguments[0].Deserialize<string>();
var last = evt.Arguments[1].Deserialize<decimal>();
Console.WriteLine($"Currencypair: {currencyPair}, Last: {last}");
},
ex => {
Console.WriteLine($"Oh no! {ex}");
});
};
WampChannelReconnector reconnector =
new WampChannelReconnector(channel, connect);
reconnector.Start();
Console.WriteLine("Press a key to exit");
Console.ReadKey();
}
This is based on this code sample.

Get rid of the Console.WriteLine it is interfering with your code.

Related

Event hub CreateBatchAsync - A connection attempt failed because the connected party did not properly respond

I tried to insert the data into event hub for that followed this link to created the Free Trial event hub in azure portal and configured the connectionstring, eventHubName in my sample .Net application(referred link)
sample code:
class Program
{
const string eventHubName = "<eventHubName>";
const string connectionString = #"<connectionString>";
public static async Task Main(string[] args)
{
await EventHubIngestionAsync();
}
public static async Task EventHubIngestionAsync()
{
await using (var producerClient = new EventHubProducerClient(connectionString, eventHubName))
{
int counter = 0;
for (int i = 0; i < 100; i++)
{
int recordsPerMessage = 3;
try
{
var records = Enumerable
.Range(0, recordsPerMessage)
.Select(recordNumber => $"{{\"timeStamp\": \"{DateTime.UtcNow.AddSeconds(100 * counter)}\", \"name\": \"{$"name {counter}"}\", \"metric\": {counter + recordNumber}, \"source\": \"EventHubMessage\"}}");
string recordString = string.Join(Environment.NewLine, records);
EventData eventData = new EventData(Encoding.UTF8.GetBytes(recordString));
Console.WriteLine($"sending message {counter}");
// Optional "dynamic routing" properties for the database, table, and mapping you created.
//eventData.Properties.Add("Table", "TestTable");
//eventData.Properties.Add("IngestionMappingReference", "TestMapping");
//eventData.Properties.Add("Format", "json");
using EventDataBatch eventBatch = await producerClient.CreateBatchAsync();
eventBatch.TryAdd(eventData);
IEnumerable<EventData> dd = null;
await producerClient.SendAsync(dd);
}
catch (Exception exception)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("{0} > Exception: {1}", DateTime.Now, exception.Message);
Console.ResetColor();
}
counter += recordsPerMessage;
}
}
}
}
When running CreateBatchAsync getting the 'A connection attempt failed because the connected party did not properly respond'.
I tried both connection string and Access control method getting the same error.
That exception indicates that the client was unable to establish a connection with the Event Hubs service. The most common reason for this specific failure is that the network does not allow traffic over the AMQP ports (5761, 5762).
I'd suggest configuring the client to use AMQP over web sockets, as shown in this sample. That will direct traffic over port 443, which is more commonly allowed in restricted networks.

Using "Queue" in C# for sending SMS

I am trying to send SMS to clients from transactional data. It works fine but sometimes the staging table gets tanked due to huge data load. I was thinking if there is any way to queue data in a First-In-First-Out (FIFO) order. I am still learning C#. Please help me to implement the following code in a smart way.
I am sharing what I did.
private static void Main(string[] args)
{
var datetime = DateTime.Now;
var hr = datetime.Hour;
var mm = datetime.Minute + 1;
var ss = double.Parse(ConfigurationManager.AppSettings["SMSTIME"]);
// For Interval in Seconds
// This Scheduler will start at current time + 1 minute and call after every 3 Seconds
// IntervalInSeconds(start_hour, start_minute, seconds)
SchedulerTasks.IntervalInSeconds(hr, mm, ss,
() =>
{
CreateNewSms.Instance.PostNewSmsText();
});
Console.ReadLine();
}
public async void PostNewSmsText()
{
var smsDt = await Task.Run(() => DataAccessLayer.Instance.InsertSmsDataToLocalDb());
if (smsDt.Rows.Count != 0)
{
var smsData = GetSmsData(smsDt);
var xmlRespDoc = new XmlDocument();
await Task.Run(() =>
{
foreach (var sms in smsData)
{
var smsText = GetSmsText(sms.Channel, sms.AccountNumber, sms.Amount, sms.DrCr, sms.CurrentBalance, sms.BranchName,
sms.CurrencyName, sms.TrnDescription, sms.UbsTrnDateTime);
var smsSubmitTime = DateTime.Now.ToString(CultureInfo.InvariantCulture);
var response = ExecuteSmsService.Instance.PostSmsText(sms.MobileNo, smsText, sms.TrnRefNo);
var smsDeliveryTime = DateTime.Now.ToString(CultureInfo.InvariantCulture);
var operatorInfo = ConfigurationManager.AppSettings["Operator"];
xmlRespDoc.LoadXml(response);
var smsCsmsId = xmlRespDoc.SelectSingleNode("//SMSINFO/CSMSID")?.InnerText;
var smsRefNo = xmlRespDoc.SelectSingleNode("//SMSINFO/REFERENCEID")?.InnerText;
var smsDeliveryStatus = xmlRespDoc.SelectSingleNode("//SMSINFO/MSISDNSTATUS")?.InnerText;
if (smsRefNo != null) //Save response data if sms delivery successful
{
DataAccessLayer.Instance.InsertSmsResponseDetails(
sms.EntrySerialNo,
smsCsmsId,
smsRefNo,
smsText,
smsSubmitTime,
smsDeliveryTime,
true,
"Success",
operatorInfo);
DataAccessLayer.Instance.UpdateSmsStatus(sms.EntrySerialNo);
DataAccessLayer.Instance.DeleteSmsData(sms.EntrySerialNo, true);
Console.WriteLine("SMS successfully sent to: " + sms.MobileNo);
}
else
{
//If any sms delivery failed here we set a counter to retry again in next date
DataAccessLayer.Instance.SetSmsCounter(sms.EntrySerialNo);
//Save response data if sms delivery unsuccessful with failed status
DataAccessLayer.Instance.InsertSmsResponseDetails(
sms.EntrySerialNo,
smsCsmsId,
null,
smsText,
smsSubmitTime,
smsDeliveryTime,
false,
smsDeliveryStatus,
operatorInfo);
DataAccessLayer.Instance.DeleteSmsData(sms.EntrySerialNo, false);
Console.WriteLine("Invalid mobile no: " + sms.MobileNo);
}
}
});
}
else
{
Console.WriteLine("Waiting for transactions.....");
}
}
I was searching on Queue Implementations and found this but confused how to use it here in my code.
public class SendSmsQueue
{
private ConcurrentQueue<object> _jobs = new ConcurrentQueue<object>();
public SendSmsQueue()
{
var thread = new Thread(new ThreadStart(OnStart));
thread.IsBackground = true;
thread.Start();
}
public void Enqueue(object job)
{
_jobs.Enqueue(job);
}
private void OnStart()
{
while (true)
{
if (_jobs.TryDequeue(out object result))
{
Console.WriteLine(result);
}
}
}
}

grpc-dotnet authentication jwt bearer token

I am looking for some feedback or guidance. I have built a grpc server and client in dotnet core 3.1. Only this client will be talking to the server, but still need to protect the server endpoints. I am trying to implement authentication security on it and the jwt bearer token seems like a good path. I am trying to follow the example here(which came from this MS Doc) which seems like a pretty simple implementation, however seems insecure for production use since anyone can hit the generate token endpoint. I figured it could modify and implement a shared secret that is passed on the get token request. Does this seem like a good approach or other thoughts?
Besides this part, I have a question about the client side code that I don't quite understand. At the start of the client, it establishes a grpc channel by calling the CreateAuthenticatedChannel() which appears to only add the bearer token if the _token is set. You don't get the token until the client starts up and hit number three, but I don't see where the channel or client is rebuilt to include the metadata token value. The sample appears to work to but don't understand it.
class Program
{
// The port number(5001) must match the port of the gRPC server.
private const string Address = "localhost:5001";
private static string _token;
static async Task Main(string[] args)
{
var channel = CreateAuthenticatedChannel($"https://{Address}");
var client = new Ticketer.TicketerClient(channel);
Console.WriteLine("gRPC Ticketer");
Console.WriteLine();
Console.WriteLine("Press a key:");
Console.WriteLine("1: Get available tickets");
Console.WriteLine("2: Purchase ticket");
Console.WriteLine("3: Authenticate");
Console.WriteLine("4: Exit");
Console.WriteLine();
var exiting = false;
while (!exiting)
{
var consoleKeyInfo = Console.ReadKey(intercept: true);
switch (consoleKeyInfo.KeyChar)
{
case '1':
await GetAvailableTickets(client);
break;
case '2':
await PurchaseTicket(client);
break;
case '3':
_token = await Authenticate();
break;
case '4':
exiting = true;
break;
}
}
Console.WriteLine("Exiting");
}
private static GrpcChannel CreateAuthenticatedChannel(string address)
{
var credentials = CallCredentials.FromInterceptor((context, metadata) =>
{
if (!string.IsNullOrEmpty(_token))
{
metadata.Add("Authorization", $"Bearer {_token}");
}
return Task.CompletedTask;
});
// SslCredentials is used here because this channel is using TLS.
// Channels that aren't using TLS should use ChannelCredentials.Insecure instead.
var channel = GrpcChannel.ForAddress(address, new GrpcChannelOptions
{
Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
});
return channel;
}
private static async Task<string> Authenticate()
{
Console.WriteLine($"Authenticating as {Environment.UserName}...");
var httpClient = new HttpClient();
var request = new HttpRequestMessage
{
RequestUri = new Uri($"https://{Address}/generateJwtToken?name={HttpUtility.UrlEncode(Environment.UserName)}"),
Method = HttpMethod.Get,
Version = new Version(2, 0)
};
var tokenResponse = await httpClient.SendAsync(request);
tokenResponse.EnsureSuccessStatusCode();
var token = await tokenResponse.Content.ReadAsStringAsync();
Console.WriteLine(token);
Console.WriteLine("Successfully authenticated.");
return token;
}
private static async Task PurchaseTicket(Ticketer.TicketerClient client)
{
Console.WriteLine("Purchasing ticket...");
try
{
var response = await client.BuyTicketsAsync(new BuyTicketsRequest { Count = 1 });
if (response.Success)
{
Console.WriteLine("Purchase successful.");
}
else
{
Console.WriteLine("Purchase failed. No tickets available.");
}
}
catch (Exception ex)
{
Console.WriteLine("Error purchasing ticket." + Environment.NewLine + ex.ToString());
}
}
private static async Task GetAvailableTickets(Ticketer.TicketerClient client)
{
Console.WriteLine("Getting available ticket count...");
var response = await client.GetAvailableTicketsAsync(new Empty());
Console.WriteLine("Available ticket count: " + response.Count);
}
}
}

How to fix MassTransit.EndpointNotFoundException when using Request/Response initialized with localhost?

We are using masstransit with Request/Response pattern as described here: http://masstransit-project.com/MassTransit/usage/request-response.html
For some reason when the bus is initialized with localhost I receive a MassTransit.EndpointNotFoundException on the respond side, using context.RespondAsync method.
When the bus is initialized with the actual IP it works good without any exception.
We are using the bus also with other patterns of masstransit initialized with localhost without any problems.
We tried using both, Request and GetResponse patterns on the request side thinking maybe the problem source is there, but with no success.
Following is the consumer code the Response side, which generate the exception on the RespondAsync:
public override async Task Consume(ConsumeContext<IImageRequest> context)
{
var msg = context.Message;
try
{
var image = GetImage(msg.Id);
await context.RespondAsync<IImageResult>(new
{
msg.Id,
AImage = image
});
}
catch (Exception e)
{
Logger.Instance.Error($"{e}");
}
}
Following is the request side:
Task.Run(async () =>
{
var reqResClient =
BusControl.GetBusControl.CreateRequestClient<IImageRequest, IImageResult>("requestimage");
var req = new ImageRequest(msg.Id);
var response = await reqResClient.Request(req);
}).Wait();
Bus initialization code:
_bus = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.Durable = true;
_host = cfg.Host(HostName, port, VirtualHost, h =>
{
h.Username(UserName);
h.Password(Password);
});
cfg.ReceiveEndpoint(host, subscriber.QueueName, ep =>
{
ep.Durable = !subscriber.AutoDelete;
ep.AutoDelete = subscriber.AutoDelete;
ep.Instance(subscriber.Consumer);
if (subscriber.PrefetchCount.HasValue)
ep.PrefetchCount = subscriber.PrefetchCount.Value;
if (subscriber.ConcurrencyLimit.HasValue)
ep.UseConcurrencyLimit(subscriber.ConcurrencyLimit.Value);
});
cfg.Message<T>(x =>
{
x.SetEntityName(entityName);
});
});
public void Start()
{
if (_state == BusState.NotInitialized)
throw new InvalidOperationException("Cannot start bus. Bus is not initialized");
_bus?.Start();
_state = BusState.Started;
}
I wanted to know if there's a solution for it? or is it a known problem?
Thanks,

M2MQTT client disconnecting without an exception or error message

I'm trying to create an API that consumes various topics.
For this, I'm trying to multi-thread things, so that the whole thing can be scalable into multiple APIs, later on, but that's very besides the point.
I'm using ASP.net Core 4.0, if that's got anything to do with it. Entity Framework as well.
My problem is based on my connection to my Mosquitto server being broken without throwing an exception or anything of the like, after a minute or so. It doesn't matter how big the messages are, or how many are exchanged. I have no idea of how I can create a callback or anything of the kind to know what's going on with my connection. Can anyone help?
I'll link the code I use to establish a connection and subscribe to a connection below. Using the Subscribe method or doing it manually also changes nothing. I'm at a loss, here.
Thanks in advance!
Main.cs:
Task.Factory.StartNew(() => DataflowController.ResumeQueuesAsync());
BuildWebHost(args).Run();
DataflowController.cs:
public static Boolean Subscribe(String topic)
{
Console.WriteLine("Hello from " + topic);
MqttClient mqttClient = new MqttClient(brokerAddress);
byte code = mqttClient.Connect(Guid.NewGuid().ToString());
// Register to message received
mqttClient.MqttMsgPublishReceived += client_recievedMessageAsync;
string clientId = Guid.NewGuid().ToString();
mqttClient.Connect(clientId);
// Subscribe to topic
mqttClient.Subscribe(new String[] { topic }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
System.Console.ReadLine();
return true;
}
public static async Task ResumeQueuesAsync()
{
var mongoClient = new MongoClient(connectionString);
var db = mongoClient.GetDatabase(databaseName);
var topics = db.GetCollection<BsonDocument>(topicCollection);
var filter = new BsonDocument();
List<BsonDocument> result = topics.Find(filter).ToList();
var resultSize = result.Count;
Task[] subscriptions = new Task[resultSize];
MqttClient mqttClient = new MqttClient(brokerAddress);
byte code = mqttClient.Connect(Guid.NewGuid().ToString());
// Register to message received
mqttClient.MqttMsgPublishReceived += client_recievedMessageAsync;
string clientId = Guid.NewGuid().ToString();
mqttClient.Connect(clientId);
int counter = 0;
foreach(var doc in result)
{
subscriptions[counter] = new Task(() =>
{
Console.WriteLine("Hello from " + doc["topic"].ToString());
// Subscribe to topic
mqttClient.Subscribe(new String[] { doc["topic"].ToString() }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
System.Console.ReadLine();
});
counter++;
}
foreach(Task task in subscriptions)
{
task.Start();
}
}
static async void client_recievedMessageAsync(object sender, MqttMsgPublishEventArgs e)
{
// Handle message received
var message = System.Text.Encoding.Default.GetString(e.Message);
var topic = e.Topic;
var id = topic.Split("/")[2];
BsonDocument doc = new BsonDocument {
{"Plug ID", id },
{"Consumption", message }
};
await Save(doc, "smartPDM_consumption");
System.Console.WriteLine("Message received from " + topic + " : " + message);
}
This line was the issue:
byte code = mqttClient.Connect(Guid.NewGuid().ToString());
Deleted it, and it just worked.

Categories