Google

<previous | contents | next> Pyro Manual

11. Pyro Services

This chapter describes the various services that Pyro offers.

Name Server

The Name Server is such an important service that it is documented in a separate chapter.

Event Service

In various situations it is needed that the servers and the clients are decoupled. In abstract terms this means that information producers do not know nor care about the parties that are interested in the information, and the information consumers do not know nor care about the source or sources of the information. All they know is that they produce or consume information on a certain subject.

Here does the Event Service fit in nicely. It is a third party that controls the flow of information about certain subjects ("events"). A publisher uses the Event Service to publish a message on a specific subject. A subscriber uses the Event Service to subscribe itself to specific subjects, or to a pattern that matches certain subjects. As soon as new information on a subject is produced (an "event" occurs) all subscribers for this subject receive the information. Nobody knows (and cares) about anybody else.

It is important to rembember that all events processed by the ES are transient, which means they are not stored. If there is no listener, all events disappear in the void. The store-and-forward programming model is part of a messaging service, which is not what the ES is meant to do. It is also important to know that all subscription data is transient. Once the ES is stopped, all subscriptions are lost. The clients that are subscribed are not notified of this! If no care is taken, they keep on waiting forever for events to occur, because the ES doesn't know about them anymore!

Usually your subscribers will receive the events in the order they are published. However, this is not guaranteed. If you rely on the exact order of receiving events, you must add some logic to check this (possibly by examining the event's timestamps). The chance of events not arriving in the order they were published is very, very small in a high-performance LAN. Only on very high server load, high network traffic, or a high-latency (WAN?) connection it is likely to occur.

Another thing to pay attention to is that the ES does not guarantee delivery of events. As mentioned above, the ES does not have a store-and-forward mechanism, but even if everything is up and running, the ES does not enhance Pyro's way of transporting messages. This means that it's still possible (perhaps due to a network error) that an event gets lost. For reliable, guaranteed, asynchronous message delivery you'll have to look somewhere else, sorry ;-)

The Event Service is a multithreaded server (if threads are available). Publications are dispatched to the subscribers in different threads, so they don't block eachother. Note that you can still use the Event Server if your Python implementation doesn't support threads. Also notice that events may arrive at your listener in multithreaded fashion! Pyro itself starts another thread in your listener to handle the new event, possibly while the previous one is still being handled. If you can't handle this, you have to use some form of thread locking in your client! (see the threading module on Semaphore).

Starting the Event Service

The Event Service is started using the es command from the bin directory (use es.bat on windows). You can specify the following arguments:
-n hostname
Change the hostname/ip address the server binds on. Useful with multiple network adapters.
-h port
Change the port number the server uses.
-i identification
Specify the authentication passphrase that will be required to connect to this server. If it contains spaces, use quotes around the string. The same identification is also used to connect to other Pyro servers such as the Name Server. (this is required ofcourse when the Name Server has been started with the -i option).
-h
Print help.

A new utility is planned that is a more generic service manager. You'll be able to start, stop and configure the various services, including the Name Server.

If you want to start the ES from within your own program, you can ofcourse start it by executing the start script mentioned above. You could also use the EventServiceStarter class from the Pyro.EventService.Server module to start it directly (this is what the script eventually does). Be sure to start it in a separate process or thread because it will run in its own endless loop.

Using the Event Service

The Event Service is a regular Pyro object. Its name is available in Pyro.constants.EVENTSERVER_NAME. The subjects are case insensitive. The patterns are matched case insensitive too. Your clients (subscribers) need to call the Pyro daemon's handleRequests or requestLoop (just like a server), because they receive Pyro calls, namely, the Event Service callbacks when a relevant event happened!

A base implementation of a Publisher and a Subscriber is available in Pyro.EventService.Clients, to help you get started.

Note that the code below assumes you're talking directly to the Event Service, and that you have it in a proxy object callled ES.

Publishing information
Just call the publish method: ES.publish(subjects, message) where subjects is a subject name or a sequence of one or more subject names (strings), and message is the actual message. The message can be any Python object.
Subscribing to receive information
Create a subscriber object, which must be a Pyro object (or use delegation). So your subscriber program should not only act as a Pyro client, but also as a Pyro server, to receive subscription events. The subscriber object should have a event(self, event) method. This method is called by the Event Service. event is a Pyro.EventService.Event object, which has the following properties:
msgthe actual message. Can be any Python object.
subjectthe subject string.
timethe event's timestamp.
Note again that this method can be called in a multithreaded fashion as soon as a new event arrives! See above.

Your subscriber will receive all events that are published on the relevant subjects. If your subscriber is slow, a backlog will build up. You still get all events (with the original timestamp - so you could skip events that "have expired" to catch up). Currently there is no way around this. In a future version it might be possible to specify maximum backlog length.

The multithreading of the event method can be controlled using the setThreading(threading) method. If you pass 0 or None, the threading will be switched off (it is on by default unless otherwise configured). Your events will then arrive purely sequentially, after processing each event. Call this method before entering the requestLoop or handleRequests.

To subscribe, call the subscribe method: ES.subscribe(subjects, subscriber) where subjects is a subject name or a sequence of one or more subject names (strings), and subscriber is a proxy for your subscriber object.

Pattern matching subjects: To subscribe on a pattern that matches a range of subjects, call the subscribeMatch method: ES.subscribeMatch(subjectPatterns, subscriber) , where subjectPatterns is a subject pattern or a sequence of one or more subject patterns (strings), and subscriber is a proxy for your subscriber object. The patterns are standard re-regex expressions. See the standard re module for more information.
The pattern '^STOCKQUOTE\\.S.*$' matches STOCKQUOTE.SUN, STOCKQUOTE.SAP but not STOCKQUOTE.IBM, NYSE.STOCKQUOTE.SUN etcetera.

Repeating it once more: the subjects are case insensitive. The patterns are matched case insensitive too.

To unsubscribe, call the unsubscribe method: ES.unsubscribe(subjects, subscriber) . This will remove the subscriber from the subscription list and also from the pattern match list if the subject occurs as a pattern there.

Using the skeleton Publisher and Subscriber code
For the impatient, have a look at the "stockquote" example. This example is based on the skeleton code that comes with the Event Service. There are two classes that you can subclass from:
  • Pyro.EventService.Clients.Publisher
    Subclass your event publishers from this class. The init takes care of locating the Event Service, and you can just call the publish(subjects, message) method of yourself. No Event Service proxy code needed.
  • Pyro.EventService.Clients.Subscriber
    Subclass your event listeners (subscribers) from this class. The init takes care of locating the Event Service, and you can just call the subscribe(subjects), subscribeMatch(subjectPatterns) and unsubscribe(subjects) methods of yourself. No Event Service proxy code needed. This base class also starts a Pyro daemon and by calling listen(), your code starts listening on incoming events.

    When you want to abort the event loop, you have to call self.abort().

Using authentication passphrase: the __init__ of both the Publisher and the Subscriber takes an optional ident argument. Use this to specify the authentication passphrase that will be used to connect to the Event Server (and also to connect to the Name Server).

Example

To see how you use the Event Service, have a look at the "stockquotes" and "countingcars" examples. Also have a look at the client skeleton code that comes with the Event Service.
<previous | contents | next> Pyro Manual