2008-01-11

Обработчики событий.txt

  2008-01-11 19:00

Обработчики событий: Любое действие с объектом в zope, будь то создание, изменение или удаление, порождает события. В Zope могут быть созданы и размещены различные обработчики этих событий, например, вызывающие индексацию объекта во внешних поисковых службах или выполняющие иные дополнительные операции по обработке объекта. ...

Обработчики событий:

Любое действие с объектом в zope, будь то создание, изменение или удаление, порождает события. В Zope могут быть созданы и размещены различные обработчики этих событий, например, вызывающие индексацию объекта во внешних поисковых службах или выполняющие иные дополнительные операции по обработке объекта.

События в zope не носят иерархического характера, т.е. они проходят через единственный общий диспетчер и передаются обработчику события. Если есть необходимость обработать событие с учетом иерархии (например, обработчик события должен обработать все события, происходящие на данном сайте) то необходимо применить какое-то дополнительное решение. Его вариантом может быть создание и регистрация утилиты в локальном сайт менеджере: тогда роль обработчика события сводится к нахождению утилиты в сайт-менеджере, покрывающем данный объект, а уже собственно утилита будет проводить всю обработку.

handler

handler

В качестве примера напишем специальную утилиту, подсчитывающую квоты на размер объектов внутри сайта. Утилиту оформим как отдельный продукт quota: ее можно добавить в локальный сайт-менеджер через веб-интерфейс и зарегистрировать в нем. Кроме того, для того чтобы она нормально работала, там же должна быть зарегистрирована утилита "Unique Id" (Генератор уникальных идентификаторов).

Как нетрудно заметить, quota - это практически обычный контент-объект, содержащий два поля:

size
текущий размер,
quota
квота на суммарный размер объектов,

и снабженную обычным набором формочек для настройки и редактирования.

Для того чтобы считать размеры объектов, продукт quota определяет специальный интерфейс IQuotaSize. Разумеется, ни один из объектов сайта, по умолчанию, такого интерфейса не предоставляет, поэтому для каждого объекта нужно написать специальный адаптер. Пример такого адаптера для продукта Note, можно найти в продукте note2quotasize.

Теперь посмотрим как обрабатываются события и зачем они нужны. Добавление, изменение или удаление любого объекта (не только на сайте, обслуживаемом утилитой quote) приводит к порождению трех событий: IObjectModifiedEvent, IObjectAddedEvent, IObjectRemovedEvent. Утилита quota предоставляет три метода для обслуживания этих событий, но для того, чтобы их вызвать, нужно для каждого события создать специальный обработчик события - диспетчер, задача которого - получить событие, найти ближайшую к породившему его объекту утилиту quota и вызвать соответствующий метод.

quota

quota

Приведем код одного из таких обработчиков события, взятый из quotahandler:

        def handleAdded(object,event) :
            try :
                zapi.getUtility(IQuota, context=object).handleAdded(event.object)  
            except ComponentLookupError :
                pass

Хендлер вызывает функцию getUtility в контексте объекта, породившего событие.

eventzcml

eventzcml

Вот как регистрируется этот обработчик события:

      <subscriber 
        handler=".handle.handleAdded" 
        for="note.note.Note zope.app.container.interfaces.IObjectAddedEvent" />

Обратите внимание, событие IObjectAddedEvent является событием класса ObjectEvent, а потому снабжено объектом, породившим это событие. Для таких событий существует специальный канал событий, который принимает все события класса ObjectEvent и порождает события как пару (объект, событие), которая и улавливается обработчиком события.

Код канала можно посмотреть в zope.component.event.objectEventNotify, а его регистрация как адаптера происходит в zope.app.event.confiigure.

А теперь немного теории. В сущности, обработчик события - это не более чем адаптер. Так называемый "subscribed" адаптер (см:adapter.ru.txt) . Его отличие от обычного адаптера в том, что таких "subscribed" адаптеров может быть несколько для одного и того же списка требуемых и предоставляемых интерфейсов.

eventinteraction

eventinteraction

Еще одна особенность обработчика события - это фабрика, которая не генерирует адаптер, а выполняет всю его работу сама. Поэтому обработчик события не нужно вызывать - его нужно только лишь получить из реестра (обратите внимание на код zope.component.event.objectEventNotify).

Существует функция notify (zope.event.notify), которая делает только одно: получает список всех обработчиков для данного события, или комбинации объектов (интерфейсов) и событий.

Так собственно и работает обслуживание событий: обработчики событий регистрируются, ищутся функцией notify и вызываются. Есть один удобный вариант использования: можно написать канал событий. Канал событий получает одно событие (так же как обычный обработчик события) и генерирует одно или несколько новых событий. Наиболее известный частный случай - вышеупомянутый обработчик события событий, порожденных от ObjectEvent. Возможны и другие аналогичные решения.

События, обработчики и утилиты можно представить как еще один способ связывания разнородных компонент: вместо непосредственного вызова методов-интерфейсов друг друга, компоненты порождают события, в которых передают параметры вызова. Специальный диспетчер (или некая иерархия диспетчеров, образованная обработчиками событий и каналами), доставляет события наиболее подходящему получателю, возможно, перекодируя его. Такой способ программирования настолько же гибок, как и программирование на интерфейсах и адаптерах, тем более что и сама поддержка обработки событий реализована на их основе. Таким образом, события, обработчик событияы и каналы - это не более чем еще один способ работы с компонентной моделью.

Необходимо отметить отсутствие очередей событий, иными словами, отправка события - это синхронный, блокирующий вызов: никакой код не будет выполнен до тех пор, пока обработка события не будет завершена. Исключение, произошедшее во время обработки события, вернется объекту, породившему его.y Хотя АПИ это нигде не оговаривает и, возможно, в дальнейшем ситуация изменится (просто потому что она обычно не такая).

Ссылки на эту статью:

План лекций
Официальный сайт Zope3 Московская группа изучения реактивного движения The Dream Bot Site noooxml