Problem with WCF Response - getting multiple responses - wcf

I am using Silverlight, WCF combination.
Currently, I am facing one problem with service response.
I am using request response service type.
I have 100 Items and i am going to call 100 services to fetch it's properties.
foreach (ItemDto item in items)
{
ServiceCall();
ServiceSendCount++;
}
private void OnServiceCallCompleted(.....)
{
ServiceReceiveCount++;
}
If i am sending 5 service calls then it returns with 5*5 = 25 responses.
same with as i am sending 10 service calls then it returns with 10*10 = 100 responses.
I am not able to figure out what was the problem....
Can anyone please shed some light on this?
Update:
Please find herewith the service call method.
I agree that each and every time i am sending OnServiceCallCompleted ..
foreach (ItemDto item in items)
{
itemPropertyService.GetItemProperties([parameters] , OnServiceCallCompleted);
ServiceSendCount++;
}
private void OnServiceCallCompleted(.....)
{
ServiceReceiveCount++;
/* here contains my logic to process the response
If it cames mulriple time then my logic will down
*/
}
Can you please let me know the solution for same. As the change in the service is not possible right now.
But it will create the problem of response time.
Suppose i am going to send the request for 100 items at a time.
In My first approch, i will get the first 100 responses with correct data in withing 5-10 sec.
ItemPropertyService itemPropertyService = new ItemPropertyService();
foreach (ItemDto item in items)
{
itemPropertyService.GetItemProperties([parameters] , OnServiceCallCompleted);
ServiceSendCount++;
}
(Problem as i discussed it is going to send me 100 X 100 responses which leads to the timeout)
In Second Approch, (As per u have suggested)
foreach (ItemDto item in items)
{
ItemPropertyService itemPropertyService = new ItemPropertyService();
itemPropertyService.GetItemProperties([parameters] , OnServiceCallCompleted);
ServiceSendCount++;
}
I am getting same responses as of request, but it will take time near about 2 min.
Actually, I am not able to figure out the problem of time consuming.
As our requests are very huge it will really going to take time.
Do you know about this that how to solve this problem?
I am just near to solve my problem.

Can't tell from the code as you didn't show the ServiceCall() function but numbers suggest you are reusing the same proxy object and adding the OnServiceCallCompleted event handler every time you make a request. If you add the same event handler multiple times it is going to fire multiple times and the completed event handler is per proxy object not per request.
Try creating a new proxy object for each request and seeing if you still get multiple responses.

Related

How to push Salesforce Order to an external REST API?

I have experience in Salesforce administration, but not in Salesforce development.
My task is to push a Order in Salesforce to an external REST API, if the order is in the custom status "Processing" and the Order Start Date (EffectiveDate) is in 10 days.
The order will be than processed in the down-stream system.
If the order was successfully pushed to the REST API the status should be changed to "Activated".
Can anybody give me some example code to get started?
There's very cool guide for picking right mechanism, I've been studying from this PDF for one of SF certifications: https://developer.salesforce.com/docs/atlas.en-us.integration_patterns_and_practices.meta/integration_patterns_and_practices/integ_pat_intro_overview.htm
A lot depends on whether the endpoint is accessible from Salesforce (if it isn't - you might have to pull data instead of pushing), what authentication it needs.
For push out of Salesforce you could use
Outbound Message - it'd be an XML document sent when (time-based in your case?) workflow fires, not REST but it's just clicks, no code. The downside is that it's just 1 object in message. So you can send Order header but no line items.
External Service would be code-free and you could build a flow with it.
You could always push data with Apex code (something like this). We'd split the solution into 2 bits.
The part that gets actual work done: At high level you'd write function that takes list of Order ids as parameter, queries them, calls req.setBody(JSON.serialize([SELECT Id, OrderNumber FROM Order WHERE Id IN :ids]));... If the API needs some special authentication - you'd look into "Named Credentials". Hard to say what you'll need without knowing more about your target.
And the part that would call this Apex when the time comes. Could be more code (a nightly scheduled job that makes these callouts 1 minute after midnight?) https://salesforce.stackexchange.com/questions/226403/how-to-schedule-an-apex-batch-with-callout
Could be a flow / process builder (again, you probably want time-based flows) that calls this piece of Apex. The "worker" code would have to "implement interface" (a fancy way of saying that the code promises there will be function "suchAndSuchName" that takes "suchAndSuch" parameters). Check Process.Plugin out.
For pulling data... well, target application could login to SF (SOAP, REST) and query the table of orders once a day. Lots of integration tools have Salesforce plugins, do you already use Azure Data Factory? Informatica? BizTalk? Mulesoft?
There's also something called "long polling" where client app subscribes to notifications and SF pushes info to them. You might have heard about CometD? In SF-speak read up about Platform Events, Streaming API, Change Data Capture (although that last one fires on change and sends only the changed fields, not great for pushing a complete order + line items). You can send platform events from flows too.
So... don't dive straight to coding the solution. Plan a bit, the maintenance will be easier. This is untested, written in Notepad, I don't have org with orders handy... But in theory you should be able to schedule it to run at 1 AM for example. Or from dev console you can trigger it with Database.executeBatch(new OrderSyncBatch(), 1);
public class OrderSyncBatch implements Database.Batchable, Database.AllowsCallouts {
public Database.QueryLocator start(Database.BatchableContext bc) {
Date cutoff = System.today().addDays(10);
return Database.getQueryLocator([SELECT Id, Name, Account.Name, GrandTotalAmount, OrderNumber, OrderReferenceNumber,
(SELECT Id, UnitPrice, Quantity, OrderId FROM OrderItems)
FROM Order
WHERE Status = 'Processing' AND EffectiveDate = :cutoff]);
}
public void execute(Database.BatchableContext bc, List<sObject> scope) {
Http h = new Http();
List<Order> toUpdate = new List<Order>();
// Assuming you want 1 order at a time, not a list of orders?
for (Order o : (List<Order>)scope) {
HttpRequest req = new HttpRequest();
HttpResponse res;
req.setEndpoint('https://example.com'); // your API endpoint here, or maybe something that starts with "callout:" if you'd be using Named Credentials
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
req.setBody(JSON.serializePretty(o));
res = h.send(req);
if (res.getStatusCode() == 200) {
o.Status = 'Activated';
toUpdate.add(o);
}
else {
// Error handling? Maybe just debug it, maybe make a Task for the user or look into
// Database.RaisesPlatformEvents
System.debug(res);
}
}
update toUpdate;
}
public void finish(Database.BatchableContext bc) {}
public void execute(SchedulableContext sc){
Database.executeBatch(new OrderSyncBatch(), Limits.getLimitCallouts()); // there's limit of 10 callouts per single transaction
// and by default batches process 200 records at a time so we want smaller chunks
// https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_methods_system_limits.htm
// You might want to tweak the parameter even down to 1 order at a time if processing takes a while at the other end.
}
}

sending the same request multiple times in a raw. some return with status code 204 and some are ok

I'm sending a post request to the same url multiple times in a row. Some of the requests return 200 status code and some return 204 saying no content. the request updates some content in a mongo database. I don't know if this is relevant. What could cause this problem?
My index.js:
app.post('/updatetrialsession',authenticateJWT ,(req,res)=>{
User.findOne({username:req.user.username}).then(user=>{
var trialIdx=user.examTrials.findIndex(it=>it.trialId===req.body.trialId)
var questionIdx=req.body.questionIdx
if(trialIdx!==-1){
user.examTrials[trialIdx].questions[questionIdx]=req.body.question
user.examTrials[trialIdx].currentQuestion=questionIdx+1
user.examTrials[trialIdx].countDown=req.body.countDown
user.examTrials[trialIdx].numOfSolved=req.body.numOfSolved
var filter={
'username':user.username
}
var update={
$set:{
'examTrials':user.examTrials
}
}
User.findOneAndUpdate(filter,update).then(user=>{
console.log('updated')
res.json({
status:"success"
})
})
}
})
})
Note: all requests go to this url "/epdatetrialsession".
when there's a 20 sec gap between each request everything works just fine. but when the server get flooded with say a request every 2 seconds or so, some return with 204 status code
I have had the same issue once. In my experience, When sending multiple number of requests to the server within a very short period of time, sometimes the server fails to answer all of them. Depends on the server capability. Did you try to check this by, sending the request for only the ones which returns 204 one at a time and see whether they still returns a 204? If so, the server has responded correctly even when sending the requests in a row. But if the server return a content with 200 when sending one at a time, then the issue might be with the server when handling multiple requests at a time.

How to call more than 1000 web APIs with a main API with very less response time

I have to implement MVC .Net Web api (say "Main" api) which includes two parts.
1) Database call to fetch the record.
2) And more than 1000s of another web api call(response time 100 ms on avg. for each) which will use records returned by above db call.
Also, the Main api will be called in every 3 seconds continuously. I tried implementing using async/await method but didn't find much progress and when trying to test it using Apache Benchmark tool, it throws timeout specified has expired error.
Is there any way to achieve this? Please suggest.
Code snippet
[HttpGet]
public async Task<string> doTaskasync()
{
TripDetails obj = new TripDetails();
GPSCoordinates objGPS = new GPSCoordinates();
try
{
/* uriArray Contains more than 1000 APIs which needs to be exectued. */
string[] uriArray = await dolongrunningtaskasync();
IEnumerable<Task<GPSCoordinates>> allTasks = uriArray .Select(u => GetLocationsAsync(u));
IEnumerable<GPSCoordinates> allResults = await Task.WhenAll(allTasks);
}
catch (Exception ex)
{
return ex.Message ;
}
return "success";
}
Ab.exe test
There is nothing wrong programmatically with your code - except that this is practically a DOS attack on the second (location) API. You should definitely add caching to avoid at least part of the 1000 api calls, especially if you call the main api often (as you wrote).
What I would do is to make the inner api calls a centralized operation instead of making these calls individually inside your web api method. For example you could use a central list for location api calls (tasks) that have been started (but not finished), and another list for results that have been already finished. Both list could be a concurrent dictionary by the unique urls you use for the location api calls.

Does Laravel query database each time I call Auth::user()?

In my Laravel application I used Auth::user() in multiple places. I am just worried that Laravel might be doing some queries on each call of Auth::user()
Kindly advice
No the user model is cached. Let's take a look at Illuminate\Auth\Guard#user:
public function user()
{
if ($this->loggedOut) return;
// If we have already retrieved the user for the current request we can just
// return it back immediately. We do not want to pull the user data every
// request into the method because that would tremendously slow an app.
if ( ! is_null($this->user))
{
return $this->user;
}
As the comment says, after retrieving the user for the first time, it will be stored in $this->user and just returned back on the second call.
For same Request, If you run Auth::user() multiple time, it will only run 1 query and not multiple time.
But , if you go and call for another request with Auth::user() , it will go and run 1 query again.
This cannot be cached for all request after first request has been made due to security point of view.
So, It runs 1 query per request irrespective of number of time you are calling.
I see use of some session here to avoid run multiple query, so you can try these code : http://laravel.usercv.com/post/16/using-session-against-authuser-in-laravel-4-and-5-cache-authuser
Thanks

While handling an NServiceBus message, is it possible to peek at the input queue?

I have a Windows service using NServiceBus to handle incoming messages.
While processing a message, I would like to check to see if there are any other remaining messages on the queue to process.
What is the best way to approach this?
For this specific scenario I'd say that a saga could be appropriate where it is created by the first message received, opens a timeout (for let's say one minute), collects all messages during that period of time, then Bus.SendLocal's a message containing all rows, for which another handler creates the spreadsheet and uploads.
Since, NServiceBus is using MSMQ, you can use the methods from System.Messaging.
Included is a modified method, I'm currently working on, to do a kind of batch processing.
using System.Messaging;
public int PeekAtQueue()
{
const string QUEUE_NAME = "private$\\you_precious_queuname";
if (!MessageQueue.Exists(".\\" + QUEUE_NAME))
return 0;
var messageQueues = MessageQueue.GetPrivateQueuesByMachine(Environment.MachineName);
var queue = messageQueues.Single(x => x.QueueName == QUEUE_NAME);
return queue.GetAllMessages().Count();
}
Modified here itself in the editor. Hope it still compiles :)
Found a similar discussion here, by the way:
http://jopinblog.wordpress.com/2008/03/12/counting-messages-in-an-msmq-messagequeue-from-c/