Flex database - HTTP call collision? - web-services

I have a Flex application for AIR. I fetch some data from a JSON-RPC web service through the mx.rpc.http.HTTPService class. I make all the calls asynchronously. When the results return I process them and put the data into an SQLite database through the flash.data.SQLConnection. This means quite some updates per web service calls so every callback starts a transaction, does the updates and then commits.
According to my debug console tracing I see two kinds of behaviour: either a callback successfully begins a transaction, calls the transaction event handler function, does all the updates, commits and then the next web service call returns. Or a callback successfully begins a transaction and as the next web service call returns (without trying to start a new transaction yet) the previous callback just... ceases to exist even before the callback of the beginning of the transaction.
Is that a bug in Flex? Or in AIR? Or in ActionScript? Or in the specific components? Do I do something wrong? Is this just my misunderstanding? (I'm just trying my wings in Flex, I don't really know what to expect from the system or how to handle this situation.)
Some code from my database manager class
public function beginTransaction(handler:Function):void {
// The calls are all fine up to this point
conn.begin(SQLTransactionLockType.DEFERRED, new Responder(handler, OnError));
// Begin is always called first. If another web service call doesn't come
// back up to this point then it won't until I call commit in an other
// function.
trace("this always runs yet");
// But if another call comes back just after begin is called then handler
// won't get called. Even though the previous trace still will.
}
My web service call
public function getWSCall(url:String, method:String, param:Object,
handler:Function):void
{
var http:HTTPService = new HTTPService();
http.addEventListener(FaultEvent.FAULT, JsonError);
http.addEventListener(ResultEvent.RESULT, handler);
http.url = url;
http.method = "POST";
http.contentType = "application/json";
var params:Object = {};
params.jsonrpc = "2.0";
params.method = method;
if (param !== null)
params.params = param;
params.id = method;
var json:String = JSON.stringify(params);
trace (url + " " + json);
http.send(json);
}
And an example of how I call it
JsonConnector.instance.getWSCall(WSConstants.GET_DATA_URL,
WSConstants.GET_DATA_METHOD, param, getDataCompleted);
And in the getDataCompleted after some rearrangement I call my database manager class where I finally begin the transaction:
dbConnector.Open(key, opened);
function opened(event:SQLEvent):void
{
if(event.type == SQLEvent.OPEN) {
dbConnector.beginTransaction(onBegin);
}
}

Related

Preventing a WCF client from issuing too many requests

I am writing an application where the Client issues commands to a web service (CQRS)
The client is written in C#
The client uses a WCF Proxy to send the messages
The client uses the async pattern to call the web service
The client can issue multiple requests at once.
My problem is that sometimes the client simply issues too many requests and the service starts returning that it is too busy.
Here is an example. I am registering orders and they can be from a handful up to a few 1000s.
var taskList = Orders.Select(order => _cmdSvc.ExecuteAsync(order))
.ToList();
await Task.WhenAll(taskList);
Basically, I call ExecuteAsync for every order and get a Task back. Then I just await for them all to complete.
I don't really want to fix this server-side because no matter how much I tune it, the client could still kill it by sending for example 10,000 requests.
So my question is. Can I configure the WCF Client in any way so that it simply takes all the requests and sends the maximum of say 20, once one completes it automatically dispatches the next, etc? Or is the Task I get back linked to the actual HTTP request and can therefore not return until the request has actually been dispatched?
If this is the case and WCF Client simply cannot do this form me, I have the idea of decorating the WCF Client with a class that queues commands, returns a Task (using TaskCompletionSource) and then makes sure that there are no more than say 20 requests active at a time. I know this will work but I would like to ask if anyone knows of a library or a class that does something like this?
This is kind of like Throttling but I don't want to do exactly that because I don't want to limit how many requests I can send in a given period of time but rather how many active requests can exist at any given time.
Based on #PanagiotisKanavos suggjestion, here is how I solved this.
RequestLimitCommandService acts as a decorator for the actual service which is passed in to the constructor as innerSvc. Once someone calls ExecuteAsync a completion source is created which along with the command is posted to the ActonBlock, the caller then gets back the a Task from the completion source.
The ActionBlock will then call the processing method. This method sends the command to the web service. Depending on what happens, this method will use the completion source to either notify the original sender that a command was processed successfully or attach the exception that occurred to the source.
public class RequestLimitCommandService : IAsyncCommandService
{
private class ExecutionToken
{
public TaskCompletionSource<bool> Source { get; }
public ICommand Command { get; }
public ExecutionToken(TaskCompletionSource<bool> source, ICommand command)
{
Source = source;
Command = command;
}
}
private IAsyncCommandService _innerSrc;
private ActionBlock<ExecutionToken> _block;
public RequestLimitCommandService(IAsyncCommandService innerSvc, int maxDegreeOfParallelism)
{
_innerSrc = innerSvc;
var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism };
_block = new ActionBlock<ExecutionToken>(Execute, options);
}
public Task IAsyncCommandService.ExecuteAsync(ICommand command)
{
var source = new TaskCompletionSource<bool>();
var token = new ExecutionToken(source, command);
_block.Post(token);
return source.Task;
}
private async Task Execute(ExecutionToken token)
{
try
{
await _innerSrc.ExecuteAsync(token.Command);
token.Source.SetResult(true);
}
catch (Exception ex)
{
token.Source.SetException(ex);
}
}
}

How to lock a long async call in a WebApi action?

I have this scenario where I have a WebApi and an endpoint that when triggered does a lot of work (around 2-5min). It is a POST endpoint with side effects and I would like to limit the execution so that if 2 requests are sent to this endpoint (should not happen, but better safe than sorry), one of them will have to wait in order to avoid race conditions.
I first tried to use a simple static lock inside the controller like this:
lock (_lockObj)
{
var results = await _service.LongRunningWithSideEffects();
return Ok(results);
}
this is of course not possible because of the await inside the lock statement.
Another solution I considered was to use a SemaphoreSlim implementation like this:
await semaphore.WaitAsync();
try
{
var results = await _service.LongRunningWithSideEffects();
return Ok(results);
}
finally
{
semaphore.Release();
}
However, according to MSDN:
The SemaphoreSlim class represents a lightweight, fast semaphore that can be used for waiting within a single process when wait times are expected to be very short.
Since in this scenario the wait times may even reach 5 minutes, what should I use for concurrency control?
EDIT (in response to plog17):
I do understand that passing this task onto a service might be the optimal way, however, I do not necessarily want to queue something in the background that still runs after the request is done.
The request involves other requests and integrations that take some time, but I would still like the user to wait for this request to finish and get a response regardless.
This request is expected to be only fired once a day at a specific time by a cron job. However, there is also an option to fire it manually by a developer (mostly in case something goes wrong with the job) and I would like to ensure the API doesn't run into concurrency issues if the developer e.g. double-sends the request accidentally etc.
If only one request of that sort can be processed at a given time, why not implement a queue ?
With such design, no more need to lock nor wait while processing the long running request.
Flow could be:
Client POST /RessourcesToProcess, should receive 202-Accepted quickly
HttpController simply queue the task to proceed (and return the 202-accepted)
Other service (windows service?) dequeue next task to proceed
Proceed task
Update resource status
During this process, client should be easily able to get status of requests previously made:
If task not found: 404-NotFound. Ressource not found for id 123
If task processing: 200-OK. 123 is processing.
If task done: 200-OK. Process response.
Your controller could look like:
public class TaskController
{
//constructor and private members
[HttpPost, Route("")]
public void QueueTask(RequestBody body)
{
messageQueue.Add(body);
}
[HttpGet, Route("taskId")]
public void QueueTask(string taskId)
{
YourThing thing = tasksRepository.Get(taskId);
if (thing == null)
{
return NotFound("thing does not exist");
}
if (thing.IsProcessing)
{
return Ok("thing is processing");
}
if (!thing.IsProcessing)
{
return Ok("thing is not processing yet");
}
//here we assume thing had been processed
return Ok(thing.ResponseContent);
}
}
This design suggests that you do not handle long running process inside your WebApi. Indeed, it may not be the best design choice. If you still want to do so, you may want to read:
Long running task in WebAPI
https://blogs.msdn.microsoft.com/webdev/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-background-processes-in-asp-net/

Cancelling async webservice call in windows phone

I'm developing a windows phone app that consumes a .Net Web Service (develop also by me). When I call the a Web Service method a do it asynchronously and don't block the UI. For example, here's a code sample for asking the server for a list o flights Arrivals.
service.MobileWSSoapClient Proxy { get; set; }
Proxy = new service.MobileWSSoapClient();
Proxy.GetArrivalsCompleted += proxy_GetArrivalsCompleted;
Proxy.GetArrivalsAsync(searchFilter);
This way I give the freedom to the user to call again the same method or another one (ex: refreshing the arrival list or searching for a particular arrival). In case the user generates a new call to the services, the app should "cancel" the first call and only show the result of the last call. I think that is technically impossible to Cancel a web service call that already went to the server, we should wait for the server response and then ignore it. Knowing that, it would be helpful to mark somehow that call as obsolete. It would be enough to receive an error as a response of that obsolete call. I'll write a pseudo code of what I imagine/need.
void proxy_GetArrivalsCompleted(object sender, service.GetArrivalsCompletedEventArgs e){
if (e.Error == null){
// DO WORK
}
else
{
if(e.Error == Server Exception || e.Error == Connection Exception){
MessageBox.Show("error");
}
else if (e.Error == obsolete call){
// DO NOTHING
}
}
Thanks in advance.
You can use BackgroundWorker for your scenario. So, when the user calls again to the web service you can cancel your backgroundworker process that will end the service call.
How to use BackgroundWorker here.

actionscript web services event fires off to late

I have a web service which is working find with the data proxy.
In this web service I have some functions I like to call and assign the results to a variable.
I found some example on this and below is what I have come up with.
Now all works but my event is being fired to late in the process. What I mean is once I call the getAdData() function and then call the webservice function getBleedAt() I need my event to fire off. what happening is the event is being fire at the end of the hold routine so I get my data to late.
I try using the dispatchEvent but can't get that to work. the web service function is returning a XML structure
public function getAdddata(adnum:String){
var WS:WebService = new WebService();
WS.getBleedAt.addEventListener("result", GetInfo);
WS.getBleedAt.resultFormat = 'e4x';
WS.loadWSDL(URL);
WS.getBleedAt(adnum);
}
private function GetInfo(evt:ResultEvent):void {
var myObj:Object = evt.result as Object;
trace(myObj.BleedAt.toString());
}
The call to the web service returns asynchronously so your result handler (the GetInfo method) is the earliest point at which the result data is available to you. Therefore, any code which needs to access the result data needs to be triggered from the GetInfo method.

understanding RProperty IPC communication

i'm studying this source base. Basically this is an Anim server client for Symbian 3rd edition for the purpose of grabbing input events without consuming them in a reliable way.
If you spot this line of the server, here it is basically setting the RProperty value (apparently to an increasing counter); it seems no actual processing of the input is done.
inside this client line, the client is supposed to be receiving the notification data, but it only calls Attach.
my understanding is that Attach is only required to be called once, but is not clear in the client what event is triggered every time the server sets the RProperty
How (and where) is the client supposed to access the RProperty value?
After Attaching the client will somewhere Subscribe to the property where it passes a TRequestStatus reference. The server will signal the request status property via the kernel when the asynchronous event has happened (in your case the property was changed). If your example source code is implemented in the right way, you will find an active object (AO; CActive derived class) hanging around and the iStatus of this AO will be passed to the RProperty API. In this case the RunL function of the AO will be called when the property has been changed.
It is essential in Symbian to understand the active object framework and quite few people do it actually. Unfortunately I did not find a really good description online (they are explained quite well in Symbian OS Internals book) but this page at least gives you a quick example.
Example
In the ConstructL of your CMyActive subclass of CActive:
CKeyEventsClient* iClient;
RProperty iProperty;
// ...
void CMyActive::ConstructL()
{
RProcess myProcess;
TSecureId propertyCategory = myProcess.SecureId();
// avoid interference with other properties by defining the category
// as a secure ID of your process (perhaps it's the only allowed value)
TUint propertyKey = 1; // whatever you want
iClient = CKeyEventsClient::NewL(propertyCategory, propertyKey, ...);
iClient->OpenNotificationPropertyL(&iProperty);
// ...
CActiveScheduler::Add(this);
iProperty.Subscribe(iStatus);
SetActive();
}
Your RunL will be called when the property has been changed:
void CMyActive::RunL()
{
if (iStatus.Int() != KErrCancel) User::LeaveIfError(iStatus.Int());
// forward the error to RunError
// "To ensure that the subscriber does not miss updates, it should
// re-issue a subscription request before retrieving the current value
// and acting on it." (from docs)
iProperty.Subscribe(iStatus);
TInt value; // this type is passed to RProperty::Define() in the client
TInt err = iProperty.Get(value);
if (err != KErrNotFound) User::LeaveIfError(err);
SetActive();
}