You are not logged in.
Pages: 1
I use Smart Mobile Studio to communicate with mORMot server (based on RegressionTestsServer). For my project the most suitable method is to use the sicPerSession implementation with asynchronous responses. More precisely - I need to put my requests into a FIFO queue (without waiting for each response) and let the mormot client manage the queue .
I have looked at the SynCrossPlatformREST unit, but didn't find the option how to implement such approach (I may be wrong)
So here are my questions (for the implementation sicPerSession):
1) is it possible to ensure that the request is delayed until the server completes the processing of the previous request?
2) I tried to implement simple queueing in SynCrossPlatformREST unit. It works but I wonder if there is a more efficient way to achive it?
TCallQueue=class <---added
Caller: TServiceClientAbstract;
CallMethod: string;
CallParams: string;
onSuccess: procedure(res: array of Variant);
onError: TSQLRestEvent;
ReturnsCustomAnswer: boolean;
ExpectedOutputParamsCount : integer;
end;
/// REST client access class
TSQLRestClientURI = class(TSQLRest)
protected
fAuthentication: TSQLRestServerAuthentication;
fOnlyJSONRequests: boolean;
fRunningClientDriven: TStringList;
{$ifdef ISSMS}
fAsynchCount: integer;
fCallsQueue: Array of TCallQueue; <---added
fCallIsProcessed: boolean; <---added
fAsynchPendingText: array of string;
procedure SyncCallRemoteServiceASynchQueue; <---added
...
public
...
procedure CallRemoteServiceAsynch(aCaller: TServiceClientAbstract;
const aMethodName: string; aExpectedOutputParamsCount: integer;
const aInputParams: array of variant;
onSuccess: procedure(res: array of Variant); onError: TSQLRestEvent;
aReturnsCustomAnswer: boolean=false);
procedure SyncCallRemoteServiceAsynch(aCaller: TServiceClientAbstract; <---added
const aMethodName: string; aExpectedOutputParamsCount: integer;
const aInputParams: array of variant;
onSuccess: procedure(res: array of Variant); onError: TSQLRestEvent;
aReturnsCustomAnswer: boolean=false);
...
end;
implementation
...
procedure TSQLRestClientURI.SyncCallRemoteServiceASynch(aCaller: TServiceClientAbstract;
const aMethodName: string; aExpectedOutputParamsCount: integer;
const aInputParams: array of variant;
onSuccess: procedure(res: array of Variant); onError: TSQLRestEvent;
aReturnsCustomAnswer: boolean);
var CallQueueItem : TCallQueue;
begin
CallQueueItem := TCallQueue.create;
CallQueueItem .caller := aCaller;
CallQueueItem .callMethod := aMethodName;
CallQueueItem .callParams := JSON.Stringify(variant(aInputParams));
CallQueueItem .onError := onError;
CallQueueItem .OnSuccess := onSuccess;
CallQueueItem .ReturnsCustomAnswer := aReturnsCustomAnswer;
CallQueueItem .ExpectedOutputParamsCount := aExpectedOutputParamsCount;
fCallsQueue.add(CallQueueItem ); // the length is set in constructor Create (fCallsQueue.SetLength(0); )
SyncCallRemoteServiceASynchQueue;
end;
procedure TSQLRestClientURI.SyncCallRemoteServiceASynchQueue;
var Call: TSQLRestURIParams;
CallQueueItem : TCallQueue;
begin
SetAsynch(Call,
lambda
var i:= 0;
fCallIsProcessed:= false;
CallQueueItem := fCallsQueue[ Low(fCallsQueue)];
for i := Low(fCallsQueue) + 1 to High(fCallsQueue) do
fCallsQueue[i-1] := fCallsQueue[i];
fCallsQueue.SetLength(high(fCallsQueue));
if high(fCallsQueue)>=Low(fCallsQueue) then
SyncCallRemoteServiceASynchQueue;
if not assigned(CallQueueItem.onSuccess) then
exit; // no result to handle
if CallQueueItem.ReturnsCustomAnswer then begin
if Call.OutStatus=HTTP_SUCCESS then begin
var result: TVariantDynArray;
result.Add(Call.OutBody);
CallQueueItem.onSuccess(result);
end else
if Assigned(CallQueueItem.onError) then
CallQueueItem.onError(self);
exit;
end;
var outID: integer;
var result := CallGetResult(Call,outID); // from {result:...,id:...}
if VarIsValidRef(result) then begin
if (CallQueueItem.Caller.fInstanceImplementation=sicClientDriven) and (outID<>0) then
(CallQueueItem.Caller as TServiceClientAbstractClientDriven).fClientID := IntToStr(outID);
if CallQueueItem.ExpectedOutputParamsCount=0 then
CallQueueItem.onSuccess([]) else begin
var res := TJSONVariantData.CreateFrom(result);
if (res.Kind=jvArray) and (res.Count=CallQueueItem.ExpectedOutputParamsCount) then
CallQueueItem.onSuccess(res.Values) else
if Assigned(CallQueueItem.onError) then
CallQueueItem.onError(self);
end;
end else
if Assigned(CallQueueItem.onError) then
CallQueueItem.onError(self);
end,
lambda
if Assigned(CallQueueItem.onError) then
CallQueueItem.onError(self);
end,
lambda
result := (Call.OutStatus=HTTP_SUCCESS) and (Call.OutBody<>'');
end);
CallQueueItem:= fCallsQueue[Low(fCallsQueue)];
if assigned(CallQueueItem) and not fCallIsProcessed then
begin
fCallIsProcessed:= true;
CallRemoteServiceInternal(Call,CallQueueItem.Caller,CallQueueItem.CallMethod,CallQueueItem.CallParams);
end;
end;
Eva
P.S. Thanks a lot for creating the SMS crossplatform and I also would like to thank for warleyalex for illustrative examples and for creating videotutorials
Offline
Pages: 1