Dear Graham & al.,

Congratulations for your software and documentation. I have however some 
difficulties as outlined in the subject caption.

I'm building a case study for an application on an intranet within a 
company where the users would interact with their browser communicating 
with the Apache2/mod_wsgi server (daemon mode + multi-threads).

However I'm afraid I'm misunderstanding some important underlying concepts 
of the architecture. Please allow me to give an example and to give you my 
thoughts - which could go wrong somewhere.

*Part 1:*

I wrote a simple HTML page with a one field input form.

In my `environment` dictionary, I have, among other key/value pairs, the 
following:

        REQUEST_METHOD: POST
        REQUEST_URI: /core/my-wsgi-app
        mod_wsgi.callable_object: application

The first two values come obviously from my html <form 
action="core/my-wsgi-app" method="post">...</form>, and the third value is 
the default value in the configuration directive (WSGICallableObject 
application).

In my my-wsgi-app script, I have of course:

        def application (environment, start_response):
               [my code here]
               return [response_body]

So all is fine and works well but there is something I don't get (I mean I 
haven't fully assimilated), certainly in a multi-users, multi-threads, ... 
environment. The main question is about the WSGICallableObject. 

The documentation 
(https://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGICallableObject)
 
says "*The WSGICallableObject directive can be used to override the name of 
the Python callable object in the script file which is used as the entry 
point into the WSGI application.*" [underlining is mine]. For me the WSGI 
application is the whole application: when finished the target application 
I'm case studying could serve one hundred users, delivering thousands of 
pages built dynamically over hundreds of SQL tables, ... Am I right in 
thinking than one entry point would be fit for such purpose. The size of 
the application is such that I already opted for a daemon configuration 
with multi-threads (I do not wish to have users waiting in a single queue 
because one of them is building a page that takes seconds to assemble).

Having one single callable object seems to give me these only 4 options:

1) Have only one single REQUEST_URI, say /core/my-wsgi-app,  where only one 
callable object (function, class, ...) is used under the one and same name 
(application). In such case that callable object is the one and only full 
single entry point to the overall application (thousands of pages built 
dynamically) and I must care for checking, authorisation, parsing, 
dispatching, ... and finally assembling the response and returning it. I'm 
wondering if this single script/callable-object could become a bottleneck. 
It is the concern I've just expressed. Of course, Python can handle 
hundreds of function calls and instance calls. This option makes me doubt I 
fully understand the mechanism. I call this option N to 1.

2) Have various REQUEST_URI (even one per page if need be) and in each 
called script, there would be one callable object with the same name 
("application" as defined in the WSGICallableObject directive). In that 
case, I could create a callable instance of a base class but that instance 
should bear the application name and use the two positional arguments 
passed by mod_wsgi. This option, if used exclusively, seems to me like a 
normal "CGI static serving", i.e. one request activates one script (the 
whole logic and dynamism is in the script). This point too makes me doubt I 
understand the real nature of WSGI. I call this option N to N.

3) One could combine option 1 and 2 to create more dynamism without risking 
the potential (?) bottleneck of option 1 when used alone. I call this 
option N to M (<<N)

4) There seems to be a possibility to define the WSGICallableObject per 
directory. My understanding is that the REQUEST_URI belonging to a 
directory (and its sub-directories) would use that callable object name. 
This means for instance that any URI of the form /core/section-1/abc would 
have a callable object Application_1, while any URI under 
/core/section-N/... would have a callable object Application_N. I haven't 
tried this directive yet so I may misunderstand its role.

This is my overall understanding but I'm afraid I'm missing something 
fundamental [please note that I'm not an English speaker and I might have 
missed subtleties in the documentation which is quite dense]. I tried to 
picture this in a diagram but I'm not sure I got it right:

 M (html requests) -> 1 (http server) -> N x P (mod_wsgi daemons x threads) 
-> X? (Python instance(s) / one per daemon ? I don't know) -> M (calls to 
one object in one URI or to many objects - named the same - in many URI ? ) 
and back to the user via the same route.

I assume that one user html request generates ultimately one call to a 
callable object (give or take) : that's why I use M in toth cases. Is this 
assumption correct ? My dilemma is that I can't understand the spread of 
the load between the 2 extremes: one URI containing the `application` 
callable object (that is eventually called hundreds of times per second) or 
many hundreds URI each containing a callable object named `application` 
that all get called much less frequently.

*Part 2:*

As a consequence of this hazy understanding of mine, I wonder why can't the 
name of the callable object be chosen on demand ?

If I refer to PEP3333 (http://legacy.python.org/dev/peps/pep-3333/) I 
understand that:
 "
*A server or gateway must invoke the application object using positional 
(not keyword) arguments. (E.g. by calling result = application(environ, 
start_response)*"

So my guess is that, still referring to the example at the top, one thread 
in mod_wsgi loads (I wouldn't call this an import) the /core/my-wsgi-app 
script and calls application(environment, start_response) that has been 
defined in it. Is this the correct mechanism ?

Could we imagine that mod_wsgi would sometime call my_App (arg1, arg2), 
some other time call your_App (req, resp) or call Small_app (in, out) where 
my_App, your_App, Small_app would be defined because mod_wsgi would be able 
to set dynamically the WSGICallableObject . Imagine that in the 
WSGIImportScript script file, we would have:

        def my_App (param1, param2):
             [code here]
             return [my_Response]

        def your_App (param1, param2):
             [code here]
             return [your_Response]

        def Small_app (param1, param2):
             [code here]
             return [Small_response]

all the functions would be ready to be called.

I suppose that in any case we are limited:

A)   by the HTTP protocol (URI given via the action attribute, the POST, 
GET, OPTIONS, ... from the method attribute and the key/value pairs from 
the various input fields); and

B)   by directives we could give to configure mod_wsgi. I guess it is not 
the role neither the intend to build some "user logic" within mod_wsgi.

*Conclusions:*

1) Am I correct in my understanding of mod_wsgi as expressed here above 
(Part 1) ? Beware that I could be out of my depth, i.e. talking about 
something I don't properly understand. In that case please correct me or 
complement my view.

2) Do we need to dynamically choose the callable object name for the sake 
of dynamism and multiplicity ?

->  If not, the current set-up is enough. In which case is the preceding 
point ( 1) ) complete and correct ?

->  If yes, how to do it simply and elegantly ?

        => Idea 1: create an extra key/value pair (e.g. 
wsgi_callable_object=my_application). It seems cumbersome to me.

        => Idea 2: if the URI were to have the form 
/core/my-wsgi-app/_my_application then mod_wsgi could provide:
                        REQUEST_URI: /core/my-wsgi-app
                        mod_wsgi.callable_object: my_application
             in the 'environment` dictionary because it would strip the 
trailing part beginning with an underscore provided it is told to do so by 
a directive;
             otherwise it would behave as now and deliver:
                        REQUEST_URI: /core/my-wsgi-app/_my_application
                        mod_wsgi.callable_object: application

*Thanks:*

I do realize this is an unusual post (maybe it should find its way in the 
group working on the documentation) but I would be very happy if some of 
you could answer / feedback to me. In any case I do thank you all in 
advance.

René

-- 
You received this message because you are subscribed to the Google Groups 
"modwsgi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/modwsgi.
For more options, visit https://groups.google.com/d/optout.

Reply via email to