RTC Forums
April 29, 2024, 12:24:54 PM *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Login Register  
Pages: [1] 2
  Print  
Author Topic: Problems with DelayedCall  (Read 9653 times)
HelgeLange
RTC Expired
*
Posts: 100


« on: May 11, 2017, 09:18:24 PM »

Hi Danijel,

after the update with RTC 8.02 (didn't try with 8.0 or 8.01) I have in one of my projects problems with the delayed call.
It returns immediately although my code puts the call on sleep for 60 seconds

Code:
    Sender.Session.asBoolean['bDCC'] := True;
    if ((not Param.asBoolean[STR_IS_DELAYED]) and (RData.FpActionList.Count = 0)) then begin
      // every call enters here as becaue t's basically a new call everytime
      // Param.asInteger[STR_MONITOR_ID] has a AutoIncrement Number send by the client and only the client auments this number and with every call it goes up...
      Param.asBoolean[STR_IS_DELAYED] := True;
      {$IFDEF CS5} CodeSite.Send(csmLevel4, 'Delaying call for ClientId '+ Param.asString[STR_TAXI_ID] + ' with DelayedCallId', Param.asInteger[STR_MONITOR_ID]); {$ENDIF}
      RData.CB := PrepareDelayedCall(60000, Param, fctDelayedCallExecute);
      PostDelayedCall(RData.CB);
    end else begin
      // this part is never executed and PostDelayedCall returns the call to the client
      //
      TRtcDataServer(Sender).Session.asInteger['Counter'] := TRtcDataServer(Sender).Session.asInteger['Counter'] + 1;
      //
      RData.CB := nil;


So I see that I prepare and Post the delayed call and this code has worked without problems, but now I see in my client that after posting the call it returns at once and I never get into the else-part.

I don't know atm where to look anymore.

Any ideas ?
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #1 on: May 12, 2017, 08:23:02 AM »

1. Is your code compiled into an ISAPI DLL and running from another WebServer, or is it a Stand-alone Server? If it is a stand-alone Server, is it Multi-Threaded or single-threaded?

2. What is "fctDelayedCallExecute"?

3. What is "RData"? When is it created and when is it destroyed? What happens to "RData.CB" when "RData" is destroyed?
Logged
HelgeLange
RTC Expired
*
Posts: 100


« Reply #2 on: May 12, 2017, 02:25:25 PM »

The server is Multithreaded, stand-alone exe.
fctDelayedCallExecute is the event handler for TRtcFunction.OnExecute, the object is called fctDelayedCall. The cde I posted is directly from the fctDelayedCallExecute code block
RData is an own data object with informations about the session and ths includes the DelayedCall object so that I can wake it up again.
When it wakes up (after the 60 seconds or because I have data to send) I set RData.CB to nil (last line in my code example)
RData is destroyed when the client disconnects through Logout or when the client times out (OnSessionEnd).
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #3 on: May 12, 2017, 02:58:01 PM »

I can not reproduce the problem you are describing with Delayed Calls. RTC Portal VCL and RTC Messenger Client and Server Demos (Demos/RTC_Messenger folder in the RTC SDK) are both using remote functions with delayed calls and they are both working as expected when compiled with RTC SDK v8.03 (just released) and Delphi 10.1 Berlin.

Is your Server running on Windows or some other platform?
Which Delphi version are you using?

Can you download RTC SDK v8.03 and test RTC Messenger Client and Server Demos to see if you can reproduce the problem with them? If you can reproduce the problem, then I will need the exact steps to reproduce it.

Best Regards,
Danijel Tkalcec
Logged
HelgeLange
RTC Expired
*
Posts: 100


« Reply #4 on: May 12, 2017, 03:03:19 PM »

Will try now.
I use Delphi 10.1 Berlin Upd 2 on Windows 10 Creators update.
The weird thing is that the same code wasn't touched in months and was always working perfectly Sad
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #5 on: May 12, 2017, 03:25:30 PM »

If you did NOT change anything about the way your Client and Server use remote functions with Delayed Calls, then maybe the problem is somewhere else. In any case, if you think there is a bug in the RTC SDK, then I will need a way to reproduce it - so I can debug and fix it.

Best Regards,
Danijel Tkalcec
Logged
HelgeLange
RTC Expired
*
Posts: 100


« Reply #6 on: May 12, 2017, 03:59:17 PM »

Don't get me wrong, I don't accuse of anything. I just made the observation, that the code I'm talking about is more than a year old and worked fine before. I'm just out of ideas atm.

You think there is a way to see in log files why the PostDelayedCall returnes the call directly instead of waiting the 60 seconds ?
I just deleted my whole RTC directory and used a clean install of version 8.03 and the problem persists.

Now I'm going to check out your examples. I'll keep you posted.

btw... The problem can be in the client code, too ? (although that hasn't changed either, just to eliminate maybe the need of checking the code there)
Logged
HelgeLange
RTC Expired
*
Posts: 100


« Reply #7 on: May 12, 2017, 04:23:23 PM »

Your Messenger example returns the delayed call twice, one is immediately and the other 10 seconds later, the difference is that the one that returns at once has the sender param nil

as seen here :

https://puu.sh/vNLYr/a32d5a0f14.png

Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #8 on: May 12, 2017, 04:27:18 PM »

What do you mean by "returns"? Where does it return?
Are you talking about the Server or the Client?
And where is the Sender param nil?

If you are talking about the result returning on the Client in the MsgGetDataExecute event, you will see that a PostInterativeResult is being called there if Sender<>nil, which is used to trigger the same event again on the Client outside of the connection thread context, with Sender=nil. This ensures that anything happening inside that event does NOT interfere with the state of the connection, so the connection can being used to post the next request, without waiting for the event to finish.

Logged
HelgeLange
RTC Expired
*
Posts: 100


« Reply #9 on: May 12, 2017, 04:34:10 PM »

Returns will say to the client in the TRtcResult object. This event has parameters
Code:
procedure TForm1.resTimerReturn(Sender: TRtcConnection; Data,Result: TRtcValue);

Sender is nil when it returns and enters the event at once while 10 seconds later it enters the event with a valid sender object
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #10 on: May 12, 2017, 04:39:55 PM »

You should check this from the beginning of your log. I think you are seing things in reverse. What happens there is that the event is first called with a vaid Sender parameter, then the PostInteractiveResult function is called to execute the same event outside of the connection context, with Sender=NIL.

Best Regards,
Danijel Tkalcec
Logged
HelgeLange
RTC Expired
*
Posts: 100


« Reply #11 on: May 12, 2017, 04:47:02 PM »

Could be, nevertheless the event with sender=nil I ignore now, but the problem persists. The server posts the call and the client receives instantly with

Result.IsType = rtc_Null

I post again the whole server side RtcFuntion for the delayed call.

Code:
procedure TdmCustomConnectionServer.fctDelayedCallExecute(Sender: TRtcConnection; Param: TRtcFunctionInfo; Result: TRtcValue);
var RData: TRConnectionData;
    RRec, SourceRec : TRtcRecord;
    AD : TConnectionActionData;
    i : Integer;
begin
  if not Sender.inMainThread then
    Sender.Sync(fctDelayedCallExecute, Param, Result)
  else begin
    if not ConnectionList.TryGetValue(Param.asInteger[STR_TAXI_ID], RData) then begin
      {$IFDEF CS5}CodeSite.Send(csmLevel1, 'No ConnectionData found in DelayedCallExecute with ClientId', Param.asInteger[STR_TAXI_ID]);{$ENDIF}
      Result.asBoolean := False;
      Exit;
    end;
     // we mark this session as our delayed call connection
    Sender.Session.asBoolean['bDCC'] := True;
    if ((not Param.asBoolean[STR_IS_DELAYED]) and (RData.FpActionList.Count = 0)) then begin
      Param.asBoolean[STR_IS_DELAYED] := True;
      {$IFDEF CS5} CodeSite.Send(csmLevel4, 'Delaying call for ClientId '+ Param.asString[STR_TAXI_ID] + ' with DelayedCallId', Param.asInteger[STR_MONITOR_ID]); {$ENDIF}
      RData.CB := PrepareDelayedCall(10000, Param, fctDelayedCallExecute);
      PostDelayedCall(RData.CB);
    end else begin
      {$IFDEF CS5} CodeSite.Send(csmLevel4, 'Returning delayed call for ClientId '+ Param.asString[STR_TAXI_ID] + ' with DelayedCallId', Param.asInteger[STR_MONITOR_ID]); {$ENDIF}
      //
      TRtcDataServer(Sender).Session.asInteger['Counter'] := TRtcDataServer(Sender).Session.asInteger['Counter'] + 1;
      //
      RData.CB := nil;

      if RData.FpActionList.Count > 0 then
      begin
        AD := TConnectionActionData(RData.FpActionList.Items[0]);  // we're taking the first action on the stack
        SourceRec := TRtcrecord(AD.ActionData);
        RRec := Result.NewRecord;
        for i := 0 to SourceRec.Count - 1 do begin
          RRec.asValue[SourceRec.FieldName[i]] := SourceRec.asValue[SourceRec.FieldName[i]];
          {$IFDEF CS5} CodeSite.Send(csmLevel4, SourceRec.FieldName[i], SourceRec.asString[SourceRec.FieldName[i]]); {$ENDIF}
        end;

        RData.FpActionList.Delete(0);
        {$IFDEF CS5}
        CodeSite.Send(csmLevel4, 'Returning call with action for ClientId', Param.asInteger[STR_TAXI_ID]);
        CodeSite.Send(csmLevel4, 'ActionId', AD.ActionId);
        CodeSite.SendIf((AD.IncidentId > 0), 'IncidentId', AD.IncidentId);
        {$ENDIF}
        AD.Free;
      end else begin
        {$IFDEF CS5} CodeSite.Send(csmLevel4, 'Returning empty delayed call for TaxiId', Param.asInteger[STR_TAXI_ID]); {$ENDIF}
        RRec := Result.NewRecord;
        RRec.asInteger['Counter'] := Sender.Session.asInteger['Counter'];
        RRec.asInteger[STR_ACTION_ID] := -1;
      end;
    end;
  end;
end;

Since all management of the delayed calls on the server side can be done int he same event, here must be the error, right ?
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #12 on: May 12, 2017, 05:03:05 PM »

You should have posted this code before Tongue

Here is the culprit:

  if not Sender.inMainThread then
    Sender.Sync(fctDelayedCallExecute, Param, Result)
  else begin

What happens here is that the Sync() call executes your event from the Main Thread, where the EDelayedCall exception is being raised and then silently swallowed, never reaching the connection thread.

In a nutshell, I need to update the way the Sync method is working to catch any exceptions raised in the Main Thread and re-raise them in the thread where Sync() is being called, then your code should continue working as before.

Best Regards,
Danijel Tkalcec
Logged
HelgeLange
RTC Expired
*
Posts: 100


« Reply #13 on: May 12, 2017, 05:10:21 PM »

But then it is something you changed, because I installed now the previous version of RTC (7.xx) and it works like before without problems Tongue

So, short question even shorter, I wait for your update or I write a workaround now or use the 7.xx in the meantime ?

thanks Smiley
Helge
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #14 on: May 12, 2017, 05:14:15 PM »

It is a regression bug in RTC SDK v8.0 which I am fixing now. It should be ready within the hour. It's not a big deal. I already know what I need to do, just need to code it and test it.

Best Regards,
Danijel Tkalcec
Logged
Pages: [1] 2
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.028 seconds with 16 queries.