Package: event-people
EventPeopleEventPeople is a tool to simplify the communication of event based services. It is an based on theEventBusgem.The main idea is to provide a tool that can emit or consume events based on its names, the event name has 4 words (resource.origin.action.destination) which defines some important info about what kind of event it is, where it comes from and who is eligible to consume it:resource:Defines which resource this event is related like auser, aproduct,companyor anything that you want;origin:Defines the name of the system which emitted the event;action:What action is made on the resource likecreate,delete,update, etc. PS:It is recommended to use the Simple Present tense for actions;destination (Optional):This word is optional and if not provided EventPeople will add a.allto the end of the event name. It defines which service should consume the event being emitted, so if it is defined and there is a service whith the given name only this service will receive it. It is very helpful when you need to re-emit some events. Also if it is.allall services will receive it.As of today EventPeople uses RabbitMQ as its datasource, but there are plans to add support for other Brokers in the future.InstallationAdd this line to your project'srequirements.txtfile:event_people>=0.0.3And then executepython-mpipinstall-rrequirements.txtOr install it with:python-mpipinstallevent_peopleAnd set env vars:exportRABBIT_URL='amqp://guest:guest@localhost:5672'exportRABBIT_EVENT_PEOPLE_APP_NAME='service_name'exportRABBIT_EVENT_PEOPLE_VHOST='event_people'exportRABBIT_EVENT_PEOPLE_TOPIC_NAME='event_people'UsageEventsThe main component ofEventPeopleis theEventclass which wraps all the logic of an event and whenever you receive or want to send an event you will use it.It has 2 attributesnameandpayload:name:The name must follow our conventions, being it 3 (resource.origin.action) or 4 words (resource.origin.action.destination);payload:It is the body of the massage, it should be a Hash object for simplicity and flexibility.fromevent_peopleimportEventfromevent_peopleimportEmittername='user.users.create'body={id:42,name:'John Doe',age:35}event=Event(name,body)There are 3 main interfaces to useEventPeopleon your project:Callingevent_people.Emitter.trigger(event)inside your project;Callingevent_people.Listener.on(event_name)inside your project;Or extendingevent_people.ListenersBaseand use it as a daemon.Using the EmitterYou can emit events on your project passing anevent_people.event.Eventinstance to theevent_people.emitter.triggermethod. Doing this other services that are subscribed to these events will receive it.fromevent_peopleimportEventfromevent_peopleimportEmitterevent_name='receipt.payments.pay.users'body={amount:350.76}event=Event(event_name,body)Emitter.trigger(event)See more detailsListenersYou can subscribe to events based on patterns for the event names you want to consume or you can use the full name of the event to consume single events.We follow the RabbitMQ pattern matching model, so given each word of the event name is separated by a dot (.), you can use the following symbols:* (star):to match exactly one word. Exampleresource.*.*.all;# (hash):to match zero or more words. Exampleresource.#.all.Other important aspect of event consumming is the result of the processing we provide 3 methods so you can inform the Broker what to do with the event next:success!:should be called when the event was processed successfuly and the can be discarded;fail!:should be called when an error ocurred processing the event and the message should be requeued;reject!:should be called whenever a message should be discarded without being processed.Given you want to consume a single event inside your project you can use theevent_people.Listener.onmethod. It consumes a single event, given there are events available to be consumed with the given name pattern.fromevent_peopleimportListenerfromevent_peopleimportEventdefcallback_method(event,context):print("")print("  - Received the%rmessage from%r:",event.name,event.origin)print("     Message:%r",event.body)print("")context.success()event_name='resource.origin.action.all'Listener.on(event_name,callback_method)See more detailsYou can also receive all available messages using a loop:fromevent_peopleimportListenerfromevent_peopleimportEventhas_events=truedefcallback_method(event,context):has_events=trueprint("")print("  - Received the%rmessage from%r:",event.name,event.origin)print("     Message:%r",event.body)print("")context.success()event_name='resource.origin.action.all'while(has_events):has_events=falseListener.on(event_name,callback_method)Multiple events routingIf your project needs to handle lots of events you can extendeventPeople.ListenersBaseclass to bind how many events you need to instance methods, so whenever an event is received the method will be called automatically.fromevent_peopleimportListenersBasefromevent_peopleimportEventclassCustomEventListener(Base):self.bind('resource.custom.pay',self.pay)self.bind('resource.custom.receive',self.receive)self.bind('resource.custom.private.service',self.private_channel)defpay(event):print("Paid%rfor%r~>%r",event.body['amount'],event.body['name'],event.name)self.success()defreceive(event):if(event.body.amount>500):print("Received%rfrom%r~>%r",event.body['amount'],event.body['name'],event.name)else:print("[consumer] Got SKIPPED message")returnself.reject()self.success();defprivate_channel(event):print("[consumer] Got a private message:\"%r\"~>%r",event.body['message'],event.name)self.success();See more detailsCreating a DaemonIf you have the need to create a deamon to consume messages on background you can use theeventPeople.Daemon.startmethod to do so with ease. Just remember to define or import all the event bindings before starting the daemon.fromevent_peopleimportDaemonfromevent_peopleimportBaseListenerclassCustomEventListener(BaseListener):defpay(self,event):print(f"Paid{event.body['amount']}for{event.body['name']}~>{event.name}")self.success()defreceive(self,event):ifevent.body['amount']>500:print(f"Received{event.body['amount']}from{event.body['name']}~>{event.name}")else:print('[consumer] Got SKIPPED message')returnself.reject()self.success()defprivate_channel(self,event):print(f"[consumer] Got a private message:\"{event.body['message']}\"~>{event.name}")self.success()defignore_me(self,event):print(f"This should never be called...")print(f"Spying on other systems:\"{event.body['message']}\"~>{event.name}")self.success()CustomEventListener.bind_event('resource.*.pay','pay')CustomEventListener.bind_event('resource.custom.receive','receive')CustomEventListener.bind_event('resource.custom.private.service_name','private_channel')CustomEventListener.bind_event('resource.custom.ignored.other_service','ignore_me')CustomEventListener.bind_event('resource.custom.pay.all','receive')print('****************** Daemon Ready ******************');Daemon.start()See more detailsDevelopmentAfter checking out the repo, runbin/setupto install dependencies. Then, runbin/testto run the tests.To install this package onto your local machine, runpython -m pip install -e ..ContributingFork itCreate your feature branch (git checkout -b my-new-feature)Commit your changes (git commit -am 'Add some feature')Push to the branch (git push origin my-new-feature)Create new Pull RequestLicenseThe package is available as open source under the terms of theLGPL 3.0 License.