Giter Club home page Giter Club logo

Comments (7)

silvioprog avatar silvioprog commented on July 19, 2024

Hello friend,

Can you send a small project to test it? I'm using Brook fine with multi-threads, but with FastCGI broker. I can test it with embedded server too.

CurrentAction is a useful property used only for non-thread apps. It isn't used internally in Brook.

And what is your operating system?

If this is a bug, I'll fix it ASAP. 👍

from brookframework.

uaply avatar uaply commented on July 19, 2024

Oh, I forgot to mention -- I used a long delay (~10 sec) in TAction.Get() handler to simulate busy activity. Specially crafted for-loop doing nothing 1 billion times will be ok )). To be sure there are two simultaneous requests I used different browsers for connecting - Opera sometimes cheats and do single request for two different tabs if url is the same.

Source is actually identical to brookframework\demos\simple\helloworld\embeddedserver from master branch, the only modifications are .Threaded := true; and delay.

IDE is Lazarus-1.1-42083-fpc-2.7.1-20130714-win32.

from brookframework.

silvioprog avatar silvioprog commented on July 19, 2024

Thank you. I'm working on it right now.

from brookframework.

silvioprog avatar silvioprog commented on July 19, 2024

I forgot to ask. Do you have any idea how to implement this? I'm trying, but it seems a bit complex.

from brookframework.

silvioprog avatar silvioprog commented on July 19, 2024

Fixed (0b45081).

Configure your broker to:

unit Brokers;

(...)
function App: TCustomHTTPApplication;
begin
  Result := BrookApp.Instance as TCustomHTTPApplication;
end;

initialization
  App.Port := 1024; // or your port
  App.Threaded := True;
(...)

I tested it with:

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  BrookAction, sysutils;

type

  { TMyAction1 }

  TMyAction1 = class(TBrookAction)
  public
    procedure Get; override;
  end;

  { TMyAction2 }

  TMyAction2 = class(TBrookAction)
  public
    procedure Get; override;
  end;

implementation

{ TMyAction1 }

procedure TMyAction1.Get;
begin
  Write('Action 1: %s', [FormatDateTime('dd/mm/yyyy hh:nn:ss', Now)]);
  Sleep(1000 * 10); // 10 sec delay
end;

{ TMyAction2 }

procedure TMyAction2.Get;
begin
  Write('Action 2: %s', [FormatDateTime('dd/mm/yyyy hh:nn:ss', Now)]);
end;

initialization
  TMyAction1.Register('/action1');
  TMyAction2.Register('/action2');

end.

Calling fine http://localhost:1024/action1 and http://localhost:1024/action2 simultaneous.

Please test and close this issue if work fine for you! :)

from brookframework.

uaply avatar uaply commented on July 19, 2024

Your fix works under Win32, but not under Linux. Some peculiarities of threads implementation under linux not allow terminating of thread -- it continue running even when Action processing is complete. I am not sure which thread remain running, connection or router. Maybe VThread.WaitFor hangs up - I can't figure out yet.

Anyway, I think creating one more thread specially for router is too much. Separate thread is already created for each connection, so we doesn't want one more thread for router inside this connection - it is just waste of resources. In my case resources are precious - I develop application which would run under embedded linux, with no HDD and minimal memory.

All we need is to create separate instance of TBrookRouter in each thread. Now TBrookRouter.Service() return singleton, so I solved this problem another way - I create separate instance not of TBrookRouter, but of TAction.

Please see my patch.

--- brookrouter0.pas    Tue Jul 16 08:12:36 2013
+++ brookrouter.pas Tue Jul 16 08:37:35 2013
@@ -89,14 +89,14 @@
   { Provides features for the route handling. }
   TBrookRouter = class(TBrookObject)
   private
-    FCurrentAction: TBrookAction;
-    FCurrentRoute: TBrookRoute;
+    //FCurrentAction: TBrookAction;
+    //FCurrentRoute: TBrookRoute;
     FRoutes: TBrookRoutes;
   protected
     function CreateRoutes: TBrookRoutes; virtual;
-    procedure DoCreateAction(out AActionClass: TBrookActionClass); virtual;
-    procedure DoFreeAction; virtual;
-    procedure DoExecuteAction(ARequest: TRequest; AResponse: TResponse;
+    function DoCreateAction(out AActionClass: TBrookActionClass):TBrookAction; virtual;
+    procedure DoFreeAction(AAction:TBrookAction); virtual;
+    procedure DoExecuteAction(AAction:TBrookAction; ARequest: TRequest; AResponse: TResponse;
       ANames, AValues: TBrookArrayOfString); virtual;
   public
     { Creates an instance of a @link(TBrookRouter) class. }
@@ -150,9 +150,9 @@
     { List of available routes. }
     property Routes: TBrookRoutes read FRoutes write FRoutes;
     { The current action. }
-    property CurrentAction: TBrookAction read FCurrentAction;
+    //property CurrentAction: TBrookAction read FCurrentAction;
     { The current route. }
-    property CurrentRoute: TBrookRoute read FCurrentRoute;
+    //property CurrentRoute: TBrookRoute read FCurrentRoute;
   end;

 implementation
@@ -311,24 +311,23 @@
   Result := TBrookRoutes.Create;
 end;

-procedure TBrookRouter.DoCreateAction(out AActionClass: TBrookActionClass);
+function TBrookRouter.DoCreateAction(out AActionClass: TBrookActionClass):TBrookAction;
 begin
-  FreeAndNil(FCurrentAction);
-  FCurrentAction := AActionClass.Create;
+  Result := AActionClass.Create;
 end;

-procedure TBrookRouter.DoFreeAction;
+procedure TBrookRouter.DoFreeAction(AAction:TBrookAction);
 begin
-  FreeAndNil(FCurrentAction);
+  AAction.Free;
 end;

-procedure TBrookRouter.DoExecuteAction(ARequest: TRequest; AResponse: TResponse;
+procedure TBrookRouter.DoExecuteAction(AAction:TBrookAction; ARequest: TRequest; AResponse: TResponse;
   ANames, AValues: TBrookArrayOfString);
 begin
-  FCurrentAction.FillFields(ARequest);
-  FCurrentAction.FillParams(ARequest);
-  FCurrentAction.FillValues(ANames, AValues);
-  FCurrentAction.DoRequest(ARequest, AResponse);
+  AAction.FillFields(ARequest);
+  AAction.FillParams(ARequest);
+  AAction.FillValues(ANames, AValues);
+  AAction.DoRequest(ARequest, AResponse);
 end;

 class procedure TBrookRouter.RegisterService;
@@ -563,6 +562,7 @@
   VActClass: TBrookActionClass = nil;
   VDefaultActClass: TBrookActionClass = nil;
   VRedirect, VMatchMethod, VMatchPattern: Boolean;
+  AAction:TBrookAction;
 begin
   C := FRoutes.List.Count;
   if C = 0 then
@@ -585,7 +585,7 @@
           Continue;
         VMatchMethod := True;
         VActClass := PRoute^.ActionClass;
-        FCurrentRoute := PRoute^;
+        //FCurrentRoute := PRoute^;
         if PRoute^.Method <> rmAll then
           Break;
       end;
@@ -615,7 +615,7 @@
         if VRedirect and Canonicalize(ARequest, AResponse) then
           Exit;
         VActClass := PRoute^.ActionClass;
-        FCurrentRoute := PRoute^;
+        //FCurrentRoute := PRoute^;
         Break;
       end;
     if not Assigned(VActClass) then
@@ -625,10 +625,10 @@
         raise EBrookHTTP404.Create(BROOK_HTTP_REASON_PHRASE_NOT_FOUND);
   end;
   try
-    DoCreateAction(VActClass);
-    DoExecuteAction(ARequest, AResponse, VNames, VValues);
+    AAction := DoCreateAction(VActClass);
+    DoExecuteAction(AAction, ARequest, AResponse, VNames, VValues);
   finally
-    DoFreeAction;
+    DoFreeAction(AAction);
   end;
 end;

It works without applying 0b45081 both on Windows and Linux.

The only thing I am not sure if make TAction as local variable is enough, or maybe TBrookRouter should be also made as local instance inside connection thread.

from brookframework.

silvioprog avatar silvioprog commented on July 19, 2024

Your patch is perfect and fixes the bug! I made few changes before applying it (251d319).

Please send your name to be added in CONTRIBUTORS file (https://github.com/silvioprog/brookframework/blob/master/CONTRIBUTORS.txt).

Thank you very much again and good luck in your project with Brook friend. After, if you follow, we will add it in success cases with Brook! 👍

from brookframework.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.