List Info

Thread: Web Site Process Bus




Web Site Process Bus
country flaguser name
United States
2007-06-25 12:57:11
I'd like to continue talking about standardization on
site-wide process
state and services.

As described more fully on my blog [1], I'm proposing we
create a new
spec for a simple publish-subscribe Bus to manage site-wide
state
transitions (start, stop, etc.) and connect application
components with
site-wide services (daemonize, autoreload, site logging,
etc).

This would NOT be a daemon, nor would it introduce any
dependencies. It
would simply say that the main program (be it a framework
entry point,
or Apache, or a user script) creates a Bus object according
to the spec,
and then gives a reference to that Bus object to all
participating
components that care about it.

The blog post might seem like I have a finished candidate
for this; far
from it. This should be a collaborative effort, and I'm very
open to
discussion at all levels of detail. Even if this flies at
the highest
conceptual level, there are still several things I know of
we would need
to nail down:

 * States. For example, do we need an EXITING state? If so,
we should
probably rename STOPPED to IDLE.
 * State transitions: do we need to lock or block which Bus
methods can
be called, depending on the current state?
 * Standard non-state channels, such as signals. Do we want
a 'status'
channel (for e.g. zdaemon)?
 * Should bus.log take other args, like 'severity'? Should
it assume a
stdlib logging API?
 * Should bus.log be replaced with separate stdout and
stderr instead?
 * ...and just to introduce a bikeshed, is there a better
name for the
spec effort than "WSPB"?

I have lots of other questions, but I'll let you all ask
them.


Robert Brewer
System Architect
Amor Ministries
fumanchuamor.org

[1]
http://www.aminus.org/blogs/index.php/fu
manchu/2007/06/24/web_site_proce
ss_bus
_______________________________________________
Web-SIG mailing list
Web-SIGpython.org
Web SIG: http://www.python.
org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/bo
nd%40yahoo.com

Re: Web Site Process Bus
country flaguser name
United States
2007-06-25 13:50:52
At 10:57 AM 6/25/2007 -0700, Robert Brewer wrote:
>This should be a collaborative effort, and I'm very open
to
>discussion at all levels of detail. Even if this flies
at the highest
>conceptual level, there are still several things I know
of we would need
>to nail down:
>
>  * States. For example, do we need an EXITING state? If
so, we should
>probably rename STOPPED to IDLE.
>  * State transitions: do we need to lock or block which
Bus methods can
>be called, depending on the current state?
>  * Standard non-state channels, such as signals. Do we
want a 'status'
>channel (for e.g. zdaemon)?
>  * Should bus.log take other args, like 'severity'?
Should it assume a
>stdlib logging API?
>  * Should bus.log be replaced with separate stdout and
stderr instead?
>  * ...and just to introduce a bikeshed, is there a
better name for the
>spec effort than "WSPB"?
>
>I have lots of other questions, but I'll let you all ask
them.

I have some more basic questions...  like, how do you know
you need 
to subscribe in the first place?  Who does the subscribing?

My initial reaction is that I like the general idea, but the
idea of 
having a bus *object* seems wrong to me somehow.  Perhaps
because the 
only way to get it seems to be in an already-running
application, 
which seems to sort of defeat the purpose.  But maybe my
purposes are 
different than yours?

Perhaps if you could present some example scenarios to show
how you 
see this actually being used...?

_______________________________________________
Web-SIG mailing list
Web-SIGpython.org
Web SIG: http://www.python.
org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/bo
nd%40yahoo.com

Re: Web Site Process Bus
country flaguser name
United States
2007-06-25 14:28:22
Phillip J. Eby wrote:
> At 10:57 AM 6/25/2007 -0700, Robert Brewer wrote:
>> This should be a collaborative effort, and I'm very
open to
>> discussion at all levels of detail. Even if this
flies at the highest
>> conceptual level, there are still several things I
know of we would need
>> to nail down:
>>
>>  * States. For example, do we need an EXITING
state? If so, we should
>> probably rename STOPPED to IDLE.
>>  * State transitions: do we need to lock or block
which Bus methods can
>> be called, depending on the current state?
>>  * Standard non-state channels, such as signals. Do
we want a 'status'
>> channel (for e.g. zdaemon)?
>>  * Should bus.log take other args, like 'severity'?
Should it assume a
>> stdlib logging API?
>>  * Should bus.log be replaced with separate stdout
and stderr instead?
>>  * ...and just to introduce a bikeshed, is there a
better name for the
>> spec effort than "WSPB"?
>>
>> I have lots of other questions, but I'll let you
all ask them.
> 
> I have some more basic questions...  like, how do you
know you need 
> to subscribe in the first place?  Who does the
subscribing?
> 
> My initial reaction is that I like the general idea,
but the idea of 
> having a bus *object* seems wrong to me somehow. 
Perhaps because the 
> only way to get it seems to be in an already-running
application, 
> which seems to sort of defeat the purpose.  But maybe
my purposes are 
> different than yours?
> 
> Perhaps if you could present some example scenarios to
show how you 
> see this actually being used...?

I'm also confused about what this is about.  Or maybe it
feels like it's 
about more than one thing, and needn't be.  The blog post
kind of helps 
and also kind of confuses things.

For instance, doesn't atexit work fine for exiting?  (Not in
mod_python, 
but I still don't know why it *shouldn't* work in
mod_python.)  Of 
course, there isn't anything for other signals, and creating
something 
for those would be quite useful.  Potentially a Zope-style
minimal event 
framework would work.  Maybe something like:

   send_signal(signal_name, signal_data)
   subscribe(signal_name, listener)

Where in the second case, listener(signal_name, signal_data)
is called, 
and signal_name can be used to automatically filter, or None
to receive 
all signals.  I prefer strings for the names, because then
there's no 
dependencies (you don't have to import anything, you just
have to have 
packages agree on names).  I think Zope doesn't have any
high-level 
filtering (?) and generally uses interfaces for filtering in
the 
listener itself.

Anyway, given that we still would need to define the signals
we care 
about in the web context, but it's not too terrible hard I
think.

Maybe the "bus" you are talking about that is
registered is the 
thing-that-sends-signals?  I think it can simply be a single

module/library that we all agree to use.

Anyway, this mostly seems like what you are describing.  I
guess when 
viewed as an event publishing system, there's other concerns
that pop up 
-- can you cancel the event?  (Ugh, I don't think so; I
think GUI events 
and signals are something fairly different from what we're
talking about 
here).  Also, should exceptions propagate?  I feel vaguely
like they 
should, but I'm not sure.

-- 
Ian Bicking | ianbcolorstudy.com | http://blog.ianbicking.org

             | Write code, do good | http://topp.openpla
ns.org/careers
_______________________________________________
Web-SIG mailing list
Web-SIGpython.org
Web SIG: http://www.python.
org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/bo
nd%40yahoo.com

Re: Web Site Process Bus
country flaguser name
United States
2007-06-25 14:43:19
Robert Brewer wrote:
> I'd like to continue talking about standardization on
site-wide process
> state and services.

Perhaps zope.event would be a good fit. 
http://svn.zope.org/zope.event/trunk/s
rc/zope/event/README.txt?view=markup
-- 
Benji York
http://benjiyork.com
_______________________________________________
Web-SIG mailing list
Web-SIGpython.org
Web SIG: http://www.python.
org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/bo
nd%40yahoo.com

Re: Web Site Process Bus
country flaguser name
United States
2007-06-25 15:18:05
At 02:28 PM 6/25/2007 -0500, Ian Bicking wrote:
>Potentially a Zope-style minimal event framework would
work.  Maybe 
>something like:
>
>   send_signal(signal_name, signal_data)
>   subscribe(signal_name, listener)

That was what I was wondering, too, except I was thinking it
would be 
sufficient to use entry points for subscription, but only
invoke the 
entry points whose modules are in sys.modules.  In other
words, never 
actually import a module in order to invoke a callback. 
That way, 
subscription is a natural side effect of importing the
modules that 
contain the listeners.  Something like:

def send_signal(group, name, *args, **kw):
     for ep in iter_entry_points(group, name):
         if ep.module_name in sys.modules:
             ep.load()(*args, **kw)

would then be sufficient.  pkg_resources is currently
proposed for 
inclusion in Python 2.6 (per PEP 365), so there wouldn't
even be any 
non-stdlib requirements then.  And of course the
implementation is 
trivial enough to copy into any code that wants to send
signals.

Of course, if you want prioritized callbacks, you can always
sort the 
ep.load() results using a priority attribute or some such. 
I'm not 
sure priority makes much sense, though, due to the
difficulty of 
determining a global priority scheme.

_______________________________________________
Web-SIG mailing list
Web-SIGpython.org
Web SIG: http://www.python.
org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/bo
nd%40yahoo.com

Re: Web Site Process Bus
country flaguser name
United States
2007-06-25 16:42:16
Phillip J. Eby wrote:
> At 02:28 PM 6/25/2007 -0500, Ian Bicking wrote:
>> Potentially a Zope-style minimal event framework
would work.  Maybe 
>> something like:
>>
>>   send_signal(signal_name, signal_data)
>>   subscribe(signal_name, listener)
> 
> That was what I was wondering, too, except I was
thinking it would be 
> sufficient to use entry points for subscription, but
only invoke the 
> entry points whose modules are in sys.modules.  In
other words, never 
> actually import a module in order to invoke a callback.
 That way, 
> subscription is a natural side effect of importing the
modules that 
> contain the listeners.  Something like:
> 
> def send_signal(group, name, *args, **kw):
>     for ep in iter_entry_points(group, name):
>         if ep.module_name in sys.modules:
>             ep.load()(*args, **kw)

I don't think that makes sense for this case.  The way I
imagine using 
it is:

class MyApplication(object):

     def __init__(self, db):
         self.db = db
         subscribe('reload_resources', self.reload)
     def reload(self, data=None):
         self.db.close()
         self.db.open()

That is, I subscribe one particular thing when it is
applicable, not 
because the library is on the system.


-- 
Ian Bicking | ianbcolorstudy.com | http://blog.ianbicking.org

             | Write code, do good | http://topp.openpla
ns.org/careers
_______________________________________________
Web-SIG mailing list
Web-SIGpython.org
Web SIG: http://www.python.
org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/bo
nd%40yahoo.com

Re: Web Site Process Bus
country flaguser name
United States
2007-06-25 16:52:13
At 04:42 PM 6/25/2007 -0500, Ian Bicking wrote:
>Phillip J. Eby wrote:
>>At 02:28 PM 6/25/2007 -0500, Ian Bicking wrote:
>>>Potentially a Zope-style minimal event framework
would 
>>>work.  Maybe something like:
>>>
>>>   send_signal(signal_name, signal_data)
>>>   subscribe(signal_name, listener)
>>That was what I was wondering, too, except I was
thinking it would 
>>be sufficient to use entry points for subscription,
but only invoke 
>>the entry points whose modules are in sys.modules. 
In other words, 
>>never actually import a module in order to invoke a
callback.  That 
>>way, subscription is a natural side effect of
importing the modules 
>>that contain the listeners.  Something like:
>>def send_signal(group, name, *args, **kw):
>>     for ep in iter_entry_points(group, name):
>>         if ep.module_name in sys.modules:
>>             ep.load()(*args, **kw)
>
>I don't think that makes sense for this case.  The way I
imagine using it is:
>
>class MyApplication(object):
>
>     def __init__(self, db):
>         self.db = db
>         subscribe('reload_resources', self.reload)
>     def reload(self, data=None):
>         self.db.close()
>         self.db.open()


I guess I wasn't clear.  The point is that the approach I'm

suggesting allows event subscribers to be decoupled.  A
library could 
have an "on_reload" function, for example, that
references a 
library-specific event system.  Some frameworks, after all,
are going 
to have their own event systems.

So a bridge from the bus to zope.event, for example, could
just 
create objects and notify() them, and frameworks that are
okay with 
depending on zope.event can use that.


>That is, I subscribe one particular thing when it is
applicable, not 
>because the library is on the system.

That's why the code I suggested only invokes entry points
that are 
*already imported* -- i.e., that someone is using. 

_______________________________________________
Web-SIG mailing list
Web-SIGpython.org
Web SIG: http://www.python.
org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/bo
nd%40yahoo.com

Re: Web Site Process Bus
country flaguser name
United States
2007-06-25 17:00:43
Phillip J. Eby wrote:
> At 04:42 PM 6/25/2007 -0500, Ian Bicking wrote:
>> Phillip J. Eby wrote:
>>> At 02:28 PM 6/25/2007 -0500, Ian Bicking
wrote:
>>>> Potentially a Zope-style minimal event
framework would work.  Maybe 
>>>> something like:
>>>>
>>>>   send_signal(signal_name, signal_data)
>>>>   subscribe(signal_name, listener)
>>> That was what I was wondering, too, except I
was thinking it would be 
>>> sufficient to use entry points for
subscription, but only invoke the 
>>> entry points whose modules are in sys.modules. 
In other words, never 
>>> actually import a module in order to invoke a
callback.  That way, 
>>> subscription is a natural side effect of
importing the modules that 
>>> contain the listeners.  Something like:
>>> def send_signal(group, name, *args, **kw):
>>>     for ep in iter_entry_points(group, name):
>>>         if ep.module_name in sys.modules:
>>>             ep.load()(*args, **kw)
>>
>> I don't think that makes sense for this case.  The
way I imagine using 
>> it is:
>>
>> class MyApplication(object):
>>
>>     def __init__(self, db):
>>         self.db = db
>>         subscribe('reload_resources', self.reload)
>>     def reload(self, data=None):
>>         self.db.close()
>>         self.db.open()
> 
> 
> I guess I wasn't clear.  The point is that the approach
I'm suggesting 
> allows event subscribers to be decoupled.  A library
could have an 
> "on_reload" function, for example, that
references a library-specific 
> event system.  Some frameworks, after all, are going to
have their own 
> event systems.
> 
> So a bridge from the bus to zope.event, for example,
could just create 
> objects and notify() them, and frameworks that are okay
with depending 
> on zope.event can use that.

I think it's just using pkg_resources functionality so that
you don't 
need a common thing to subscribe to.  Which I guess is
exactly why 
Robert wants this idea of different buses instead of a
single bus; 
though it's vague to me how you plug the buses and listeners
and whatnot 
together without some common code or place to put objects
(entry points 
being one possibility, a single module with these functions
another).  I 
guess you could have an entry point that indicates objects
that want to 
know about any buses that are created.  It seems like a lot
of 
indirection, though.

>> That is, I subscribe one particular thing when it
is applicable, not 
>> because the library is on the system.
> 
> That's why the code I suggested only invokes entry
points that are 
> *already imported* -- i.e., that someone is using.

Just because the module is imported doesn't mean that every
case in the 
module exists.  E.g., in my example only on the
instantiation of 
MyApplication would I listen for the event.

This means that the subscription has to be done even if no
one emits the 
signal.  Which is possible if you start listening for lots
of different 
things because we can't agree on names and you want to
support lots of 
systems.  But I don't think that's going to happen.


-- 
Ian Bicking | ianbcolorstudy.com | http://blog.ianbicking.org

             | Write code, do good | http://topp.openpla
ns.org/careers
_______________________________________________
Web-SIG mailing list
Web-SIGpython.org
Web SIG: http://www.python.
org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/bo
nd%40yahoo.com

Re: Web Site Process Bus
user name
2007-06-25 17:53:28
On 26/06/07, Ian Bicking <ianbcolorstudy.com> wrote:
> For instance, doesn't atexit work fine for exiting? 
(Not in mod_python,
> but I still don't know why it *shouldn't* work in
mod_python.)

Exit functions registered by atexit don't work in mod_python
for a few reasons.

First off is that if you call Py_Finalize() then Python only
calls
exit functions on the main Python interpreter and does not
do it on
sub interpreters. Since code running under mod_python tends
to run in
sub interpreters, any atexit registered functions would
never be
called.

The second problem is that calling Py_Finalize() was
disabled in more
recent versions of mod_python as it was causing lots of
problems with
strange Python exceptions and sometimes crashes occurring
when
triggered.

In mod_wsgi I managed to work out what all the problems were
and in
mod_wsgi it will correctly call atexit registered functions
registered
in all sub interpreters as well as call Py_Finalize() to
clean up
other stuff related to any interpreters which were created.
The
changes in mod_wsgi even deal with changes made in Python
2.5 with how
threads are killed off on killing a sub interpreter. Prior
to 2.5 this
was managed by an atexit registered function from threading
module
itself, but in 2.5 the Python C code itself triggers the
cleanup
actions for threads.

Going back and fixing all this in mod_python is right down
at the end
of the reopened issue for Py_Finalize() causing problems in
the first
place.

  h
ttps://issues.apache.org/jira/browse/MODPYTHON-109

All the code in mod_python for Python initialisation and
shutdown,
plus interpreter management really needs to be completely
rewritten as
it is messy and still has bugs in there related to
simplified GIL API,
something which has again been fixed up in mod_wsgi.

Graham
_______________________________________________
Web-SIG mailing list
Web-SIGpython.org
Web SIG: http://www.python.
org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/bo
nd%40yahoo.com

Re: Web Site Process Bus
user name
2007-06-25 21:48:47
On 26/06/07, Robert Brewer <fumanchuamor.org> wrote:
> I'd like to continue talking about standardization on
site-wide process
> state and services.
>
> As described more fully on my blog [1], I'm proposing
we create a new
> spec for a simple publish-subscribe Bus to manage
site-wide state
> transitions (start, stop, etc.) and connect application
components with
> site-wide services (daemonize, autoreload, site
logging, etc).

I'm a bit too busy to fully absorb all that is being said on
this
topic, but have a few comments or observations to make based
on my
experiences. If they relate to anything, it is possibly just
to expand
on some of the issues around why a bus might be a
reasonable
requirement to have so hopefully it is of use in that
respect.

First comment is about WSGI applications somehow themselves
using
SIGTERM etc as triggers for things they want to do. For
Apache at
least, allowing any part of a hosted Python application to
register
its own signal handlers is a big no no. This is because
Apache itself
uses a whole range of signals to manage such tasks as
shutting down
sub processes or signaling worker and/or listener threads
within a
process that its time to wakeup or shutdown. If a WSGI
application
starts registering signal handlers it can as a result stop
Apache from
even being able to process requests. In mod_wsgi I have had
to
specifically take steps to prevent applications breaking
things in
this way by replacing signal.signal() on creation of an
interpreter.
Instead I log a warning that the signal registration has
been ignored
and otherwise do nothing. This was simply the safest thing
to do.

Thus I believe a clear statement should be made that UNIX
signals are
off limits to WSGI applications or components. I have no
problem with
the underlying server upon which the WSGI adapter sits using
them for
its own purposes, however, knowledge of signals should stay
in that
layer. Now it may be the case that a higher level
application signal
may be generated as a result of a SIGTERM in a specific
server
implementation, for example shutdown, but the name or type
of signal
does have to be distinct, ie., "shutdown" and have
no linkage to the
UNIX signal.

In Apache for example, SIGTERM isn't used in child processes
to
indicate process shutdown, that is instead signalled  via
what is
called the pipe of death. The trigger for process shutdown
in this
case is actually the destruction of the child process memory
pool.

I know that Robert's diagram shows the translation of UNIX
signal at a
lower level to higher level concept, but then elsewhere
there was
mention of SIGUSR signals. Apache even uses these in some
configurations so a hosted user application wouldn't even be
able to
use them.

Anyway, just wanted to make it absolutely clear that I don't
believe a
hosted WSGI application and associated framework has any
business
taking direct interest in low level UNIX signals.

Next issue was SystemExit exception, raised explicitly or
via
sys.exit(), and the ability of a WSGI application to itself
shutdown
the server. Again, shutting down the server using SystemExit
is
something I see as being off limits to a WSGI application.
In mod_wsgi
I explicitly ignore SystemExit raised by a WSGI application
when
handling a request, more or less treating it like any other
unexpected
exception. This is necessary because within Apache one can't
 tolerate
one application making a decision to shutdown a process
because of the
impacts it may have on other application code, possibly non
Python
code, running in the same process.

For a Python based web server, also believe that SystemExit
in a
request handler should be ignored. Obviously though the
underlying
server itself is free to use its for its own purpose. I
actually don't
know what other WSGI adapters do about SystemExit, so would
be
interested to learn what others do.

One thing I have sometimes thought about though is whether
there is
any valid case where a WSGI application should itself be
allowed to
request the application be shutdown. I think I'd probably
have to say
no for the general case. But then you have the case of
trying to
reload an application when the code changes. In this case it
may be
reasonable because no in process module reloading scheme is
ever going
to be good enough. The closest one can get doing it in
process is to
destroy the whole sub interpreter. This though is only a
practical
thing for something like mod_wsgi and even then doesn't
always work
because of C extension modules, eg PyProtocols, that don't
take kindly
to sub interpreters being destroyed and the module then
being reloaded
into a new sub interpreter.

Thus, purely to make administration easier for the WSGI
application to
request an application reload, perhaps triggered by user
through a web
page, one might want to signal process shutdown. Even then
though it
isn't that simple as that, as there has to be a compatible
supervisor
system in place which will restart the process. In mod_wsgi
if using
it in embedded mode whereby application runs in Apache
child
processes, an application requesting a reload like this is
not viable
as not possible to tell the Apache parent process to
restart
everything.

Even when using daemon mode of mod_wsgi where application
runs in
separate processes, only the simple case where there is one
daemon
process for that application is it trivial to initiate a
reload. When
there are multiple processes in the group, need to somehow
signal the
other processes in the group to also reload.

So that is my brain dump. I guess I'll see where you guys
take the
discussion. At the moment I am guarded as to whether some of
the ideas
of how this bus could be used would in practice be
transferable.
Certainly with Apache it may be quite challenging because of
the
multiprocess nature of the server and the fact that child
processes
don't really have any way of controlling the supervisor
(parent Apache
process).

Graham
_______________________________________________
Web-SIG mailing list
Web-SIGpython.org
Web SIG: http://www.python.
org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/bo
nd%40yahoo.com

[1-10] [11-14]

about | contact  Other archives ( Real Estate discussion Medical topics )