#1 2017-04-19 18:13:59

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 337

AsynchRedirect usage example

Hi @ab, can you post a simple use of TSQLRest.AsynchRedirect ? I tried but without luck.

Thanks in advance.


Esteban

Offline

#2 2017-04-19 20:22:24

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 337

Re: AsynchRedirect usage example

My idea is to implement an asynchronous long work service with the possibility to the cancel it. What would be the best way do it ?

Thanks in advance.


Esteban

Offline

#3 2017-04-20 14:44:57

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 337

Re: AsynchRedirect usage example

@ab, Is AsynchRedirect working ?

Thanks.


Esteban

Offline

#4 2017-04-20 14:53:28

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: AsynchRedirect usage example

Yes, it is used on production, with no stability nor performance problem.

We use it namely for two things:
- when calling callbacks for events notifications: one high-performance main process thread call the virtual interface to mark the event, which is then asynchronously notified in the background to the subscribed clients.
- when adding some information to some slow storage, using a persistence service interface (but we also use AsynchBatch for that).

Offline

#5 2017-04-20 15:01:43

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 337

Re: AsynchRedirect usage example

Good, both things are very useful for me, can you give me an example of how call AsynchRedirect, mainly I can't understood the parameters.

procedure AsynchRedirect(const aGUID: TGUID; const aDestinationInterface: IInvokable; out aCallbackInterface); overload;

- aGUID: is the source service that I want redirect ? What about the code in the method, must be empty ?
- aDestinationInterface: is any interface where the real process is executed ?
- aCallbackInterface: the aDestinationInterface must have it a callback interface ?

Thanks in advance.


Esteban

Offline

#6 2017-04-20 16:34:24

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: AsynchRedirect usage example

In short, aDestinationInterface will be executed after aCallbackInterface is called.
aCallbackInterface will contain a "fake" class implementing aGUID.

Both aDestinationInterface and aCallbackInterface should be of one interface type defined with aGUID.

Offline

#7 2017-04-20 18:24:48

EMartin
Member
From: Buenos Aires - Argentina
Registered: 2013-01-09
Posts: 337

Re: AsynchRedirect usage example

Thank you very much @ab, I could make it work !! but neither in this life nor any other I could understand the use of this function. Can you update the documentation ?

Anyway, this is an example for any other that need use this function (adapted from example 31):

interface declaration:

  ...
type
  ILongWorkCallback = interface(IInvokable)
    ['{425BF199-19C7-4B2B-B1A4-A5BE7A9A4748}']
    procedure WorkFinished(const workName: string; timeTaken: integer);
    procedure WorkFailed(const workName, error: string);
  end;

  ILongWorkService = interface(IInvokable)
    ['{09FDFCEF-86E5-4077-80D8-661801A9224A}']
    procedure StartWork(const workName: string; const onFinish: ILongWorkCallback);
    function TotalWorkCount: Integer;
  end;

  IAsynchLongWorkService = interface(IInvokable)
    ['{CFA559E5-B181-45BB-84AB-7279DDDA51A9}']
    procedure StartWork(const workName: string; const onFinish: Integer);
  end;
  ...
initialization
  TInterfaceFactory.RegisterInterfaces([
    TypeInfo(ILongWorkService),TypeInfo(ILongWorkCallback),TypeInfo(IAsynchLongWorkService)]);

class declaration:

  ...
type
  TLongWorkService = class(TInterfacedObject,ILongWorkService)
  protected
    fCallbackInterface: IAsynchLongWorkService;
    fDestinationInterface: IAsynchLongWorkService;
  public
    procedure StartWork(const workName: string; const onFinish: ILongWorkCallback);
    function TotalWorkCount: Integer;
  end;

  TAsynchLongWorkService = class(TInterfacedObject,IAsynchLongWorkService)
  protected
    fCallback: ILongWorkCallback;
    fWorkName: string;
    fTotalWorkCount: Integer;
  public
    procedure StartWork(const workName: string; const onFinish: Integer);
    function TotalWorkCount: Integer;
  end;
  ...

class implementation:

...
{ TLongWorkAsyncService }

procedure TLongWorkService.StartWork(const workName: string; const onFinish: ILongWorkCallback);
begin
  if fCallbackInterface=nil then begin
    fDestinationInterface := TAsynchLongWorkService.Create;
    ServiceContext.Request.Server.AsynchRedirect(IAsynchLongWorkService,fDestinationInterface,fCallbackInterface);
  end;
  onFinish._AddRef; // avoid GPF and the interface is available in asynch. routine
  fCallbackInterface.StartWork(workName,Integer(onFinish));
end;

function TLongWorkService.TotalWorkCount: Integer;
begin
  result := MaxInt; // this shows the asynchronous functioning
end;
...
{ TAsynchLongWorkService }

procedure TAsynchLongWorkService.StartWork(const workName: string; const onFinish: Integer);
var tix: Int64;
begin
  InterlockedIncrement(fTotalWorkCount);
  fCallback := ILongWorkCallback(onFinish);
  fWorkName := workName;
  TSQLLog.Add.Log(sllInfo,'%.Execute(%) started',[self,fWorkName]);
  tix := GetTickCount64;
  Sleep(5000+Random(1000)); // some hard work
  if Random(100)>20 then
    fCallback.WorkFinished(fWorkName,GetTickCount64-tix) else
    fCallback.WorkFailed(fWorkName,'expected random failure');
  TSQLLog.Add.Log(sllInfo,'%.Execute(%) notified',[self,fWorkName]);
  fCallback._Release; // release the interface out this function
end;

function TAsynchLongWorkService.TotalWorkCount: Integer;
begin
  result := fTotalWorkCount;
end;

Best regards.


Esteban

Offline

#8 2019-01-24 12:54:10

mohsenti
Member
Registered: 2015-04-11
Posts: 72

Re: AsynchRedirect usage example

@ab,
It is the only search result about AsynchRedirect that has sample code.
Can you make documentation more clear or give a simple sample on this subject? because as you mentioned in the doc it seems using AsynchRedirect is the only good way to prevents locks (For example calling server again in the callback)

Offline

#9 2019-05-10 19:25:44

macfly
Member
From: Brasil
Registered: 2016-08-20
Posts: 374

Re: AsynchRedirect usage example

Hi, gyus

AsynchRedirect start the threads sequentially.

That is, when a second request is made, new "longworker" is queued to start after the completion of the previous one.

Is there any way to run in parallel?

Offline

#10 2019-05-10 23:38:15

macfly
Member
From: Brasil
Registered: 2016-08-20
Posts: 374

Re: AsynchRedirect usage example

Well, responding to myself ...

I followed the example of this post that implements the execution in sequence.

Using example 31 (Project31LongWorkServer), where TLongWorkServiceThread is (of course) a Thread, the worker runs in parallel.

Last edited by macfly (2019-05-10 23:39:04)

Offline

Board footer

Powered by FluxBB